RFR: 8247532: Records deserialization is slow
Peter Levart
peter.levart at gmail.com
Sun Jun 14 16:28:21 UTC 2020
Hi,
I noticed that deserializing records (new preview Java feature in JDK14
and JDK15) is slow compared to equivalent classical classes. I created a
JMH benchmark [1] to se how it compares (ran it on JDK14):
Benchmark Mode Cnt Score Error Units
RecordSerializationBench.deserializeClasses avgt 10 31.911 ± 0.218 us/op
RecordSerializationBench.deserializeClasses:·gc.alloc.rate avgt 10 815.106 ± 5.545 MB/sec
RecordSerializationBench.deserializeClasses:·gc.alloc.rate.norm avgt 10 40921.903 ± 0.615 B/op
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Eden_Space avgt 10 839.522 ± 191.195 MB/sec
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Eden_Space.norm avgt 10 42153.661 ± 9682.799 B/op
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Survivor_Space avgt 10 0.117 ± 0.492 MB/sec
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Survivor_Space.norm avgt 10 5.835 ± 24.447 B/op
RecordSerializationBench.deserializeClasses:·gc.count avgt 10 21.000 counts
RecordSerializationBench.deserializeClasses:·gc.time avgt 10 17.000 ms
RecordSerializationBench.deserializeRecords avgt 10 531.333 ± 3.094 us/op
RecordSerializationBench.deserializeRecords:·gc.alloc.rate avgt 10 346.511 ± 1.997 MB/sec
RecordSerializationBench.deserializeRecords:·gc.alloc.rate.norm avgt 10 289637.193 ± 6.894 B/op
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Eden_Space avgt 10 359.773 ± 191.116 MB/sec
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Eden_Space.norm avgt 10 300657.838 ± 159724.346 B/op
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Survivor_Space avgt 10 0.007 ± 0.012 MB/sec
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Survivor_Space.norm avgt 10 6.020 ± 9.910 B/op
RecordSerializationBench.deserializeRecords:·gc.count avgt 10 9.000 counts
RecordSerializationBench.deserializeRecords:·gc.time avgt 10 14.000 ms
...not only it is it about 16x slower, it also produces 7x garbage. I
checked the code and it is not very optimal. It matches the record
component names with object stream fields in O(n^2) way. It uses method
handles but binds arguments of canonical constructor each time an
instance of record is constructed. So I tried to optimize it [2] and
with that patch on top of JDK16 the benchmark produces the following
results:
Benchmark Mode Cnt Score Error Units
RecordSerializationBench.deserializeClasses avgt 10 31.049 ± 0.235 us/op
RecordSerializationBench.deserializeClasses:·gc.alloc.rate avgt 10 837.614 ± 6.326 MB/sec
RecordSerializationBench.deserializeClasses:·gc.alloc.rate.norm avgt 10 40921.931 ± 0.666 B/op
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Eden_Space avgt 10 867.743 ± 251.373 MB/sec
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Eden_Space.norm avgt 10 42405.532 ± 12403.301 B/op
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Survivor_Space avgt 10 0.126 ± 0.478 MB/sec
RecordSerializationBench.deserializeClasses:·gc.churn.G1_Survivor_Space.norm avgt 10 6.113 ± 23.268 B/op
RecordSerializationBench.deserializeClasses:·gc.count avgt 10 22.000 counts
RecordSerializationBench.deserializeClasses:·gc.time avgt 10 19.000 ms
RecordSerializationBench.deserializeRecords avgt 10 33.588 ± 0.394 us/op
RecordSerializationBench.deserializeRecords:·gc.alloc.rate avgt 10 500.033 ± 5.871 MB/sec
RecordSerializationBench.deserializeRecords:·gc.alloc.rate.norm avgt 10 26425.293 ± 0.759 B/op
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Eden_Space avgt 10 512.772 ± 288.112 MB/sec
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Eden_Space.norm avgt 10 27090.499 ± 15175.280 B/op
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Survivor_Space avgt 10 0.134 ± 0.496 MB/sec
RecordSerializationBench.deserializeRecords:·gc.churn.G1_Survivor_Space.norm avgt 10 7.128 ± 26.526 B/op
RecordSerializationBench.deserializeRecords:·gc.count avgt 10 13.000 counts
RecordSerializationBench.deserializeRecords:·gc.time avgt 10 17.000 ms
...so here the speed is comparable and it even produces less garbage.
I created an issue [3].
So WDYT? Since this is still a preview feature in JDK15, is it possible
to squeeze it into JDK15?
Regards, Peter
[1]
http://cr.openjdk.java.net/~plevart/jdk-dev/RecordsDeserialization/RecordSerializationBench.java
[2]
http://cr.openjdk.java.net/~plevart/jdk-dev/RecordsDeserialization/webrev.01/
[3] https://bugs.openjdk.java.net/browse/JDK-8247532
More information about the core-libs-dev
mailing list