1 package kotlinx.benchmarks.json 2 3 import com.fasterxml.jackson.databind.* 4 import com.fasterxml.jackson.module.kotlin.* 5 import kotlinx.serialization.* 6 import kotlinx.serialization.json.* 7 import kotlinx.serialization.json.okio.encodeToBufferedSink 8 import okio.blackholeSink 9 import okio.buffer 10 import org.openjdk.jmh.annotations.* 11 import java.io.ByteArrayInputStream 12 import java.io.OutputStream 13 import java.util.concurrent.* 14 15 @Warmup(iterations = 7, time = 1) 16 @Measurement(iterations = 5, time = 1) 17 @BenchmarkMode(Mode.Throughput) 18 @OutputTimeUnit(TimeUnit.MILLISECONDS) 19 @State(Scope.Benchmark) 20 @Fork(2) 21 open class JacksonComparisonBenchmark { 22 23 @Serializable 24 data class DefaultPixelEvent( 25 val version: Int, 26 val dateTime2: String, 27 val serverName: String, 28 val domain: String, 29 val method: String, 30 val clientIp: String, 31 val queryString: String, 32 val userAgent: String, 33 val contentType: String, 34 val browserLanguage: String, 35 val postData: String, 36 val cookies: String 37 ) 38 39 private val objectMapper: ObjectMapper = jacksonObjectMapper() 40 41 private val data = DefaultPixelEvent( 42 version = 1, 43 dateTime2 = System.currentTimeMillis().toString(), 44 serverName = "some-endpoint-qwer", 45 domain = "some.domain.com", 46 method = "POST", 47 clientIp = "127.0.0.1", 48 queryString = "anxa=CASCative&anxv=13.901.16.34566&anxe=FoolbarActive&anxt=E7AFBF15-1761-4343-92C1-78167ED19B1C&anxtv=13.901.16.34566&anxp=%5ECQ6%5Expt292%5ES33656%5Eus&anxsi&anxd=2019-10-08T17%3A03%3A57.246Z&f=00400000&anxr=1571945992297&coid=66abafd0d49f42e58dc7536109395306&userSegment&cwsid=opgkcnbminncdgghighmimmphiooeohh", 49 userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0", 50 contentType = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 51 browserLanguage = "en-US,en;q=0.5", 52 postData = "-", 53 cookies = "_ga=GA1.2.971852807.1546968515" 54 ) 55 56 private val dataWithEscapes = DefaultPixelEvent( 57 version = 1, 58 dateTime2 = System.currentTimeMillis().toString(), 59 serverName = "some-endp\"oint-qwer", 60 domain = "<a href=\"some.domain.com\">", 61 method = "POST", 62 clientIp = "127.0.0.1", 63 queryString = "anxa=CASCative&anxv=13.901.16.34566&anxe=\"FoolbarActive\"&anxt=E7AFBF15-1761-4343-92C1-78167ED19B1C&anxtv=13.901.16.34566&anxp=%5ECQ6%5Expt292%5ES33656%5Eus&anxsi&anxd=2019-10-08T17%3A03%3A57.246Z&f=00400000&anxr=1571945992297&coid=\"66abafd0d49f42e58dc7536109395306\"&userSegment&cwsid=opgkcnbminncdgghighmimmphiooeohh", 64 userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:70.0) Gecko/20100101 Firefox/70.0", 65 contentType = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", 66 browserLanguage = "\"en\"-\"US\",en;\\q=0.5", 67 postData = "-", 68 cookies = "_ga=GA1.2.971852807.1546968515" 69 ) 70 71 private val devNullSink = blackholeSink().buffer() 72 private val devNullStream = object : OutputStream() { writenull73 override fun write(b: Int) {} writenull74 override fun write(b: ByteArray) {} writenull75 override fun write(b: ByteArray, off: Int, len: Int) {} 76 } 77 78 private val stringData = Json.encodeToString(DefaultPixelEvent.serializer(), data) 79 private val utf8BytesData = stringData.toByteArray() 80 81 @Serializable 82 private class SmallDataClass(val id: Int, val name: String) 83 84 private val smallData = SmallDataClass(42, "Vincent") 85 86 @Benchmark jacksonToStringnull87 fun jacksonToString(): String = objectMapper.writeValueAsString(data) 88 89 @Benchmark 90 fun jacksonToStringWithEscapes(): String = objectMapper.writeValueAsString(dataWithEscapes) 91 92 @Benchmark 93 fun jacksonSmallToString(): String = objectMapper.writeValueAsString(smallData) 94 95 @Benchmark 96 fun kotlinToString(): String = Json.encodeToString(DefaultPixelEvent.serializer(), data) 97 98 @Benchmark 99 fun kotlinToStream() = Json.encodeToStream(DefaultPixelEvent.serializer(), data, devNullStream) 100 101 @Benchmark 102 fun kotlinFromStream() = Json.decodeFromStream(DefaultPixelEvent.serializer(), ByteArrayInputStream(utf8BytesData)) 103 104 @Benchmark 105 fun kotlinToOkio() = Json.encodeToBufferedSink(DefaultPixelEvent.serializer(), data, devNullSink) 106 107 @Benchmark 108 fun kotlinToStringWithEscapes(): String = Json.encodeToString(DefaultPixelEvent.serializer(), dataWithEscapes) 109 110 @Benchmark 111 fun kotlinSmallToString(): String = Json.encodeToString(SmallDataClass.serializer(), smallData) 112 113 @Benchmark 114 fun kotlinSmallToStream() = Json.encodeToStream(SmallDataClass.serializer(), smallData, devNullStream) 115 116 @Benchmark 117 fun kotlinSmallToOkio() = Json.encodeToBufferedSink(SmallDataClass.serializer(), smallData, devNullSink) 118 119 @Benchmark 120 fun jacksonFromString(): DefaultPixelEvent = objectMapper.readValue(stringData, DefaultPixelEvent::class.java) 121 122 @Benchmark 123 fun kotlinFromString(): DefaultPixelEvent = Json.decodeFromString(DefaultPixelEvent.serializer(), stringData) 124 } 125