-
Notifications
You must be signed in to change notification settings - Fork 612
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/master' into dev
- Loading branch information
Showing
5 changed files
with
217 additions
and
6 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/ContextualOverheadBenchmark.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
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 ContextualOverheadBenchmark { | ||
@Serializable | ||
data class Holder(val data: @Contextual Data) | ||
|
||
class Data(val a: Int, val b: String) | ||
|
||
object DataSerializer: KSerializer<Data> { | ||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Serializer") { | ||
element<Int>("a") | ||
element<String>("b") | ||
} | ||
|
||
override fun deserialize(decoder: Decoder): Data { | ||
return decoder.decodeStructure(descriptor) { | ||
var a = 0 | ||
var b = "" | ||
while (true) { | ||
when (val index = decodeElementIndex(descriptor)) { | ||
0 -> a = decodeIntElement(descriptor, 0) | ||
1 -> b = decodeStringElement(descriptor, 1) | ||
CompositeDecoder.DECODE_DONE -> break | ||
else -> error("Unexpected index: $index") | ||
} | ||
} | ||
Data(a, b) | ||
} | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: Data) { | ||
encoder.encodeStructure(descriptor) { | ||
encodeIntElement(descriptor, 0, value.a) | ||
encodeStringElement(descriptor, 1, value.b) | ||
} | ||
} | ||
|
||
} | ||
|
||
private val module = SerializersModule { | ||
contextual(DataSerializer) | ||
} | ||
|
||
private val json = Json { serializersModule = module } | ||
|
||
private val holder = Holder(Data(1, "abc")) | ||
private val holderString = json.encodeToString(holder) | ||
private val holderSerializer = serializer<Holder>() | ||
|
||
@Benchmark | ||
fun decode() = json.decodeFromString(holderSerializer, holderString) | ||
|
||
@Benchmark | ||
fun encode() = json.encodeToString(holderSerializer, holder) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
benchmark/src/jmh/kotlin/kotlinx/benchmarks/json/UseSerializerOverheadBenchmark.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters