Skip to content

Commit

Permalink
Add benchmarks for parsing (and decoding) of numbers by different cir…
Browse files Browse the repository at this point in the history
…ce parsers (and decoders)
  • Loading branch information
plokhotnyuk committed Oct 17, 2024
1 parent 16caf35 commit 54e8e48
Show file tree
Hide file tree
Showing 6 changed files with 688 additions and 0 deletions.
113 changes: 113 additions & 0 deletions circe-jawn.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//> using jmh
//> using jmhVersion 1.37
//> using dep "com.epam.deltix:dfp:1.0.3"
//> using dep "io.circe::circe-jawn:0.14.10"
package bench

import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit
import io.circe.*
import io.circe.Decoder.*
import io.circe.jawn.*
import com.epam.deltix.dfp.{Decimal64, Decimal64Utils}
import scala.util.control.NonFatal

implicit val decimal64Decoder: Decoder[Decimal64] = new Decoder[Decimal64] {
final def apply(c: HCursor): Result[Decimal64] = try {
val x = c.value
if (x.isNumber) {
x.asNumber match {
case Some(n) => n.toBigDecimal match {
case Some(bd) => canonizedDecimal64Result(Decimal64Utils.fromBigDecimalExact(bd.bigDecimal))
case _ => numberError(c)
}
case _ => numberError(c)
}
} else if (x.isString) {
x.asString match {
case Some(s) => canonizedDecimal64Result(Decimal64Utils.parse(s))
case _ => numberError(c)
}
} else numberError(c)
} catch {
case NonFatal(_) => numberError(c)
}

private[this] def canonizedDecimal64Result(x: Long) = new Right(Decimal64.fromUnderlying(Decimal64Utils.canonize(x)))

private[this] def numberError(c: HCursor) = new Left(DecodingFailure("expected decimal64 number", c.history))
}

@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
class Benchmarks {
var jsonNumberBytes: Array[Byte] = Array(0)
var jsonStringBytes: Array[Byte] = Array(0)

@Param(Array("1", "10", "100", "1000", "10000", "100000", "1000000"))
var size: Int = 10

@Setup
def setup(): Unit = {
jsonNumberBytes = ("1" + "0" * (size - 1)).getBytes
jsonStringBytes = ("\"1" + "0" * (size - 1) + "\"").getBytes
}

@Benchmark
def circeDecimal64FromJsonNumber() = decodeByteArray[Decimal64](jsonNumberBytes)

@Benchmark
def circeDecimal64FromJsonString() = decodeByteArray[Decimal64](jsonStringBytes)

@Benchmark
def circeBigIntFromJsonNumber() = decodeByteArray[BigInt](jsonNumberBytes)

@Benchmark
def circeBigIntFromJsonString() = decodeByteArray[BigInt](jsonStringBytes)

@Benchmark
def circeBigDecimalFromJsonNumber() = decodeByteArray[BigDecimal](jsonNumberBytes)

@Benchmark
def circeBigDecimalFromJsonString() = decodeByteArray[BigDecimal](jsonStringBytes)

@Benchmark
def circeByteFromJsonNumber() = decodeByteArray[Byte](jsonNumberBytes)

@Benchmark
def circeByteFromJsonString() = decodeByteArray[Byte](jsonStringBytes)

@Benchmark
def circeShortFromJsonNumber() = decodeByteArray[Short](jsonNumberBytes)

@Benchmark
def circeShortFromJsonString() = decodeByteArray[Short](jsonStringBytes)

@Benchmark
def circeIntFromJsonNumber() = decodeByteArray[Int](jsonNumberBytes)

@Benchmark
def circeIntFromJsonString() = decodeByteArray[Int](jsonStringBytes)

@Benchmark
def circeLongFromJsonNumber() = decodeByteArray[Long](jsonNumberBytes)

@Benchmark
def circeLongFromJsonString() = decodeByteArray[Long](jsonStringBytes)

@Benchmark
def circeFloatFromJsonNumber() = decodeByteArray[Float](jsonNumberBytes)

@Benchmark
def circeFloatFromJsonString() = decodeByteArray[Float](jsonStringBytes)

@Benchmark
def circeDoubleFromJsonNumber() = decodeByteArray[Double](jsonNumberBytes)

@Benchmark
def circeDoubleFromJsonString() = decodeByteArray[Double](jsonStringBytes)
}
127 changes: 127 additions & 0 deletions circe-jawn.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
Benchmark (size) Mode Cnt Score Error Units
Benchmarks.circeBigDecimalFromJsonNumber 1 thrpt 39476117.660 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 10 thrpt 23870438.801 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 100 thrpt 1951912.610 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 1000 thrpt 76296.701 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 10000 thrpt 871.338 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 100000 thrpt 9.511 ops/s
Benchmarks.circeBigDecimalFromJsonNumber 1000000 thrpt 0.086 ops/s
Benchmarks.circeBigDecimalFromJsonString 1 thrpt 14053935.026 ops/s
Benchmarks.circeBigDecimalFromJsonString 10 thrpt 9814810.112 ops/s
Benchmarks.circeBigDecimalFromJsonString 100 thrpt 1715046.478 ops/s
Benchmarks.circeBigDecimalFromJsonString 1000 thrpt 74286.966 ops/s
Benchmarks.circeBigDecimalFromJsonString 10000 thrpt 920.533 ops/s
Benchmarks.circeBigDecimalFromJsonString 100000 thrpt 9.505 ops/s
Benchmarks.circeBigDecimalFromJsonString 1000000 thrpt 0.086 ops/s
Benchmarks.circeBigIntFromJsonNumber 1 thrpt 41303826.019 ops/s
Benchmarks.circeBigIntFromJsonNumber 10 thrpt 27441945.796 ops/s
Benchmarks.circeBigIntFromJsonNumber 100 thrpt 4995149.026 ops/s
Benchmarks.circeBigIntFromJsonNumber 1000 thrpt 611914.994 ops/s
Benchmarks.circeBigIntFromJsonNumber 10000 thrpt 18585.182 ops/s
Benchmarks.circeBigIntFromJsonNumber 100000 thrpt 537.163 ops/s
Benchmarks.circeBigIntFromJsonNumber 1000000 thrpt 969.438 ops/s
Benchmarks.circeBigIntFromJsonString 1 thrpt 10336573.789 ops/s
Benchmarks.circeBigIntFromJsonString 10 thrpt 6984835.276 ops/s
Benchmarks.circeBigIntFromJsonString 100 thrpt 3459097.660 ops/s
Benchmarks.circeBigIntFromJsonString 1000 thrpt 514351.068 ops/s
Benchmarks.circeBigIntFromJsonString 10000 thrpt 17358.881 ops/s
Benchmarks.circeBigIntFromJsonString 100000 thrpt 523.623 ops/s
Benchmarks.circeBigIntFromJsonString 1000000 thrpt 709.427 ops/s
Benchmarks.circeByteFromJsonNumber 1 thrpt 42723593.988 ops/s
Benchmarks.circeByteFromJsonNumber 10 thrpt 21215282.283 ops/s
Benchmarks.circeByteFromJsonNumber 100 thrpt 3953844.964 ops/s
Benchmarks.circeByteFromJsonNumber 1000 thrpt 613406.698 ops/s
Benchmarks.circeByteFromJsonNumber 10000 thrpt 18684.245 ops/s
Benchmarks.circeByteFromJsonNumber 100000 thrpt 536.919 ops/s
Benchmarks.circeByteFromJsonNumber 1000000 thrpt 970.243 ops/s
Benchmarks.circeByteFromJsonString 1 thrpt 9590048.009 ops/s
Benchmarks.circeByteFromJsonString 10 thrpt 5672037.632 ops/s
Benchmarks.circeByteFromJsonString 100 thrpt 3121562.583 ops/s
Benchmarks.circeByteFromJsonString 1000 thrpt 498306.794 ops/s
Benchmarks.circeByteFromJsonString 10000 thrpt 16637.525 ops/s
Benchmarks.circeByteFromJsonString 100000 thrpt 512.431 ops/s
Benchmarks.circeByteFromJsonString 1000000 thrpt 705.323 ops/s
Benchmarks.circeDecimal64FromJsonNumber 1 thrpt 32465804.888 ops/s
Benchmarks.circeDecimal64FromJsonNumber 10 thrpt 18183803.739 ops/s
Benchmarks.circeDecimal64FromJsonNumber 100 thrpt 441654.942 ops/s
Benchmarks.circeDecimal64FromJsonNumber 1000 thrpt 55450.156 ops/s
Benchmarks.circeDecimal64FromJsonNumber 10000 thrpt 680.992 ops/s
Benchmarks.circeDecimal64FromJsonNumber 100000 thrpt 8.036 ops/s
Benchmarks.circeDecimal64FromJsonNumber 1000000 thrpt 0.084 ops/s
Benchmarks.circeDecimal64FromJsonString 1 thrpt 35237726.073 ops/s
Benchmarks.circeDecimal64FromJsonString 10 thrpt 18060724.965 ops/s
Benchmarks.circeDecimal64FromJsonString 100 thrpt 3790494.091 ops/s
Benchmarks.circeDecimal64FromJsonString 1000 thrpt 517224.279 ops/s
Benchmarks.circeDecimal64FromJsonString 10000 thrpt 50172.814 ops/s
Benchmarks.circeDecimal64FromJsonString 100000 thrpt 3871.600 ops/s
Benchmarks.circeDecimal64FromJsonString 1000000 thrpt 380.760 ops/s
Benchmarks.circeDoubleFromJsonNumber 1 thrpt 42118925.325 ops/s
Benchmarks.circeDoubleFromJsonNumber 10 thrpt 27851697.083 ops/s
Benchmarks.circeDoubleFromJsonNumber 100 thrpt 6023453.307 ops/s
Benchmarks.circeDoubleFromJsonNumber 1000 thrpt 1291577.287 ops/s
Benchmarks.circeDoubleFromJsonNumber 10000 thrpt 120729.779 ops/s
Benchmarks.circeDoubleFromJsonNumber 100000 thrpt 6996.223 ops/s
Benchmarks.circeDoubleFromJsonNumber 1000000 thrpt 648.855 ops/s
Benchmarks.circeDoubleFromJsonString 1 thrpt 18350628.983 ops/s
Benchmarks.circeDoubleFromJsonString 10 thrpt 13816580.327 ops/s
Benchmarks.circeDoubleFromJsonString 100 thrpt 3157595.600 ops/s
Benchmarks.circeDoubleFromJsonString 1000 thrpt 937630.772 ops/s
Benchmarks.circeDoubleFromJsonString 10000 thrpt 93229.579 ops/s
Benchmarks.circeDoubleFromJsonString 100000 thrpt 7687.841 ops/s
Benchmarks.circeDoubleFromJsonString 1000000 thrpt 704.978 ops/s
Benchmarks.circeFloatFromJsonNumber 1 thrpt 42032996.188 ops/s
Benchmarks.circeFloatFromJsonNumber 10 thrpt 27994441.293 ops/s
Benchmarks.circeFloatFromJsonNumber 100 thrpt 10257296.519 ops/s
Benchmarks.circeFloatFromJsonNumber 1000 thrpt 1232474.955 ops/s
Benchmarks.circeFloatFromJsonNumber 10000 thrpt 131005.673 ops/s
Benchmarks.circeFloatFromJsonNumber 100000 thrpt 7008.675 ops/s
Benchmarks.circeFloatFromJsonNumber 1000000 thrpt 642.680 ops/s
Benchmarks.circeFloatFromJsonString 1 thrpt 19430976.365 ops/s
Benchmarks.circeFloatFromJsonString 10 thrpt 13425339.747 ops/s
Benchmarks.circeFloatFromJsonString 100 thrpt 4027332.257 ops/s
Benchmarks.circeFloatFromJsonString 1000 thrpt 948563.761 ops/s
Benchmarks.circeFloatFromJsonString 10000 thrpt 93368.598 ops/s
Benchmarks.circeFloatFromJsonString 100000 thrpt 7721.166 ops/s
Benchmarks.circeFloatFromJsonString 1000000 thrpt 704.441 ops/s
Benchmarks.circeIntFromJsonNumber 1 thrpt 41168617.236 ops/s
Benchmarks.circeIntFromJsonNumber 10 thrpt 26584051.952 ops/s
Benchmarks.circeIntFromJsonNumber 100 thrpt 3903281.136 ops/s
Benchmarks.circeIntFromJsonNumber 1000 thrpt 606354.171 ops/s
Benchmarks.circeIntFromJsonNumber 10000 thrpt 17681.390 ops/s
Benchmarks.circeIntFromJsonNumber 100000 thrpt 532.075 ops/s
Benchmarks.circeIntFromJsonNumber 1000000 thrpt 964.282 ops/s
Benchmarks.circeIntFromJsonString 1 thrpt 9594250.207 ops/s
Benchmarks.circeIntFromJsonString 10 thrpt 6049361.136 ops/s
Benchmarks.circeIntFromJsonString 100 thrpt 3287719.278 ops/s
Benchmarks.circeIntFromJsonString 1000 thrpt 503430.218 ops/s
Benchmarks.circeIntFromJsonString 10000 thrpt 16595.507 ops/s
Benchmarks.circeIntFromJsonString 100000 thrpt 516.309 ops/s
Benchmarks.circeIntFromJsonString 1000000 thrpt 705.881 ops/s
Benchmarks.circeLongFromJsonNumber 1 thrpt 42684283.443 ops/s
Benchmarks.circeLongFromJsonNumber 10 thrpt 24972578.937 ops/s
Benchmarks.circeLongFromJsonNumber 100 thrpt 3949936.690 ops/s
Benchmarks.circeLongFromJsonNumber 1000 thrpt 610716.514 ops/s
Benchmarks.circeLongFromJsonNumber 10000 thrpt 17622.310 ops/s
Benchmarks.circeLongFromJsonNumber 100000 thrpt 531.353 ops/s
Benchmarks.circeLongFromJsonNumber 1000000 thrpt 962.567 ops/s
Benchmarks.circeLongFromJsonString 1 thrpt 9497064.832 ops/s
Benchmarks.circeLongFromJsonString 10 thrpt 5995864.687 ops/s
Benchmarks.circeLongFromJsonString 100 thrpt 3127753.443 ops/s
Benchmarks.circeLongFromJsonString 1000 thrpt 483981.544 ops/s
Benchmarks.circeLongFromJsonString 10000 thrpt 16670.505 ops/s
Benchmarks.circeLongFromJsonString 100000 thrpt 522.309 ops/s
Benchmarks.circeLongFromJsonString 1000000 thrpt 705.313 ops/s
Benchmarks.circeShortFromJsonNumber 1 thrpt 42228993.309 ops/s
Benchmarks.circeShortFromJsonNumber 10 thrpt 21475140.418 ops/s
Benchmarks.circeShortFromJsonNumber 100 thrpt 3945419.978 ops/s
Benchmarks.circeShortFromJsonNumber 1000 thrpt 609905.669 ops/s
Benchmarks.circeShortFromJsonNumber 10000 thrpt 17734.904 ops/s
Benchmarks.circeShortFromJsonNumber 100000 thrpt 528.852 ops/s
Benchmarks.circeShortFromJsonNumber 1000000 thrpt 965.868 ops/s
Benchmarks.circeShortFromJsonString 1 thrpt 8542676.984 ops/s
Benchmarks.circeShortFromJsonString 10 thrpt 5553321.717 ops/s
Benchmarks.circeShortFromJsonString 100 thrpt 3311176.578 ops/s
Benchmarks.circeShortFromJsonString 1000 thrpt 499538.092 ops/s
Benchmarks.circeShortFromJsonString 10000 thrpt 17418.006 ops/s
Benchmarks.circeShortFromJsonString 100000 thrpt 493.251 ops/s
Benchmarks.circeShortFromJsonString 1000000 thrpt 706.962 ops/s
116 changes: 116 additions & 0 deletions circe-jsoniter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//> using jmh
//> using jmhVersion 1.37
//> using repositories ivy2local
//> using dep "com.epam.deltix:dfp:1.0.3"
//> using dep "com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-circe::2.31.0-SNAPSHOT"
package bench

import org.openjdk.jmh.annotations.*
import java.util.concurrent.TimeUnit
import io.circe.*
import io.circe.Decoder.*
import com.github.plokhotnyuk.jsoniter_scala.core.*
import com.github.plokhotnyuk.jsoniter_scala.circe.JsoniterScalaCodec.*
import com.github.plokhotnyuk.jsoniter_scala.circe.CirceCodecs.*
import com.epam.deltix.dfp.{Decimal64, Decimal64Utils}
import scala.util.control.NonFatal

implicit val decimal64Decoder: Decoder[Decimal64] = new Decoder[Decimal64] {
final def apply(c: HCursor): Result[Decimal64] = try {
val x = c.value
if (x.isNumber) {
x.asNumber match {
case Some(n) => n.toBigDecimal match {
case Some(bd) => canonizedDecimal64Result(Decimal64Utils.fromBigDecimalExact(bd.bigDecimal))
case _ => numberError(c)
}
case _ => numberError(c)
}
} else if (x.isString) {
x.asString match {
case Some(s) => canonizedDecimal64Result(Decimal64Utils.parse(s))
case _ => numberError(c)
}
} else numberError(c)
} catch {
case NonFatal(_) => numberError(c)
}

private[this] def canonizedDecimal64Result(x: Long) = new Right(Decimal64.fromUnderlying(Decimal64Utils.canonize(x)))

private[this] def numberError(c: HCursor) = new Left(DecodingFailure("expected decimal64 number", c.history))
}

@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
@Warmup(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 1, time = 1, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(1)
class Benchmarks {
var jsonNumberBytes: Array[Byte] = Array(0)
var jsonStringBytes: Array[Byte] = Array(0)

@Param(Array("1", "10", "100", "1000", "10000", "100000", "1000000"))
var size: Int = 10

@Setup
def setup(): Unit = {
jsonNumberBytes = ("1" + "0" * (size - 1)).getBytes
jsonStringBytes = ("\"1" + "0" * (size - 1) + "\"").getBytes
}

@Benchmark
def circeDecimal64FromJsonNumber() = Decoder[Decimal64].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeDecimal64FromJsonString() = Decoder[Decimal64].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeBigIntFromJsonNumber() = Decoder[BigInt].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeBigIntFromJsonString() = Decoder[BigInt].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeBigDecimalFromJsonNumber() = Decoder[BigDecimal].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeBigDecimalFromJsonString() = Decoder[BigDecimal].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeByteFromJsonNumber() = Decoder[Byte].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeByteFromJsonString() = Decoder[Byte].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeShortFromJsonNumber() = Decoder[Short].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeShortFromJsonString() = Decoder[Short].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeIntFromJsonNumber() = Decoder[Int].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeIntFromJsonString() = Decoder[Int].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeLongFromJsonNumber() = Decoder[Long].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeLongFromJsonString() = Decoder[Long].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeFloatFromJsonNumber() = Decoder[Float].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeFloatFromJsonString() = Decoder[Float].decodeJson(readFromArray(jsonStringBytes))

@Benchmark
def circeDoubleFromJsonNumber() = Decoder[Double].decodeJson(readFromArray(jsonNumberBytes))

@Benchmark
def circeDoubleFromJsonString() = Decoder[Double].decodeJson(readFromArray(jsonStringBytes))
}
Loading

0 comments on commit 54e8e48

Please sign in to comment.