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