Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: No more kotlin-reflect for logical types #214

Merged
merged 10 commits into from
May 23, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ jobs:
run: find . -type d -name 'reports' | zip -@ -r build-reports.zip
- name: Upload the build report
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: error-report
path: build-reports.zip
2 changes: 1 addition & 1 deletion .github/workflows/pr.yml
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ jobs:

- name: Upload the build report
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: error-report
path: build-reports.zip
82 changes: 50 additions & 32 deletions README.md

Large diffs are not rendered by default.

117 changes: 98 additions & 19 deletions api/avro4k-core.api

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion benchmark/README.md
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ This project contains a benchmark that compares the serialization / deserializat
## Results

<details>
<summary>Macbook air M2</summary>
<summary>Macbook air M2 - without direct encoding</summary>

```
Benchmark Mode Cnt Score Error Units
@@ -23,6 +23,21 @@ For the moment, Jackson Avro is faster than Avro4k because Avro4k is still not d

</details>

<br>

<details>
<summary>Macbook air M2 - with direct encoding but without direct decoding</summary>

```
Benchmark Mode Cnt Score Error Units
Avro4kClientsBenchmark.read thrpt 2 471489.689 ops/s
Avro4kClientsBenchmark.write thrpt 2 686791.337 ops/s
JacksonAvroClientsBenchmark.read thrpt 2 513425.052 ops/s
JacksonAvroClientsBenchmark.write thrpt 2 627412.940 ops/s
```

</details>

## Run the benchmark locally

Just execute the benchmark:
8 changes: 8 additions & 0 deletions benchmark/api/benchmark.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
public abstract interface class com/github/avrokotlin/benchmark/Partner {
public static final field Companion Lcom/github/avrokotlin/benchmark/Partner$Companion;
}

public final class com/github/avrokotlin/benchmark/Partner$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

Original file line number Diff line number Diff line change
@@ -5,8 +5,9 @@ import com.github.avrokotlin.avro4k.decodeFromByteArray
import com.github.avrokotlin.avro4k.encodeToByteArray
import kotlinx.benchmark.Benchmark

internal class Avro4kClientsStaticReadBenchmark {
fun main() {
internal object Avro4kClientsStaticReadBenchmark {
@JvmStatic
fun main(vararg args: String) {
Avro4kClientsBenchmark().apply {
initTestData()
for (i in 0 until 1000000) {
@@ -17,8 +18,9 @@ internal class Avro4kClientsStaticReadBenchmark {
}
}

internal class Avro4kClientsStaticWriteBenchmark {
fun main() {
internal object Avro4kClientsStaticWriteBenchmark {
@JvmStatic
fun main(vararg args: String) {
Avro4kClientsBenchmark().apply {
initTestData()
for (i in 0 until 1000000) {
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
@file:OptIn(ExperimentalSerializationApi::class)

package com.github.avrokotlin.benchmark

import com.github.avrokotlin.avro4k.AvroDecimal
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import java.math.BigDecimal
import java.time.Instant
import java.time.LocalDate
import java.util.*
import java.util.UUID
import kotlinx.serialization.Contextual
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable

@Serializable
internal data class Clients(
@@ -37,7 +40,7 @@ internal data class Client(
var latitude : Double = 0.0,
var longitude: Double = 0.0,
var tags: List<String> = emptyList(),
var partners: List<Partner> = emptyList(),
var partners: List<Partner?> = emptyList(),
)

@Serializable
@@ -46,10 +49,28 @@ internal enum class EyeColor {
BLUE,
GREEN;
}

@Serializable
sealed interface Partner

@Serializable
internal class Partner(
internal class GoodPartner(
val id: Long = 0,
val name: String? = null,
@Contextual
val since: Instant? = null
)
) : Partner

@Serializable
internal class BadPartner(
val id: Long = 0,
val name: String? = null,
@Contextual
val since: Instant? = null
) : Partner

@Serializable
internal enum class Stranger : Partner {
KNOWN_STRANGER,
UNKNOWN_STRANGER
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.github.avrokotlin.benchmark.gen

import com.github.avrokotlin.benchmark.BadPartner
import com.github.avrokotlin.benchmark.Client
import com.github.avrokotlin.benchmark.Clients
import com.github.avrokotlin.benchmark.EyeColor
import com.github.avrokotlin.benchmark.GoodPartner
import com.github.avrokotlin.benchmark.Partner
import com.github.avrokotlin.benchmark.Stranger

import java.time.LocalDate
import java.time.OffsetDateTime
@@ -87,7 +90,7 @@ internal object ClientsGenerator {
}
u.tags = tags
val nPartners: Int = RandomUtils.nextInt(0, 30)
val partners = mutableListOf<Partner>()
val partners = mutableListOf<Partner?>()
expectedSize += 13 // ,'partners':[]
for (i in 0 until nPartners) {
if (expectedSize > sizeAvailable) {
@@ -105,7 +108,15 @@ internal object ClientsGenerator {
RandomUtils.nextInt(1000000000),
ZoneOffset.UTC
).toInstant()
partners.add(Partner(id, name, at))
partners.add(
when (RandomUtils.nextInt(4)) {
0 -> GoodPartner(id, name, at)
1 -> BadPartner(id, name, at)
2 -> if (RandomUtils.nextBoolean()) Stranger.KNOWN_STRANGER else Stranger.UNKNOWN_STRANGER
3 -> null
else -> throw IllegalStateException("Unexpected value")
}
)
expectedSize += id.toString().length + name.length + 50 // {'id':'','name':'','since':''},
}
u.partners = partners
Original file line number Diff line number Diff line change
@@ -58,6 +58,10 @@ internal object RandomUtils {
return RANDOM.nextLong()
}

fun nextBoolean(): Boolean {
return RANDOM.nextBoolean()
}

fun longArray(size: Int): LongArray {
val arr = LongArray(size)
for (i in 0..<size) {
40 changes: 9 additions & 31 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

buildscript {
repositories {
mavenCentral()
mavenLocal()
google()
gradlePluginPortal()
}
}

plugins {
java
id("java-library")
@@ -37,32 +25,22 @@ dependencies {
api(libs.apache.avro)
api(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)
implementation(kotlin("reflect"))
testImplementation(libs.kotest.junit5)
testImplementation(libs.kotest.core)
testImplementation(libs.kotest.json)
testImplementation(libs.kotest.property)
}

kotlin {
explicitApi = ExplicitApiMode.Strict
}

apiValidation {
nonPublicMarkers.add("kotlinx.serialization.ExperimentalSerializationApi")
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.apiVersion = "1.6"
kotlinOptions.languageVersion = "1.6"
kotlinOptions.freeCompilerArgs +=
listOf(
"-Xexplicit-api=strict",
"-opt-in=kotlinx.serialization.ExperimentalSerializationApi",
"-opt-in=kotlin.RequiresOptIn",
"-Xcontext-receivers"
)
explicitApi()

compilerOptions {
optIn = listOf("kotlin.RequiresOptIn", "kotlinx.serialization.ExperimentalSerializationApi")
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8)
apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
freeCompilerArgs = listOf("-Xcontext-receivers")
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
18 changes: 16 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -5,19 +5,33 @@ pluginManagement {
}
}

plugins {
id("com.gradle.enterprise") version ("3.16.2")
}

rootProject.name = "avro4k-core"

include("benchmark")

gradleEnterprise {
if (System.getenv("CI") != null) {
buildScan {
publishAlways()
termsOfServiceUrl = "https://gradle.com/terms-of-service"
termsOfServiceAgree = "yes"
}
}
}

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("kotlin", "1.9.23")
version("kotlin", "2.0.0")
version("jvm", "21")

library("apache-avro", "org.apache.avro", "avro").version("1.11.3")

val kotlinxSerialization = "1.6.3"
val kotlinxSerialization = "1.7.0-RC"
library("kotlinx-serialization-core", "org.jetbrains.kotlinx", "kotlinx-serialization-core").version(kotlinxSerialization)
library("kotlinx-serialization-json", "org.jetbrains.kotlinx", "kotlinx-serialization-json").version(kotlinxSerialization)

Loading