Skip to content

Commit 62252fa

Browse files
samuelAndalonSamuel Vazquez
and
Samuel Vazquez
authored
feat(v6): fastjson2 for serialization of GraphQLResponse and deserialization of GraphQLRequest (#2043)
### 📝 Description cherry pick https://github.com/ExpediaGroup/graphql-kotlin/pull/2040/files --------- Co-authored-by: Samuel Vazquez <[email protected]>
1 parent c0874e2 commit 62252fa

23 files changed

+333
-611
lines changed

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ reactorExtensionsVersion = 1.1.7
3434
slf4jVersion = 1.7.36
3535
springBootVersion = 2.7.2
3636
springVersion = 5.3.22
37-
37+
fastjson2Version = 2.0.48
3838
# test dependency versions
3939
# kotlin-compile-testing has to be using the same kotlin version as the kotlinx-serialization compiler
4040
# kotlin-compile-testing v1.4.9+ requires Kotlin v1.7

servers/graphql-kotlin-server/build.gradle.kts

+11-4
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,19 @@ description = "Common code for running a GraphQL server in any HTTP server frame
44

55
val kotlinCoroutinesVersion: String by project
66
val kotlinxBenchmarkVersion: String by project
7+
val jacksonVersion: String by project
8+
val fastjson2Version: String by project
79

810
plugins {
911
id("org.jetbrains.kotlinx.benchmark")
10-
kotlin("plugin.serialization")
1112
}
1213

13-
val jacksonVersion: String by project
14-
val kotlinxSerializationVersion: String by project
1514
dependencies {
1615
api(project(path = ":graphql-kotlin-schema-generator"))
1716
api(project(path = ":graphql-kotlin-dataloader-instrumentation"))
1817
api(project(path = ":graphql-kotlin-automatic-persisted-queries"))
1918
api("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion")
20-
api("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
19+
api("com.alibaba.fastjson2:fastjson2-kotlin:$fastjson2Version")
2120
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutinesVersion")
2221
}
2322

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

3736
benchmark {
37+
configurations {
38+
register("graphQLRequest") {
39+
include("com.expediagroup.graphql.server.GraphQLServerRequest*")
40+
}
41+
register("graphQLResponse") {
42+
include("com.expediagroup.graphql.server.GraphQLServerResponse*")
43+
}
44+
}
3845
targets {
3946
register("benchmarks") {
4047
this as JvmBenchmarkTarget
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2024 Expedia, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.expediagroup.graphql.server
18+
19+
import com.alibaba.fastjson2.JSON
20+
import com.alibaba.fastjson2.JSONWriter
21+
import com.alibaba.fastjson2.to
22+
import com.expediagroup.graphql.server.types.GraphQLServerRequest
23+
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
24+
import com.fasterxml.jackson.module.kotlin.readValue
25+
import org.openjdk.jmh.annotations.Benchmark
26+
import org.openjdk.jmh.annotations.Fork
27+
import org.openjdk.jmh.annotations.Measurement
28+
import org.openjdk.jmh.annotations.Scope
29+
import org.openjdk.jmh.annotations.Setup
30+
import org.openjdk.jmh.annotations.State
31+
import org.openjdk.jmh.annotations.Warmup
32+
import java.util.concurrent.TimeUnit
33+
34+
@State(Scope.Benchmark)
35+
@Fork(value = 5, jvmArgsAppend = ["--add-modules=jdk.incubator.vector", "-Dfastjson2.readerVector=true"])
36+
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
37+
@Measurement(iterations = 4, time = 5, timeUnit = TimeUnit.SECONDS)
38+
open class GraphQLServerRequestBatchDeserializationBenchmark {
39+
private val mapper = jacksonObjectMapper()
40+
private lateinit var request: String
41+
private lateinit var batchRequest: String
42+
43+
@Setup
44+
fun setUp() {
45+
JSON.config(JSONWriter.Feature.WriteNulls)
46+
val loader = this::class.java.classLoader
47+
val operation = loader.getResource("StarWarsDetails.graphql")!!.readText().replace("\n", "\\n")
48+
val variables = loader.getResource("StarWarsDetailsVariables.json")!!.readText()
49+
batchRequest = """
50+
[
51+
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
52+
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
53+
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
54+
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables }
55+
]
56+
""".trimIndent()
57+
}
58+
59+
@Benchmark
60+
fun JacksonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = mapper.readValue(batchRequest)
61+
62+
@Benchmark
63+
fun FastJsonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = batchRequest.to<GraphQLServerRequest>()
64+
}

servers/graphql-kotlin-server/src/benchmarks/kotlin/GraphQLServerRequestDeserializationBenchmark.kt

+9-22
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616

1717
package com.expediagroup.graphql.server
1818

19-
import com.expediagroup.graphql.server.testtypes.GraphQLServerRequest
20-
import com.expediagroup.graphql.server.testtypes.GraphQLServerRequestKSerializer
19+
import com.alibaba.fastjson2.JSON
20+
import com.alibaba.fastjson2.JSONWriter
21+
import com.alibaba.fastjson2.to
22+
import com.expediagroup.graphql.server.types.GraphQLServerRequest
2123
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
2224
import com.fasterxml.jackson.module.kotlin.readValue
23-
import kotlinx.serialization.json.Json
2425
import org.openjdk.jmh.annotations.Benchmark
2526
import org.openjdk.jmh.annotations.Fork
2627
import org.openjdk.jmh.annotations.Measurement
@@ -31,16 +32,16 @@ import org.openjdk.jmh.annotations.Warmup
3132
import java.util.concurrent.TimeUnit
3233

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

4242
@Setup
4343
fun setUp() {
44+
JSON.config(JSONWriter.Feature.WriteNulls)
4445
val loader = this::class.java.classLoader
4546
val operation = loader.getResource("StarWarsDetails.graphql")!!.readText().replace("\n", "\\n")
4647
val variables = loader.getResource("StarWarsDetailsVariables.json")!!.readText()
@@ -51,25 +52,11 @@ open class GraphQLServerRequestDeserializationBenchmark {
5152
"variables": $variables
5253
}
5354
""".trimIndent()
54-
batchRequest = """
55-
[
56-
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
57-
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
58-
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables },
59-
{ "operationName": "StarWarsDetails", "query": "$operation", "variables": $variables }
60-
]
61-
""".trimIndent()
6255
}
6356

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

6760
@Benchmark
68-
fun JacksonDeserializeGraphQLBatchRequest(): GraphQLServerRequest = mapper.readValue(batchRequest)
69-
70-
@Benchmark
71-
fun KSerializationDeserializeGraphQLRequest(): GraphQLServerRequest = Json.decodeFromString(GraphQLServerRequestKSerializer, request)
72-
73-
@Benchmark
74-
fun KSerializationDeserializeGraphQLBatchRequest(): GraphQLServerRequest = Json.decodeFromString(GraphQLServerRequestKSerializer, batchRequest)
61+
fun FastJsonDeserializeGraphQLRequest(): GraphQLServerRequest = request.to()
7562
}

servers/graphql-kotlin-server/src/benchmarks/kotlin/GraphQLServerRequestSerializationBenchmark.kt

-70
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2024 Expedia, Inc
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.expediagroup.graphql.server
18+
19+
import com.alibaba.fastjson2.JSON
20+
import com.alibaba.fastjson2.JSONWriter
21+
import com.expediagroup.graphql.server.types.GraphQLBatchResponse
22+
import com.expediagroup.graphql.server.types.GraphQLResponse
23+
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
24+
import com.fasterxml.jackson.module.kotlin.readValue
25+
import org.openjdk.jmh.annotations.Benchmark
26+
import org.openjdk.jmh.annotations.Fork
27+
import org.openjdk.jmh.annotations.Measurement
28+
import org.openjdk.jmh.annotations.Scope
29+
import org.openjdk.jmh.annotations.Setup
30+
import org.openjdk.jmh.annotations.State
31+
import org.openjdk.jmh.annotations.Warmup
32+
import java.util.concurrent.TimeUnit
33+
34+
@State(Scope.Benchmark)
35+
@Fork(value = 5, jvmArgsAppend = ["--add-modules=jdk.incubator.vector", "-Dfastjson2.readerVector=true"])
36+
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
37+
@Measurement(iterations = 4, time = 5, timeUnit = TimeUnit.SECONDS)
38+
open class GraphQLServerResponseBatchSerializationBenchmark {
39+
private val mapper = jacksonObjectMapper()
40+
private lateinit var batchResponse: GraphQLBatchResponse
41+
42+
@Setup
43+
fun setUp() {
44+
JSON.config(JSONWriter.Feature.WriteNulls)
45+
val data = mapper.readValue<Map<String, Any?>>(
46+
this::class.java.classLoader.getResourceAsStream("StarWarsDetailsResponse.json")!!
47+
)
48+
batchResponse = GraphQLBatchResponse(
49+
listOf(
50+
GraphQLResponse(data),
51+
GraphQLResponse(data),
52+
GraphQLResponse(data),
53+
GraphQLResponse(data)
54+
)
55+
)
56+
}
57+
58+
@Benchmark
59+
fun JacksonSerializeGraphQLBatchResponse(): String = mapper.writeValueAsString(batchResponse)
60+
61+
@Benchmark
62+
fun FastJsonSerializeGraphQLBatchResponse(): String = JSON.toJSONString(batchResponse)
63+
}

servers/graphql-kotlin-server/src/benchmarks/kotlin/GraphQLServerResponseDeserializationBenchmark.kt

-66
This file was deleted.

0 commit comments

Comments
 (0)