From df5bd78b39149f4ee4ed0a7ee8f56a8342dd0b91 Mon Sep 17 00:00:00 2001 From: Shawn Yang Date: Tue, 24 Sep 2024 22:54:44 -0700 Subject: [PATCH] perf(java): optimize read classdef perf (#1852) ## What does this PR do? ## Related issues ## Does this PR introduce any user-facing change? - [ ] Does this PR introduce any public API change? - [ ] Does this PR introduce any binary protocol compatibility change? ## Benchmark --- .../apache/fury/resolver/ClassResolver.java | 99 +++++++++---------- 1 file changed, 49 insertions(+), 50 deletions(-) diff --git a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java index 1fba168007..06748a041f 100644 --- a/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java +++ b/java/fury-core/src/main/java/org/apache/fury/resolver/ClassResolver.java @@ -418,26 +418,7 @@ public void register(Class... classes) { public void register(Class cls, boolean createSerializer) { register(cls); if (createSerializer) { - ClassInfo classInfo = getClassInfo(cls); - ClassInfo deserializationClassInfo; - if (metaContextShareEnabled && needToWriteClassDef(classInfo.serializer)) { - ClassDef classDef = classInfo.classDef; - if (classDef == null) { - classDef = buildClassDef(classInfo); - } - deserializationClassInfo = buildMetaSharedClassInfo(Tuple2.of(classDef, null), classDef); - if (deserializationClassInfo != null && GraalvmSupport.isGraalBuildtime()) { - getGraalvmClassRegistry() - .deserializerClassMap - .put(classDef.getId(), deserializationClassInfo.serializer.getClass()); - deserializationClassInfo.serializer = null; - } - } - if (GraalvmSupport.isGraalBuildtime()) { - // Instance for generated class should be hold at graalvm runtime only. - getGraalvmClassRegistry().serializerClassMap.put(cls, classInfo.serializer.getClass()); - classInfo.serializer = null; - } + createSerializerAhead(cls); } } @@ -503,7 +484,7 @@ public void register(Class cls, int classId) { public void register(Class cls, Short id, boolean createSerializer) { register(cls, id); if (createSerializer) { - getSerializer(cls); + createSerializerAhead(cls); } } @@ -712,7 +693,7 @@ public void resetSerializer(Class cls, Serializer serializer) { /** * Set serializer to avoid circular error when there is a serializer query for fields by {@link - * #buildMetaSharedClassInfo} and {@link #getSerializer(Class)} which access current creating + * #readClassInfoWithMetaShare} and {@link #getSerializer(Class)} which access current creating * serializer. This method is used to avoid overwriting existing serializer for class when * creating a data serializer for serialization of parts fields of a class. */ @@ -1226,6 +1207,32 @@ private Serializer createSerializer(Class cls) { return serializer; } + private void createSerializerAhead(Class cls) { + ClassInfo classInfo = getClassInfo(cls); + ClassInfo deserializationClassInfo; + if (metaContextShareEnabled && needToWriteClassDef(classInfo.serializer)) { + ClassDef classDef = classInfo.classDef; + if (classDef == null) { + classDef = buildClassDef(classInfo); + } + deserializationClassInfo = buildMetaSharedClassInfo(Tuple2.of(classDef, null), classDef); + if (deserializationClassInfo != null && GraalvmSupport.isGraalBuildtime()) { + getGraalvmClassRegistry() + .deserializerClassMap + .put(classDef.getId(), deserializationClassInfo.serializer.getClass()); + Tuple2 classDefTuple = extRegistry.classIdToDef.get(classDef.getId()); + // empty serializer for graalvm build time + classDefTuple.f1.serializer = null; + extRegistry.classIdToDef.put(classDef.getId(), Tuple2.of(classDefTuple.f0, null)); + } + } + if (GraalvmSupport.isGraalBuildtime()) { + // Instance for generated class should be hold at graalvm runtime only. + getGraalvmClassRegistry().serializerClassMap.put(cls, classInfo.serializer.getClass()); + classInfo.serializer = null; + } + } + private String generateSecurityMsg(Class cls) { String tpl = "%s is not registered, please check whether it's the type you want to serialize or " @@ -1363,21 +1370,23 @@ private ClassInfo readClassInfoWithMetaShare(MemoryBuffer buffer, MetaContext me if ((header & 0b1) == 0) { return getOrUpdateClassInfo((short) id); } - ObjectArray readClassInfos = metaContext.readClassInfos; - ClassInfo classInfo = readClassInfos.get(id); + ClassInfo classInfo = metaContext.readClassInfos.get(id); if (classInfo == null) { - ObjectArray readClassDefs = metaContext.readClassDefs; - ClassDef classDef = readClassDefs.get(id); - Tuple2 classDefTuple = extRegistry.classIdToDef.get(classDef.getId()); - if (classDefTuple == null - || classDefTuple.f1 == null - || classDefTuple.f1.serializer == null) { - classInfo = buildMetaSharedClassInfo(classDefTuple, classDef); - } else { - classInfo = classDefTuple.f1; - } - readClassInfos.set(id, classInfo); + classInfo = readClassInfoWithMetaShare(metaContext, id); + } + return classInfo; + } + + private ClassInfo readClassInfoWithMetaShare(MetaContext metaContext, int index) { + ClassDef classDef = metaContext.readClassDefs.get(index); + Tuple2 classDefTuple = extRegistry.classIdToDef.get(classDef.getId()); + ClassInfo classInfo; + if (classDefTuple == null || classDefTuple.f1 == null || classDefTuple.f1.serializer == null) { + classInfo = buildMetaSharedClassInfo(classDefTuple, classDef); + } else { + classInfo = classDefTuple.f1; } + metaContext.readClassInfos.set(index, classInfo); return classInfo; } @@ -1492,7 +1501,7 @@ private void writeClassDefs( public void readClassDefs(MemoryBuffer buffer) { MetaContext metaContext = fury.getSerializationContext().getMetaContext(); assert metaContext != null : SET_META__CONTEXT_MSG; - int numClassDefs = buffer.readVarUint32Small14(); + int numClassDefs = buffer.readVarUint32Small7(); for (int i = 0; i < numClassDefs; i++) { long id = buffer.readInt64(); Tuple2 tuple2 = extRegistry.classIdToDef.get(id); @@ -1506,9 +1515,7 @@ public void readClassDefs(MemoryBuffer buffer) { tuple2 = readClassDef(buffer, id); } metaContext.readClassDefs.add(tuple2.f0); - // Will be set lazily, so even some classes doesn't exist, remaining classinfo - // can be created still. - metaContext.readClassInfos.add(null); + metaContext.readClassInfos.add(tuple2.f1); } } @@ -1963,7 +1970,7 @@ private GraalvmClassRegistry getGraalvmClassRegistry() { private Class getSerializerClassFromGraalvmRegistry(Class cls) { GraalvmClassRegistry registry = getGraalvmClassRegistry(); List classResolvers = registry.resolvers; - if (classResolvers == null || classResolvers.isEmpty()) { + if (classResolvers.isEmpty()) { return null; } for (ClassResolver classResolver : classResolvers) { @@ -1975,6 +1982,7 @@ private Class getSerializerClassFromGraalvmRegistry(Class< } } Class serializerClass = registry.serializerClassMap.get(cls); + // noinspection Duplicates if (serializerClass != null) { return serializerClass; } @@ -1991,18 +1999,9 @@ private Class getMetaSharedDeserializerClassFromGraalvmReg Class cls, ClassDef classDef) { GraalvmClassRegistry registry = getGraalvmClassRegistry(); List classResolvers = registry.resolvers; - if (classResolvers == null || classResolvers.isEmpty()) { + if (classResolvers.isEmpty()) { return null; } - for (ClassResolver classResolver : classResolvers) { - if (classResolver != this) { - Tuple2 tuple2 = - classResolver.extRegistry.classIdToDef.get(classDef.getId()); - if (tuple2 != null && tuple2.f1 != null && tuple2.f1.serializer != null) { - return tuple2.f1.serializer.getClass(); - } - } - } Class deserializerClass = registry.deserializerClassMap.get(classDef.getId()); // noinspection Duplicates