• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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