1 @file:UseSerializers(UseSerializerOverheadBenchmark.DataClassSerializer::class, UseSerializerOverheadBenchmark.DataObjectSerializer::class) 2 package kotlinx.benchmarks.json 3 4 5 import kotlinx.serialization.* 6 import kotlinx.serialization.descriptors.SerialDescriptor 7 import kotlinx.serialization.descriptors.buildClassSerialDescriptor 8 import kotlinx.serialization.descriptors.element 9 import kotlinx.serialization.encoding.* 10 import kotlinx.serialization.json.* 11 import kotlinx.serialization.modules.* 12 import org.openjdk.jmh.annotations.* 13 import java.util.concurrent.* 14 15 @Warmup(iterations = 7, time = 1) 16 @Measurement(iterations = 5, time = 1) 17 @BenchmarkMode(Mode.Throughput) 18 @OutputTimeUnit(TimeUnit.MILLISECONDS) 19 @State(Scope.Benchmark) 20 @Fork(1) 21 open class UseSerializerOverheadBenchmark { 22 @Serializable 23 data class HolderForClass(val data: DataForClass) 24 25 @Serializable 26 data class HolderForObject(val data: DataForObject) 27 28 class DataForClass(val a: Int, val b: String) 29 30 class DataForObject(val a: Int, val b: String) 31 32 object DataClassSerializer: KSerializer<DataForClass> { <lambda>null33 override val descriptor: SerialDescriptor = buildClassSerialDescriptor("ClassSerializer") { 34 element<Int>("a") 35 element<String>("b") 36 } 37 deserializenull38 override fun deserialize(decoder: Decoder): DataForClass { 39 return decoder.decodeStructure(descriptor) { 40 var a = 0 41 var b = "" 42 while (true) { 43 when (val index = decodeElementIndex(ContextualOverheadBenchmark.DataSerializer.descriptor)) { 44 0 -> a = decodeIntElement(ContextualOverheadBenchmark.DataSerializer.descriptor, 0) 45 1 -> b = decodeStringElement(ContextualOverheadBenchmark.DataSerializer.descriptor, 1) 46 CompositeDecoder.DECODE_DONE -> break 47 else -> error("Unexpected index: $index") 48 } 49 } 50 DataForClass(a, b) 51 } 52 } 53 serializenull54 override fun serialize(encoder: Encoder, value: DataForClass) { 55 encoder.encodeStructure(descriptor) { 56 encodeIntElement(descriptor, 0, value.a) 57 encodeStringElement(descriptor, 1, value.b) 58 } 59 } 60 } 61 62 object DataObjectSerializer: KSerializer<DataForObject> { <lambda>null63 override val descriptor: SerialDescriptor = buildClassSerialDescriptor("ObjectSerializer") { 64 element<Int>("a") 65 element<String>("b") 66 } 67 deserializenull68 override fun deserialize(decoder: Decoder): DataForObject { 69 return decoder.decodeStructure(descriptor) { 70 var a = 0 71 var b = "" 72 while (true) { 73 when (val index = decodeElementIndex(ContextualOverheadBenchmark.DataSerializer.descriptor)) { 74 0 -> a = decodeIntElement(ContextualOverheadBenchmark.DataSerializer.descriptor, 0) 75 1 -> b = decodeStringElement(ContextualOverheadBenchmark.DataSerializer.descriptor, 1) 76 CompositeDecoder.DECODE_DONE -> break 77 else -> error("Unexpected index: $index") 78 } 79 } 80 DataForObject(a, b) 81 } 82 } 83 serializenull84 override fun serialize(encoder: Encoder, value: DataForObject) { 85 encoder.encodeStructure(descriptor) { 86 encodeIntElement(descriptor, 0, value.a) 87 encodeStringElement(descriptor, 1, value.b) 88 } 89 } 90 } 91 <lambda>null92 private val module = SerializersModule { 93 contextual(DataClassSerializer) 94 } 95 <lambda>null96 private val json = Json { serializersModule = module } 97 98 private val classHolder = HolderForClass(DataForClass(1, "abc")) 99 private val classHolderString = json.encodeToString(classHolder) 100 private val classHolderSerializer = serializer<HolderForClass>() 101 102 private val objectHolder = HolderForObject(DataForObject(1, "abc")) 103 private val objectHolderString = json.encodeToString(objectHolder) 104 private val objectHolderSerializer = serializer<HolderForObject>() 105 106 @Benchmark decodeForClassnull107 fun decodeForClass() = json.decodeFromString(classHolderSerializer, classHolderString) 108 109 @Benchmark 110 fun encodeForClass() = json.encodeToString(classHolderSerializer, classHolder) 111 112 /* 113 Any optimizations should not affect the speed of these tests. 114 It doesn't make sense to cache singleton (`object`) serializer, because the object is accessed instantly 115 */ 116 117 @Benchmark 118 fun decodeForObject() = json.decodeFromString(objectHolderSerializer, objectHolderString) 119 120 @Benchmark 121 fun encodeForObject() = json.encodeToString(objectHolderSerializer, objectHolder) 122 123 } 124