Skip to content

Commit

Permalink
feat(v6): fastjson2 for serialization of GraphQLResponse and deserial…
Browse files Browse the repository at this point in the history
…ization of GraphQLRequest (#2043)

### 📝 Description
cherry pick
https://github.com/ExpediaGroup/graphql-kotlin/pull/2040/files

---------

Co-authored-by: Samuel Vazquez <[email protected]>
  • Loading branch information
samuelAndalon and Samuel Vazquez authored Oct 5, 2024
1 parent c0874e2 commit 62252fa
Show file tree
Hide file tree
Showing 23 changed files with 333 additions and 611 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ reactorExtensionsVersion = 1.1.7
slf4jVersion = 1.7.36
springBootVersion = 2.7.2
springVersion = 5.3.22

fastjson2Version = 2.0.48
# test dependency versions
# kotlin-compile-testing has to be using the same kotlin version as the kotlinx-serialization compiler
# kotlin-compile-testing v1.4.9+ requires Kotlin v1.7
Expand Down
15 changes: 11 additions & 4 deletions servers/graphql-kotlin-server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@ description = "Common code for running a GraphQL server in any HTTP server frame

val kotlinCoroutinesVersion: String by project
val kotlinxBenchmarkVersion: String by project
val jacksonVersion: String by project
val fastjson2Version: String by project

plugins {
id("org.jetbrains.kotlinx.benchmark")
kotlin("plugin.serialization")
}

val jacksonVersion: String by project
val kotlinxSerializationVersion: String by project
dependencies {
api(project(path = ":graphql-kotlin-schema-generator"))
api(project(path = ":graphql-kotlin-dataloader-instrumentation"))
api(project(path = ":graphql-kotlin-automatic-persisted-queries"))
api("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion")
api("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
api("com.alibaba.fastjson2:fastjson2-kotlin:$fastjson2Version")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutinesVersion")
}

Expand All @@ -35,6 +34,14 @@ kotlin.sourceSets.getByName("benchmarks") {
}

benchmark {
configurations {
register("graphQLRequest") {
include("com.expediagroup.graphql.server.GraphQLServerRequest*")
}
register("graphQLResponse") {
include("com.expediagroup.graphql.server.GraphQLServerResponse*")
}
}
targets {
register("benchmarks") {
this as JvmBenchmarkTarget
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2024 Expedia, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.expediagroup.graphql.server

import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONWriter
import com.alibaba.fastjson2.to
import com.expediagroup.graphql.server.types.GraphQLServerRequest
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Fork
import org.openjdk.jmh.annotations.Measurement
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.Setup
import org.openjdk.jmh.annotations.State
import org.openjdk.jmh.annotations.Warmup
import java.util.concurrent.TimeUnit

@State(Scope.Benchmark)
@Fork(value = 5, jvmArgsAppend = ["--add-modules=jdk.incubator.vector", "-Dfastjson2.readerVector=true"])
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 4, time = 5, timeUnit = TimeUnit.SECONDS)
open class GraphQLServerRequestBatchDeserializationBenchmark {
private val mapper = jacksonObjectMapper()
private lateinit var request: String
private lateinit var batchRequest: String

@Setup
fun setUp() {
JSON.config(JSONWriter.Feature.WriteNulls)
val loader = this::class.java.classLoader
val operation = loader.getResource("StarWarsDetails.graphql")!!.readText().replace("\n", "\\n")
val variables = loader.getResource("StarWarsDetailsVariables.json")!!.readText()
batchRequest = """
[
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables }
]
""".trimIndent()
}

@Benchmark
fun JacksonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = mapper.readValue(batchRequest)

@Benchmark
fun FastJsonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = batchRequest.to<GraphQLServerRequest>()
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@

package com.expediagroup.graphql.server

import com.expediagroup.graphql.server.testtypes.GraphQLServerRequest
import com.expediagroup.graphql.server.testtypes.GraphQLServerRequestKSerializer
import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONWriter
import com.alibaba.fastjson2.to
import com.expediagroup.graphql.server.types.GraphQLServerRequest
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import kotlinx.serialization.json.Json
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Fork
import org.openjdk.jmh.annotations.Measurement
Expand All @@ -31,16 +32,16 @@ import org.openjdk.jmh.annotations.Warmup
import java.util.concurrent.TimeUnit

@State(Scope.Benchmark)
@Fork(5)
@Warmup(iterations = 1, time = 5, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(value = 5, jvmArgsAppend = ["--add-modules=jdk.incubator.vector", "-Dfastjson2.readerVector=true"])
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 4, time = 5, timeUnit = TimeUnit.SECONDS)
open class GraphQLServerRequestDeserializationBenchmark {
private val mapper = jacksonObjectMapper()
private lateinit var request: String
private lateinit var batchRequest: String

@Setup
fun setUp() {
JSON.config(JSONWriter.Feature.WriteNulls)
val loader = this::class.java.classLoader
val operation = loader.getResource("StarWarsDetails.graphql")!!.readText().replace("\n", "\\n")
val variables = loader.getResource("StarWarsDetailsVariables.json")!!.readText()
Expand All @@ -51,25 +52,11 @@ open class GraphQLServerRequestDeserializationBenchmark {
"variables": $variables
}
""".trimIndent()
batchRequest = """
[
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables }
]
""".trimIndent()
}

@Benchmark
fun JacksonDeserializeGraphQLRequest(): GraphQLServerRequest = mapper.readValue(request)

@Benchmark
fun JacksonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = mapper.readValue(batchRequest)

@Benchmark
fun KSerializationDeserializeGraphQLRequest(): GraphQLServerRequest = Json.decodeFromString(GraphQLServerRequestKSerializer, request)

@Benchmark
fun KSerializationDeserializeGraphQLBatchRequest(): GraphQLServerRequest = Json.decodeFromString(GraphQLServerRequestKSerializer, batchRequest)
fun FastJsonDeserializeGraphQLRequest(): GraphQLServerRequest = request.to()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2024 Expedia, Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.expediagroup.graphql.server

import com.alibaba.fastjson2.JSON
import com.alibaba.fastjson2.JSONWriter
import com.expediagroup.graphql.server.types.GraphQLBatchResponse
import com.expediagroup.graphql.server.types.GraphQLResponse
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Fork
import org.openjdk.jmh.annotations.Measurement
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.Setup
import org.openjdk.jmh.annotations.State
import org.openjdk.jmh.annotations.Warmup
import java.util.concurrent.TimeUnit

@State(Scope.Benchmark)
@Fork(value = 5, jvmArgsAppend = ["--add-modules=jdk.incubator.vector", "-Dfastjson2.readerVector=true"])
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 4, time = 5, timeUnit = TimeUnit.SECONDS)
open class GraphQLServerResponseBatchSerializationBenchmark {
private val mapper = jacksonObjectMapper()
private lateinit var batchResponse: GraphQLBatchResponse

@Setup
fun setUp() {
JSON.config(JSONWriter.Feature.WriteNulls)
val data = mapper.readValue<Map<String, Any?>>(
this::class.java.classLoader.getResourceAsStream("StarWarsDetailsResponse.json")!!
)
batchResponse = GraphQLBatchResponse(
listOf(
GraphQLResponse(data),
GraphQLResponse(data),
GraphQLResponse(data),
GraphQLResponse(data)
)
)
}

@Benchmark
fun JacksonSerializeGraphQLBatchResponse(): String = mapper.writeValueAsString(batchResponse)

@Benchmark
fun FastJsonSerializeGraphQLBatchResponse(): String = JSON.toJSONString(batchResponse)
}

This file was deleted.

Loading

0 comments on commit 62252fa

Please sign in to comment.