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.ArrayReadWriteBuf 19 import com.google.flatbuffers.FlexBuffers 20 import com.google.flatbuffers.FlexBuffersBuilder.BUILDER_FLAG_SHARE_ALL 21 import com.google.flatbuffers.kotlin.FlexBuffersBuilder 22 import com.google.flatbuffers.kotlin.getRoot 23 import kotlinx.benchmark.Blackhole 24 import org.openjdk.jmh.annotations.Benchmark 25 import org.openjdk.jmh.annotations.BenchmarkMode 26 import org.openjdk.jmh.annotations.Measurement 27 import org.openjdk.jmh.annotations.Mode 28 import org.openjdk.jmh.annotations.OutputTimeUnit 29 import org.openjdk.jmh.annotations.Scope 30 import org.openjdk.jmh.annotations.Setup 31 import org.openjdk.jmh.annotations.State 32 import java.util.concurrent.TimeUnit 33 34 @State(Scope.Benchmark) 35 @BenchmarkMode(Mode.AverageTime) 36 @OutputTimeUnit(TimeUnit.NANOSECONDS) 37 @Measurement(iterations = 20, time = 1, timeUnit = TimeUnit.NANOSECONDS) 38 class FlexBuffersBenchmark { 39 40 var initialCapacity = 1024 41 var value: Double = 0.0 <lambda>null42 val stringKey = Array(500) { "Ḧ̵̘́ȩ̵̐myFairlyBigKey$it" } <lambda>null43 val stringValue = Array(500) { "Ḧ̵̘́ȩ̵̐myFairlyBigValue$it" } <lambda>null44 val bigIntArray = IntArray(5000) { it } 45 46 @Setup setUpnull47 fun setUp() { 48 value = 3.0 49 } 50 51 @Benchmark mapKotlinnull52 fun mapKotlin(blackhole: Blackhole) { 53 val kBuilder = FlexBuffersBuilder(initialCapacity, FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS) 54 kBuilder.putMap { 55 this["hello"] = "world" 56 this["int"] = 10 57 this["float"] = 12.3 58 this["intarray"] = bigIntArray 59 this.putMap("myMap") { 60 this["cool"] = "beans" 61 } 62 } 63 val ref = getRoot(kBuilder.finish()) 64 val map = ref.toMap() 65 blackhole.consume(map.size) 66 blackhole.consume(map["hello"].toString()) 67 blackhole.consume(map["int"].toInt()) 68 blackhole.consume(map["float"].toDouble()) 69 blackhole.consume(map["intarray"].toIntArray()) 70 blackhole.consume(ref["myMap"]["cool"].toString()) 71 blackhole.consume(ref["invalid_key"].isNull) 72 } 73 74 @Benchmark mapJavanull75 fun mapJava(blackhole: Blackhole) { 76 val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL) 77 val startMap = jBuilder.startMap() 78 jBuilder.putString("hello", "world") 79 jBuilder.putInt("int", 10) 80 jBuilder.putFloat("float", 12.3) 81 82 val startVec = jBuilder.startVector() 83 bigIntArray.forEach { jBuilder.putInt(it) } 84 jBuilder.endVector("intarray", startVec, true, false) 85 86 val startInnerMap = jBuilder.startMap() 87 jBuilder.putString("cool", "beans") 88 jBuilder.endMap("myMap", startInnerMap) 89 90 jBuilder.endMap(null, startMap) 91 val ref = FlexBuffers.getRoot(jBuilder.finish()) 92 val map = ref.asMap() 93 blackhole.consume(map.size()) 94 blackhole.consume(map.get("hello").toString()) 95 blackhole.consume(map.get("int").asInt()) 96 blackhole.consume(map.get("float").asFloat()) 97 val vec = map.get("intarray").asVector() 98 blackhole.consume(IntArray(vec.size()) { vec.get(it).asInt() }) 99 100 blackhole.consume(ref.asMap()["myMap"].asMap()["cool"].toString()) 101 blackhole.consume(ref.asMap()["invalid_key"].isNull) 102 } 103 104 @Benchmark intArrayKotlinnull105 fun intArrayKotlin(blackhole: Blackhole) { 106 val kBuilder = FlexBuffersBuilder(initialCapacity, FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS) 107 kBuilder.put(bigIntArray) 108 val root = getRoot(kBuilder.finish()) 109 blackhole.consume(root.toIntArray()) 110 } 111 112 @Benchmark intArrayJavanull113 fun intArrayJava(blackhole: Blackhole) { 114 val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL) 115 val v = jBuilder.startVector() 116 bigIntArray.forEach { jBuilder.putInt(it) } 117 jBuilder.endVector(null, v, true, false) 118 jBuilder.finish() 119 val root = FlexBuffers.getRoot(jBuilder.buffer) 120 val vec = root.asVector() 121 blackhole.consume( 122 IntArray(vec.size()) { 123 vec[it].asInt() 124 } 125 ) 126 } 127 128 @Benchmark stringArrayKotlinnull129 fun stringArrayKotlin(blackhole: Blackhole) { 130 val kBuilder = FlexBuffersBuilder(initialCapacity, FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS) 131 kBuilder.putVector { stringValue.forEach { kBuilder.put(it) } } 132 kBuilder.finish() 133 val root = getRoot(kBuilder.buffer) 134 val vec = root.toVector() 135 blackhole.consume(Array(vec.size) { vec[it].toString() }) 136 } 137 138 @Benchmark stringArrayJavanull139 fun stringArrayJava(blackhole: Blackhole) { 140 val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL) 141 val v = jBuilder.startVector() 142 stringValue.forEach { jBuilder.putString(it) } 143 jBuilder.endVector(null, v, false, false) 144 jBuilder.finish() 145 val root = FlexBuffers.getRoot(jBuilder.buffer) 146 val vec = root.asVector() 147 blackhole.consume(Array(vec.size()) { vec[it].toString() }) 148 } 149 150 @Benchmark stringMapKotlinnull151 fun stringMapKotlin(blackhole: Blackhole) { 152 val kBuilder = FlexBuffersBuilder(initialCapacity, FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS) 153 val pos = kBuilder.startMap() 154 for (i in stringKey.indices) { 155 kBuilder[stringKey[i]] = stringValue[i] 156 } 157 kBuilder.endMap(pos) 158 val ref = getRoot(kBuilder.finish()) 159 val map = ref.toMap() 160 val keys = map.keys 161 162 for (key in keys) { 163 blackhole.consume(map[key.toString()].toString()) 164 } 165 } 166 167 @Benchmark stringMapBytIndexKotlinnull168 fun stringMapBytIndexKotlin(blackhole: Blackhole) { 169 val kBuilder = FlexBuffersBuilder(initialCapacity, FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS) 170 val pos = kBuilder.startMap() 171 for (i in stringKey.indices) { 172 kBuilder[stringKey[i]] = stringValue[i] 173 } 174 kBuilder.endMap(pos) 175 val ref = getRoot(kBuilder.finish()) 176 val map = ref.toMap() 177 for (index in 0 until map.size) { 178 blackhole.consume(map[index].toString()) 179 } 180 } 181 182 @Benchmark stringMapJavanull183 fun stringMapJava(blackhole: Blackhole) { 184 val jBuilder = com.google.flatbuffers.FlexBuffersBuilder(ArrayReadWriteBuf(initialCapacity), BUILDER_FLAG_SHARE_ALL) 185 val v = jBuilder.startMap() 186 for (i in stringKey.indices) { 187 jBuilder.putString(stringKey[i], stringValue[i]) 188 } 189 jBuilder.endMap(null, v) 190 val ref = FlexBuffers.getRoot(jBuilder.finish()) 191 val map = ref.asMap() 192 val keyVec = map.keys() 193 for (i in 0 until keyVec.size()) { 194 val s = keyVec[i].toString() 195 blackhole.consume(map[s].toString()) 196 } 197 } 198 } 199