Skip to content

Commit

Permalink
Lists of ints serialization benchmarks (#270)
Browse files Browse the repository at this point in the history
* Add list wrappers related benchmarks

* add list related results dump
  • Loading branch information
rutkowskij authored Feb 4, 2025
1 parent 8b4d2e0 commit 8b78af0
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 0 deletions.
13 changes: 13 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ c.g.a.b.simple.Avro4kSimpleBenchmark.write thrpt 5 4466
c.g.a.b.simple.ApacheAvroReflectSimpleBenchmark.write thrpt 5 320367.673 ± 33394.537 ops/s
c.g.a.b.simple.Avro4kGenericWithApacheAvroSimpleBenchmark.write thrpt 5 168702.542 ± 5553.797 ops/s
c.g.a.b.simple.JacksonAvroSimpleBenchmark.write thrpt 5 138898.312 ± 9156.715 ops/s
c.g.a.b.lists.Avro4kV1ListsBenchmark.read thrpt 5 475.048 ± 22.037 ops/s 0%
c.g.a.b.lists.ApacheAvroReflectListsBenchmark.read thrpt 5 290.714 ± 6.295 ops/s -38.80%
c.g.a.b.lists.Avro4kGenericWithApacheAvroListsBenchmark.read thrpt 5 311.651 ± 3.760 ops/s -34.42%
c.g.a.b.lists.Avro4kListsBenchmark.read thrpt 5 412.503 ± 6.127 ops/s -13.16%
c.g.a.b.lists.JacksonAvroListsBenchmark.read thrpt 5 1002.527 ± 23.039 ops/s +111.09%
c.g.a.b.lists.Avro4kV1ListsBenchmark.write thrpt 5 530.151 ± 14.683 ops/s 0%
c.g.a.b.lists.ApacheAvroReflectListsBenchmark.write thrpt 5 561.516 ± 11.003 ops/s +5.91%
c.g.a.b.lists.Avro4kGenericWithApacheAvroListsBenchmark.write thrpt 5 708.795 ± 77.770 ops/s +33.76%
c.g.a.b.lists.Avro4kListsBenchmark.write thrpt 5 1499.795 ± 59.895 ops/s +183.02%
c.g.a.b.lists.JacksonAvroListsBenchmark.write thrpt 5 464.208 ± 9.000 ops/s -12.42%
```

> [!WARNING]
Expand Down
6 changes: 6 additions & 0 deletions benchmark/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ benchmark {
register("avro4k-write") {
include("Avro4k.+write")
}
register("lists-read") {
include("^com.github.avrokotlin.benchmark.lists.+.read$")
}
register("lists-write") {
include("^com.github.avrokotlin.benchmark.lists.+.write$")
}
}
targets {
register("main") {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.github.avrokotlin.benchmark.internal

import kotlinx.serialization.Serializable

@Serializable
internal data class ListWrapperDataClass(val index: Int, val entries: List<StatsEntry>) {
companion object {
fun create(size: Int, entriesSize: Int, random: RandomUtils = RandomUtils()) =
ListWrapperDataClass(random.nextInt(), List(size) { StatsEntry.create(entriesSize) })
}
}

@Serializable
internal data class StatsEntry(val elementId: Long, val values: List<Long>) {
companion object {
fun create(entriesSize: Int, random: RandomUtils = RandomUtils()) =
StatsEntry(random.nextLong(), List(entriesSize) { random.nextLong() })
}
}

@Serializable
internal data class ListWrapperDatasClass(
val data: List<ListWrapperDataClass>
) {
companion object {
fun create(size: Int, wrapperSize: Int, entriesSize: Int = 100) =
ListWrapperDatasClass(data = List(size) { ListWrapperDataClass.create(wrapperSize, entriesSize) }
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.github.avrokotlin.benchmark.lists

import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.encodeToByteArray
import com.github.avrokotlin.benchmark.internal.ListWrapperDatasClass
import kotlinx.benchmark.Benchmark
import org.apache.avro.io.DatumReader
import org.apache.avro.io.DatumWriter
import org.apache.avro.io.DecoderFactory
import org.apache.avro.io.Encoder
import org.apache.avro.io.EncoderFactory
import org.apache.avro.reflect.ReflectData
import java.io.OutputStream

internal class ApacheAvroReflectListsBenchmark : SerializationListsBenchmark() {
lateinit var writer: DatumWriter<ListWrapperDatasClass>
lateinit var encoder: Encoder
lateinit var reader: DatumReader<ListWrapperDatasClass>

lateinit var data: ByteArray

override fun setup() {
writer = ReflectData.get().createDatumWriter(schema) as DatumWriter<ListWrapperDatasClass>
encoder = EncoderFactory.get().directBinaryEncoder(OutputStream.nullOutputStream(), null)

reader = ReflectData.get().createDatumReader(schema) as DatumReader<ListWrapperDatasClass>
}

override fun prepareBinaryData() {
data = Avro.encodeToByteArray(schema, lists)
}

@Benchmark
fun read() {
val decoder = DecoderFactory.get().binaryDecoder(data, null)
reader.read(null, decoder)
}

@Benchmark
fun write() {
writer.write(lists, encoder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.avrokotlin.benchmark.lists

import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.decodeFromGenericData
import com.github.avrokotlin.avro4k.encodeToByteArray
import com.github.avrokotlin.avro4k.encodeToGenericData
import com.github.avrokotlin.benchmark.internal.Clients
import kotlinx.benchmark.Benchmark
import kotlinx.serialization.ExperimentalSerializationApi
import org.apache.avro.generic.GenericData
import org.apache.avro.io.DatumReader
import org.apache.avro.io.DatumWriter
import org.apache.avro.io.DecoderFactory
import org.apache.avro.io.Encoder
import org.apache.avro.io.EncoderFactory
import java.io.OutputStream

internal class Avro4kGenericWithApacheAvroListsBenchmark : SerializationListsBenchmark() {
lateinit var writer: DatumWriter<Any?>
lateinit var encoder: Encoder
lateinit var reader: DatumReader<Any?>

lateinit var data: ByteArray

override fun setup() {
writer = GenericData.get().createDatumWriter(schema) as DatumWriter<Any?>
encoder = EncoderFactory.get().directBinaryEncoder(OutputStream.nullOutputStream(), null)

reader = GenericData.get().createDatumReader(schema) as DatumReader<Any?>
}

override fun prepareBinaryData() {
data = Avro.encodeToByteArray(schema, lists)
}

@OptIn(ExperimentalSerializationApi::class)
@Benchmark
fun read() {
val decoder = DecoderFactory.get().binaryDecoder(data, null)
val genericData = reader.read(null, decoder)
Avro.decodeFromGenericData<Clients>(schema, genericData)
}

@OptIn(ExperimentalSerializationApi::class)
@Benchmark
fun write() {
val genericData = Avro.encodeToGenericData(schema, lists)
writer.write(genericData, encoder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.github.avrokotlin.benchmark.lists

import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.decodeFromByteArray
import com.github.avrokotlin.avro4k.encodeToByteArray
import com.github.avrokotlin.avro4k.encodeToStream
import com.github.avrokotlin.benchmark.internal.ListWrapperDatasClass
import kotlinx.benchmark.Benchmark
import kotlinx.serialization.ExperimentalSerializationApi
import java.io.OutputStream

internal class Avro4kListsBenchmark : SerializationListsBenchmark() {
lateinit var data: ByteArray

override fun setup() {
}

override fun prepareBinaryData() {
data = Avro.encodeToByteArray(schema, lists)
}

@Benchmark
fun read() {
Avro.decodeFromByteArray<ListWrapperDatasClass>(schema, data)
}

@OptIn(ExperimentalSerializationApi::class)
@Benchmark
fun write() {
Avro.encodeToStream(schema, lists, OutputStream.nullOutputStream())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.github.avrokotlin.benchmark.lists

import com.fasterxml.jackson.databind.MapperFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectReader
import com.fasterxml.jackson.databind.ObjectWriter
import com.fasterxml.jackson.dataformat.avro.AvroMapper
import com.fasterxml.jackson.dataformat.avro.AvroSchema
import com.fasterxml.jackson.dataformat.avro.jsr310.AvroJavaTimeModule
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.encodeToByteArray
import com.github.avrokotlin.benchmark.internal.ListWrapperDatasClass
import kotlinx.benchmark.Benchmark
import java.io.OutputStream


internal class JacksonAvroListsBenchmark : SerializationListsBenchmark() {
lateinit var writer: ObjectWriter
lateinit var reader: ObjectReader

lateinit var data: ByteArray

override fun setup() {
writer = ListWrapperDatasClass::class.java.createWriter()
reader = ListWrapperDatasClass::class.java.createReader()
}

override fun prepareBinaryData() {
data = Avro.encodeToByteArray(schema, lists)
}

@Benchmark
fun read() {
reader.readValue<ListWrapperDatasClass>(data)
}

@Benchmark
fun write() {
writer.writeValue(OutputStream.nullOutputStream(), lists)
}

private fun <T> Class<T>.createWriter(): ObjectWriter {
val mapper = avroMapper()

return mapper.writer(AvroSchema(schema)).forType(this)
}

private fun <T> Class<T>.createReader(): ObjectReader {
val mapper = avroMapper()

return mapper.reader(AvroSchema(schema)).forType(this)
}

private fun avroMapper(): ObjectMapper = AvroMapper()
.disable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
.registerKotlinModule()
.registerModule(AvroJavaTimeModule())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.github.avrokotlin.benchmark.lists

import com.github.avrokotlin.avro4k.Avro
import com.github.avrokotlin.avro4k.schema
import com.github.avrokotlin.benchmark.internal.Clients
import com.github.avrokotlin.benchmark.internal.ClientsGenerator
import com.github.avrokotlin.benchmark.internal.ListWrapperDataClass
import com.github.avrokotlin.benchmark.internal.ListWrapperDatasClass
import kotlinx.benchmark.*
import java.util.concurrent.TimeUnit


@State(Scope.Benchmark)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@BenchmarkMode(Mode.Throughput)
@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)
internal abstract class SerializationListsBenchmark {
lateinit var lists: ListWrapperDatasClass
val schema = Avro.schema<ListWrapperDatasClass>()

@Setup
fun initTestData() {
setup()
lists = ListWrapperDatasClass.create(10, 10000)
prepareBinaryData()
}

abstract fun setup()

abstract fun prepareBinaryData()
}

0 comments on commit 8b78af0

Please sign in to comment.