From 887f2db005a5063146473bb09ba04d4d87bb3f7d Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Fri, 11 Sep 2020 14:58:24 -0300 Subject: [PATCH 1/2] Cache record names to avoid hitting class loader --- .../avro/schema/AvroSchemaHelper.java | 74 ++++++++++++------- 1 file changed, 49 insertions(+), 25 deletions(-) diff --git a/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java b/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java index a35bea8e0..c185c25cb 100644 --- a/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java +++ b/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java @@ -24,6 +24,8 @@ public abstract class AvroSchemaHelper { + private static final Map SCHEMA_NAME_CACHE = new HashMap<>(); + /** * Dedicated mapper for handling default values (String <-> JsonNode <-> Object) * @@ -332,32 +334,54 @@ public static String getTypeId(Schema schema) { */ public static String getFullName(Schema schema) { switch (schema.getType()) { - case RECORD: - case ENUM: - case FIXED: - String namespace = schema.getNamespace(); - String name = schema.getName(); - if (namespace == null) { - return schema.getName(); - } - if (namespace.endsWith("$")) { - return namespace + name; - } - StringBuilder sb = new StringBuilder(1 + namespace.length() + name.length()); - // 28-Feb-2020: [dataformats-binary#195] somewhat complicated logic of trying - // to support differences between avro-lib 1.8 and 1.9... - // Check if this is a nested class - String nestedClassName = sb.append(namespace).append('$').append(name).toString(); - try { - Class.forName(nestedClassName); - return nestedClassName; - } catch (ClassNotFoundException e) { - // Could not find a nested class, must be a regular class - sb.setLength(0); - return sb.append(namespace).append('.').append(name).toString(); - } + case RECORD: + case ENUM: + case FIXED: + String namespace = schema.getNamespace(); + String name = schema.getName(); + String key = namespace + "." + name; + String schemaName = SCHEMA_NAME_CACHE.get(key); + + if (schemaName == null) { + schemaName = resolveFullName(schema); + SCHEMA_NAME_CACHE.put(key, schemaName); + } + + return schemaName; + default: - return schema.getType().getName(); + return schema.getType().getName(); + } + } + + private static String resolveFullName(Schema schema) { + String namespace = schema.getNamespace(); + String name = schema.getName(); + + if (namespace == null) { + return schema.getName(); + } + + if (namespace.endsWith("$")) { + return namespace + name; + } + + StringBuilder sb = new StringBuilder(1 + namespace.length() + name.length()); + + // 28-Feb-2020: [dataformats-binary#195] somewhat complicated logic of trying + // to support differences between avro-lib 1.8 and 1.9... + // Check if this is a nested class + String nestedClassName = sb.append(namespace).append('$').append(name).toString(); + + try { + Class.forName(nestedClassName); + + return nestedClassName; + } catch (ClassNotFoundException e) { + // Could not find a nested class, must be a regular class + sb.setLength(0); + + return sb.append(namespace).append('.').append(name).toString(); } } From db1b79d4785011367db885ed9c9601e7d1abebd2 Mon Sep 17 00:00:00 2001 From: Marcos Passos Date: Sat, 19 Sep 2020 17:42:52 -0300 Subject: [PATCH 2/2] Use LRUCache instead of HashMap --- .../jackson/dataformat/avro/schema/AvroSchemaHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java b/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java index c185c25cb..a346a20e1 100644 --- a/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java +++ b/avro/src/main/java/com/fasterxml/jackson/dataformat/avro/schema/AvroSchemaHelper.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.dataformat.avro.schema; +import com.fasterxml.jackson.databind.util.LRUMap; import java.io.File; import java.math.BigDecimal; import java.math.BigInteger; @@ -24,7 +25,7 @@ public abstract class AvroSchemaHelper { - private static final Map SCHEMA_NAME_CACHE = new HashMap<>(); + private static final LRUMap SCHEMA_NAME_CACHE = new LRUMap<>(16, 1024); /** * Dedicated mapper for handling default values (String <-> JsonNode <-> Object)