RFR: 8254078: DataOutputStream is very slow post-disabling of Biased Locking

Andrew Haley aph at openjdk.java.net
Wed Oct 7 13:40:16 UTC 2020


On Wed, 7 Oct 2020 13:30:14 GMT, Andrew Haley <aph at openjdk.org> wrote:

> DataOutputStream is very slow post-disabling of Biased Locking. This
> was discovered when benchmarking a transaction library, which showed
> significant performance loss when moving to JDK 15. WIth some small
> changes to DataOutputStream we can get the performance back. There's a
> JMH benchmark at
> http://cr.openjdk.java.net/~aph/JDK-8254078/jmh-tests.tar
> 
> Some Stream classes use very fine-grained locking.
> 
> In particular, writeInt is defined like this:
> 
>         out.write((v >>> 24) & 0xFF);
>         out.write((v >>> 16) & 0xFF);
>         out.write((v >>> 8) & 0xFF);
>         out.write((v >>> 0) & 0xFF);
>         incCount(4);
> 
> Unfortunately, ByteArrayOutputStream.write(byte) is defined like this:
> 
>     public synchronized void write(int b) {
>         ensureCapacity(count + 1);
>         buf[count] = (byte) b;
>         count += 1;
>     }
> 
> so we acquire and release a lock for every byte that is output.
> 
>  For example, writing 4kb of ints goes from 17.3 us/op to 53.9 us/op when biased locking is disabled:
> 
> 
> +UseBiasedLocking DataOutputStreamTest.dataOutputStreamOverByteArray avgt 6 53.895 ± 5.126 us/op
> -UseBiasedLocking DataOutputStreamTest.dataOutputStreamOverByteArray avgt 6 17.291 ± 4.430 us/op
> 
> There are refactorings of DataOutputStream we can do to mitigate this.

, with option +UseBiasedLocking:

Benchmark                                                    (BASIC_TYPE)  (KIND)  (SIZE)  Mode  Cnt     Score
Error  Units DataOutputStreamTest.dataOutputStreamOverBufferedFileStream          char     old    4096  avgt    6
45.145 ± 38.769  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream         short     old    4096
avgt    6    54.226 ±  0.872  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream           int
old    4096  avgt    6    56.863 ±  1.264  us/op DataOutputStreamTest.dataOutputStreamOverByteArray
char     old    4096  avgt    6    20.369 ±  0.462  us/op
DataOutputStreamTest.dataOutputStreamOverByteArray                  short     old    4096  avgt    6    20.272 ±
0.214  us/op DataOutputStreamTest.dataOutputStreamOverByteArray                    int     old    4096  avgt    6
17.625 ±  0.142  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream               char     old    4096
avgt    6  3045.074 ± 79.539  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream              short
old    4096  avgt    6  3133.192 ± 74.831  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream
int     old    4096  avgt    6  2988.553 ± 29.789  us/op

jdk, default -UseBiasedLocking:

DataOutputStreamTest.dataOutputStreamOverBufferedFileStream          char     old    4096  avgt    6    58.267 ±
1.070  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream         short     old    4096  avgt    6
57.875 ±  2.386  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream           int     old    4096
avgt    6    58.393 ±  0.405  us/op DataOutputStreamTest.dataOutputStreamOverByteArray                   char
old    4096  avgt    6    50.269 ± 14.233  us/op DataOutputStreamTest.dataOutputStreamOverByteArray
short     old    4096  avgt    6    49.006 ± 11.184  us/op
DataOutputStreamTest.dataOutputStreamOverByteArray                    int     old    4096  avgt    6    52.905 ±
5.153  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream               char     old    4096  avgt    6
3053.183 ± 89.999  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream              short     old    4096
avgt    6  2986.694 ± 57.205  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream                int
old    4096  avgt    6  3061.812 ± 57.636  us/op

jdk, default -UseBiasedLocking, patched:

Benchmark                                                    (BASIC_TYPE)  (KIND)  (SIZE)  Mode  Cnt     Score
Error  Units DataOutputStreamTest.dataOutputStreamOverBufferedFileStream          char     old    4096  avgt    6
28.911 ±  0.529  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream         short     old    4096
avgt    6    28.895 ±  0.286  us/op DataOutputStreamTest.dataOutputStreamOverBufferedFileStream           int
old    4096  avgt    6    15.157 ±  2.870  us/op DataOutputStreamTest.dataOutputStreamOverByteArray
char     old    4096  avgt    6    29.251 ±  0.291  us/op
DataOutputStreamTest.dataOutputStreamOverByteArray                  short     old    4096  avgt    6    29.712 ±
0.230  us/op DataOutputStreamTest.dataOutputStreamOverByteArray                    int     old    4096  avgt    6
15.703 ±  0.265  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream               char     old    4096
avgt    6  1704.795 ± 36.028  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream              short
old    4096  avgt    6  1731.482 ± 21.304  us/op DataOutputStreamTest.dataOutputStreamOverRawFileStream
int     old    4096  avgt    6   861.758 ± 18.296  us/op```

-------------

PR: https://git.openjdk.java.net/jdk/pull/542


More information about the core-libs-dev mailing list