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 <[email protected]>
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 <[email protected]>
---
.../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();
}