Optimize DeserializedAnnotations in terms of memory traffic

Do not wrap every annotation object into an AnnotationWithTarget
This commit is contained in:
Alexander Udalov
2017-07-04 13:09:18 +03:00
parent 21197b53aa
commit 5636318eb4
5 changed files with 45 additions and 33 deletions
@@ -224,7 +224,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
}
return DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
c.containingDeclaration.asProtoContainer()?.let {
c.components.annotationAndConstantLoader.loadCallableAnnotations(it, proto, kind)
c.components.annotationAndConstantLoader.loadCallableAnnotations(it, proto, kind).toList()
}.orEmpty()
}
}
@@ -239,6 +239,7 @@ class MemberDeserializer(private val c: DeserializationContext) {
c.components.annotationAndConstantLoader
.loadExtensionReceiverParameterAnnotations(it, proto, receiverTargetedKind)
.map { AnnotationWithTarget(it, AnnotationUseSiteTarget.RECEIVER) }
.toList()
}.orEmpty()
}
}
@@ -255,7 +256,9 @@ class MemberDeserializer(private val c: DeserializationContext) {
val flags = if (proto.hasFlags()) proto.flags else 0
val annotations = if (containerOfCallable != null && Flags.HAS_ANNOTATIONS.get(flags)) {
DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadValueParameterAnnotations(containerOfCallable, callable, kind, i, proto)
c.components.annotationAndConstantLoader
.loadValueParameterAnnotations(containerOfCallable, callable, kind, i, proto)
.toList()
}
}
else Annotations.EMPTY
@@ -85,9 +85,10 @@ class TypeDeserializer(
}
val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
c.components.annotationAndConstantLoader
.loadTypeAnnotations(proto, c.nameResolver)
.map { AnnotationWithTarget(it, null) } + additionalAnnotations.getAllAnnotations()
c.components.annotationAndConstantLoader.loadTypeAnnotations(proto, c.nameResolver)
.map { AnnotationWithTarget(it, null) }
.plus(additionalAnnotations.getAllAnnotations())
.toList()
}
fun ProtoBuf.Type.collectAllArguments(): List<ProtoBuf.Type.Argument> =
@@ -16,44 +16,55 @@
package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
class DeserializedAnnotations(
storageManager: StorageManager,
compute: () -> List<AnnotationDescriptor>
) : DeserializedAnnotationsWithPossibleTargets(
storageManager,
{ compute().map { AnnotationWithTarget(it, null) } })
open class DeserializedAnnotationsWithPossibleTargets(
storageManager: StorageManager,
compute: () -> List<AnnotationWithTarget>
) : Annotations {
private val annotations = storageManager.createLazyValue { compute().toList() }
private val annotations by storageManager.createLazyValue(compute)
override fun isEmpty(): Boolean = annotations().isEmpty()
override fun isEmpty(): Boolean = annotations.isEmpty()
override fun findAnnotation(fqName: FqName) = annotations().firstOrNull {
annotationWithTarget ->
if (annotationWithTarget.target != null) return@firstOrNull false
val descriptor = annotationWithTarget.annotation.annotationClass
descriptor != null && fqName.toUnsafe() == DescriptorUtils.getFqName(descriptor)
}?.annotation
override fun findAnnotation(fqName: FqName) =
annotations.firstOrNull { annotation -> annotation.annotationClass?.fqNameUnsafe == fqName.toUnsafe() }
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations() = annotations().filter { it.target != null }
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = emptyList()
override fun getAllAnnotations() = annotations()
override fun getAllAnnotations(): List<AnnotationWithTarget> = annotations.map { AnnotationWithTarget(it, null) }
override fun iterator(): Iterator<AnnotationDescriptor> = annotations.iterator()
}
class DeserializedAnnotationsWithPossibleTargets(
storageManager: StorageManager,
compute: () -> List<AnnotationWithTarget>
) : Annotations {
private val annotations by storageManager.createLazyValue(compute)
override fun isEmpty(): Boolean = annotations.isEmpty()
override fun findAnnotation(fqName: FqName): AnnotationDescriptor? =
annotations.firstOrNull { (annotation, target) ->
target == null && annotation.annotationClass?.fqNameUnsafe == fqName.toUnsafe()
}?.annotation
override fun findExternalAnnotation(fqName: FqName) = null
override fun getUseSiteTargetedAnnotations(): List<AnnotationWithTarget> = annotations.filter { it.target != null }
override fun getAllAnnotations(): List<AnnotationWithTarget> = annotations
override fun iterator(): Iterator<AnnotationDescriptor> {
return annotations().asSequence().filter { it.target == null }.map { it.annotation }.iterator()
return annotations.asSequence().filter { it.target == null }.map { it.annotation }.iterator()
}
}
}
@@ -81,7 +81,7 @@ class DeserializedClassDescriptor(
Annotations.EMPTY
}
else DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadClassAnnotations(thisAsProtoContainer)
c.components.annotationAndConstantLoader.loadClassAnnotations(thisAsProtoContainer).toList()
}
override fun getContainingDeclaration(): DeclarationDescriptor = containingDeclaration
@@ -309,7 +309,7 @@ class DeserializedClassDescriptor(
EnumEntrySyntheticClassDescriptor.create(
c.storageManager, this@DeserializedClassDescriptor, name, enumMemberNames,
DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadEnumEntryAnnotations(thisAsProtoContainer, proto)
c.components.annotationAndConstantLoader.loadEnumEntryAnnotations(thisAsProtoContainer, proto).toList()
},
SourceElement.NO_SOURCE
)
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.serialization.deserialization.descriptors
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.SupertypeLoopChecker
import org.jetbrains.kotlin.descriptors.annotations.AnnotationWithTarget
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -36,10 +35,8 @@ class DeserializedTypeParameterDescriptor(
c.storageManager, c.containingDeclaration, c.nameResolver.getName(proto.name),
Deserialization.variance(proto.variance), proto.reified, index, SourceElement.NO_SOURCE, SupertypeLoopChecker.EMPTY
) {
override val annotations = DeserializedAnnotationsWithPossibleTargets(c.storageManager) {
c.components.annotationAndConstantLoader
.loadTypeParameterAnnotations(proto, c.nameResolver)
.map { AnnotationWithTarget(it, null) }
override val annotations = DeserializedAnnotations(c.storageManager) {
c.components.annotationAndConstantLoader.loadTypeParameterAnnotations(proto, c.nameResolver).toList()
}
override fun resolveUpperBounds(): List<KotlinType> {