diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/builder/BuilderAdapter.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/builder/BuilderAdapter.kt index 650b71fd..13421634 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/builder/BuilderAdapter.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/io/json/builder/BuilderAdapter.kt @@ -14,12 +14,15 @@ import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonToken import com.google.gson.stream.JsonWriter import it.unimi.dsi.fastutil.objects.ObjectArraySet +import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import org.apache.logging.log4j.LogManager import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.defs.util.flattenJsonElement import ru.dbotthepony.kstarbound.io.json.util.asReference import ru.dbotthepony.kstarbound.util.NotNullVar +import java.util.concurrent.ConcurrentHashMap import kotlin.properties.Delegates import kotlin.reflect.KCallable import kotlin.reflect.KClass @@ -349,12 +352,27 @@ class BuilderAdapter private constructor( companion object : TypeAdapterFactory { private val LOGGER = LogManager.getLogger() + private val declCache = Reference2ObjectOpenHashMap, ArrayList>>() private fun collectDecl(input: KClass<*>, output: MutableMap>) { + for (decl in collectDeclImpl(input)) { + output.putIfAbsent(decl.name, decl) + } + } + + private fun collectDeclImpl(input: KClass<*>): ArrayList> { + val getValues = synchronized(declCache) { declCache[input] } + + if (getValues != null) { + return getValues + } + + val values = ObjectLinkedOpenHashSet>() + for (decl in input.declaredMembers) { if (decl is KMutableProperty1<*, *>) { decl.isAccessible = true - output.putIfAbsent(decl.name, decl) + values.add(decl) } } @@ -362,9 +380,13 @@ class BuilderAdapter private constructor( val classifier = parent.classifier if (classifier is KClass<*> && !classifier.java.isInterface) { - collectDecl(classifier, output) + values.addAll(collectDeclImpl(classifier)) } } + + val list = ArrayList(values) + synchronized(declCache) { declCache.put(input, list) } + return list } override fun create(gson: Gson, type: TypeToken): TypeAdapter? {