You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by rs...@apache.org on 2021/04/06 13:10:49 UTC

[avro] branch master updated: AVRO-3094: improve performance of SpecificData.getForClass(), especially around old generated specific record classes (#1172)

This is an automated email from the ASF dual-hosted git repository.

rskraba pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new 89efb8d  AVRO-3094: improve performance of SpecificData.getForClass(), especially around old generated specific record classes (#1172)
89efb8d is described below

commit 89efb8dd7bef28945d0e9598d913aa9ec843593c
Author: Radai Rosenblatt <ra...@gmail.com>
AuthorDate: Tue Apr 6 06:09:47 2021 -0700

    AVRO-3094: improve performance of SpecificData.getForClass(), especially around old generated specific record classes (#1172)
    
    Avro 1.9+ attempts to access static field MODEL$ on avo-generated classes.
    Record classes generated by older Avro (for example 1.7) do not have this field.
    This causes modern avro to catch an exception on every record being deserialized
    for such classes, which can cause a x3 slow down
    (see profiler results in the Jira ticket).
    
    This fix uses ClassValue to cache the SpecificData instance to use per class.
    This results in s ~x5 speedup for the happy path (classes that have MODEL$) and
    ~x50 speedup for classes that do not have MODEL$.
    
    Co-authored-by: radai <ra...@fractal.lan>
---
 .../org/apache/avro/specific/SpecificData.java     | 28 +++++++++++++---------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
index 3cbb21d..b595b28 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/specific/SpecificData.java
@@ -69,6 +69,22 @@ public class SpecificData extends GenericData {
     }
 
   };
+  private static final ClassValue<SpecificData> MODEL_CACHE = new ClassValue<SpecificData>() {
+    @Override
+    protected SpecificData computeValue(Class<?> type) {
+      Field specificDataField;
+      try {
+        specificDataField = type.getDeclaredField("MODEL$");
+        specificDataField.setAccessible(true);
+        return (SpecificData) specificDataField.get(null);
+      } catch (NoSuchFieldException e) {
+        // Return default instance
+        return SpecificData.get();
+      } catch (IllegalAccessException e) {
+        throw new AvroRuntimeException("while trying to access field MODEL$ on " + type.getCanonicalName(), e);
+      }
+    }
+  };
 
   public static final String CLASS_PROP = "java-class";
   public static final String KEY_CLASS_PROP = "java-key-class";
@@ -168,17 +184,7 @@ public class SpecificData extends GenericData {
    */
   public static <T> SpecificData getForClass(Class<T> c) {
     if (SpecificRecordBase.class.isAssignableFrom(c)) {
-      final Field specificDataField;
-      try {
-        specificDataField = c.getDeclaredField("MODEL$");
-        specificDataField.setAccessible(true);
-        return (SpecificData) specificDataField.get(null);
-      } catch (NoSuchFieldException e) {
-        // Return default instance
-        return SpecificData.get();
-      } catch (IllegalAccessException e) {
-        throw new AvroRuntimeException(e);
-      }
+      return MODEL_CACHE.get(c);
     }
     return SpecificData.get();
   }