1 /* 2 * Copyright 2021 Google Inc. All rights reserved. 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 * http://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 package com.google.flatbuffers.kotlin.benchmark 17 18 import com.google.flatbuffers.kotlin.ArrayReadBuffer 19 import com.google.flatbuffers.kotlin.JSONParser 20 import com.google.flatbuffers.kotlin.Reference 21 import com.google.flatbuffers.kotlin.toJson 22 import com.google.gson.Gson 23 import com.google.gson.JsonObject 24 import com.google.gson.JsonParser 25 import com.squareup.moshi.Moshi 26 import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory 27 import kotlinx.benchmark.Blackhole 28 import okio.Buffer 29 import org.openjdk.jmh.annotations.Benchmark 30 import org.openjdk.jmh.annotations.BenchmarkMode 31 import org.openjdk.jmh.annotations.Measurement 32 import org.openjdk.jmh.annotations.Mode 33 import org.openjdk.jmh.annotations.OutputTimeUnit 34 import org.openjdk.jmh.annotations.Scope 35 import org.openjdk.jmh.annotations.State 36 import java.io.ByteArrayInputStream 37 import java.io.InputStreamReader 38 import java.util.concurrent.TimeUnit 39 40 @State(Scope.Benchmark) 41 @BenchmarkMode(Mode.AverageTime) 42 @OutputTimeUnit(TimeUnit.MICROSECONDS) 43 @Measurement(iterations = 100, time = 1, timeUnit = TimeUnit.MICROSECONDS) 44 class JsonBenchmark { 45 46 final val moshi = Moshi.Builder() 47 .addLast(KotlinJsonAdapterFactory()) 48 .build() 49 final val moshiAdapter = moshi.adapter(Map::class.java) 50 51 final val gson = Gson() 52 final val gsonParser = JsonParser() 53 54 val fbParser = JSONParser() 55 56 final val twitterData = this.javaClass.classLoader.getResourceAsStream("twitter.json")!!.readBytes() 57 final val canadaData = this.javaClass.classLoader.getResourceAsStream("canada.json")!!.readBytes() 58 final val citmData = this.javaClass.classLoader.getResourceAsStream("citm_catalog.json")!!.readBytes() 59 60 val fbCitmRef = JSONParser().parse(ArrayReadBuffer(citmData)) 61 val moshiCitmRef = moshi.adapter(Map::class.java).fromJson(citmData.decodeToString()) 62 val gsonCitmRef = gsonParser.parse(citmData.decodeToString()) 63 readFlexBuffersnull64 fun readFlexBuffers(data: ByteArray): Reference = fbParser.parse(ArrayReadBuffer(data)) 65 66 fun readMoshi(data: ByteArray): Map<*, *>? { 67 val buffer = Buffer().write(data) 68 return moshiAdapter.fromJson(buffer) 69 } 70 readGsonnull71 fun readGson(data: ByteArray): JsonObject { 72 val parser = JsonParser() 73 val jsonReader = InputStreamReader(ByteArrayInputStream(data)) 74 return parser.parse(jsonReader).asJsonObject 75 } 76 77 // TWITTER 78 @Benchmark readTwitterFlexBuffersnull79 fun readTwitterFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(twitterData)) 80 @Benchmark 81 fun readTwitterMoshi(hole: Blackhole?) = hole?.consume(readMoshi(twitterData)) 82 @Benchmark 83 fun readTwitterGson(hole: Blackhole?) = hole?.consume(readGson(twitterData)) 84 85 @Benchmark 86 fun roundTripTwitterFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(twitterData).toJson()) 87 @Benchmark 88 fun roundTripTwitterMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(twitterData))) 89 @Benchmark 90 fun roundTripTwitterGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(twitterData))) 91 92 // CITM 93 @Benchmark 94 fun readCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(citmData)) 95 @Benchmark 96 fun readCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(citmData))) 97 @Benchmark 98 fun readCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(citmData))) 99 100 @Benchmark 101 fun roundTripCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(citmData).toJson()) 102 @Benchmark 103 fun roundTripCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(readMoshi(citmData))) 104 @Benchmark 105 fun roundTripCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(readGson(citmData))) 106 107 @Benchmark 108 fun writeCITMFlexBuffers(hole: Blackhole? = null) = hole?.consume(fbCitmRef.toJson()) 109 @Benchmark 110 fun writeCITMMoshi(hole: Blackhole?) = hole?.consume(moshiAdapter.toJson(moshiCitmRef)) 111 @Benchmark 112 fun writeCITMGson(hole: Blackhole?) = hole?.consume(gson.toJson(gsonCitmRef)) 113 114 // CANADA 115 @Benchmark 116 fun readCanadaFlexBuffers(hole: Blackhole? = null) = hole?.consume(readFlexBuffers(canadaData)) 117 @Benchmark 118 fun readCanadaMoshi(hole: Blackhole?) = hole?.consume(readMoshi(canadaData)) 119 @Benchmark 120 fun readCanadaGson(hole: Blackhole?) = hole?.consume(readGson(canadaData)) 121 } 122