-
Bug
-
Resolution: Fixed
-
P4
-
8, 11, 16
-
b24
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.
With biased locking we don't see the pain because the acquire and release operations are basically no-ops, and C2 optimizes the whole lot away. Without biased locking, things are very much worse.
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.
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.
With biased locking we don't see the pain because the acquire and release operations are basically no-ops, and C2 optimizes the whole lot away. Without biased locking, things are very much worse.
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.
- csr for
-
JDK-8254224 Change DataOutputStream to use its internal buffer for ints, chars, and shorts
- Closed
- relates to
-
JDK-8034058 Lock coarsening works for local variables, breaks for fields
- Open
-
JDK-8155902 DataOuputStream should clarify that it might write primitive types as multiple byte groups
- Resolved