Hi Chris,

On 24/06/2020 2:30 am, Chris Hegarty wrote:

On 23 Jun 2020, at 14:49, Peter Levart <peter.lev...@gmail.com> wrote:

...

Ok, I'm going to push this to jdk15.

Thank you Peter. This is a really nice change.

As a follow on, and not for JDK 15, I observe that Class::isRecord0 / 
JVM_IsRecord shows up as consuming a significant amount of time, more than 10%, 
in some runs of the deserialization benchmark. The isRecord implementation is a 
native method in the JVM, so relatively expensive to call.

This shows an opportunity to improve the Class::isRecord implementation with a 
simple cache of the record-ness of the j.l.Class, as is done selectively with 
other particular aspects of a class’s state. There are various ways to 
implement this, but here is just one [*].

There has been reluctance to add more and more fields to Class to cache all these new attributes that are being added - but ultimately that is a call for core-libs folk to make. The general expectation is/was that the need to ask a class if it is a Record (or isSealed etc) would be rare. But (de)serialization is the exception for isRecord() as unlike enums a simple instanceof test can't be used.

Cheers,
David
-----

Running the deserialization benchmark with this change [*], gives the following 
results:

Benchmark                                    (length)  Mode  Cnt    Score    
Error  Units
RecordSerializationBench.deserializeClasses        10  avgt   10   14.136 ±  
0.841  us/op
RecordSerializationBench.deserializeClasses       100  avgt   10   61.821 ±  
1.279  us/op
RecordSerializationBench.deserializeClasses      1000  avgt   10  519.473 ±  
7.950  us/op
RecordSerializationBench.deserializeRecords        10  avgt   10   13.781 ±  
1.917  us/op
RecordSerializationBench.deserializeRecords       100  avgt   10   54.061 ±  
4.188  us/op
RecordSerializationBench.deserializeRecords      1000  avgt   10  444.538 ± 
13.940  us/op

I think it is worth considering caching the record-ness state of a j.l.Class, 
as I’m sure it will be widely used in third-party serialization libraries, as 
well as by Java Serialization.

-Chris.

[*]
diff -r 3a9521647349 src/java.base/share/classes/java/lang/Class.java
--- a/src/java.base/share/classes/java/lang/Class.java  Tue Jun 23 10:46:39 
2020 +0100
+++ b/src/java.base/share/classes/java/lang/Class.java  Tue Jun 23 17:11:35 
2020 +0100
@@ -3712,9 +3712,17 @@
      
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS,
                                   essentialAPI=false)
      public boolean isRecord() {
-        return getSuperclass() == JAVA_LANG_RECORD_CLASS && isRecord0();
+        if (!isRecordCalled) {
+            isRecord = getSuperclass() == JAVA_LANG_RECORD_CLASS && 
isRecord0();
+            isRecordCalled = true;
+        }
+        return isRecord;
      }
+ // cached record(ness) status
+    private transient boolean isRecord;
+    private transient boolean isRecordCalled;
+
      // Fetches the factory for reflective objects
      private static ReflectionFactory getReflectionFactory() {
          if (reflectionFactory == null) {

Reply via email to