From b5f38d540067cd480f05272d619c2529616c93e3 Mon Sep 17 00:00:00 2001 From: Yann Simon Date: Wed, 20 Mar 2019 10:38:33 +0100 Subject: [PATCH 1/2] more benchmarks --- .../main/scala/json/FromJsonBenchmark.scala | 45 +++++++++++++ .../src/main/scala/json/JsonBenchmark.scala | 63 ++----------------- .../main/scala/json/ParseJsonBenchmark.scala | 27 ++++++++ .../src/main/scala/json/ToJsonBenchmark.scala | 50 +++++++++++++++ 4 files changed, 128 insertions(+), 57 deletions(-) create mode 100644 benchmarks/src/main/scala/json/FromJsonBenchmark.scala create mode 100644 benchmarks/src/main/scala/json/ParseJsonBenchmark.scala create mode 100644 benchmarks/src/main/scala/json/ToJsonBenchmark.scala diff --git a/benchmarks/src/main/scala/json/FromJsonBenchmark.scala b/benchmarks/src/main/scala/json/FromJsonBenchmark.scala new file mode 100644 index 00000000..5dd1301c --- /dev/null +++ b/benchmarks/src/main/scala/json/FromJsonBenchmark.scala @@ -0,0 +1,45 @@ +package json + +import io.sphere.json._ +import org.openjdk.jmh.annotations._ + +@State(Scope.Benchmark) +@BenchmarkMode(Array(Mode.Throughput)) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) +@Fork(value = 1) +class FromJsonBenchmark { + + /* on local mac + jmh:run + +Benchmark Mode Cnt Score Error Units +FromJsonBenchmark.listReader thrpt 10 66,286 ± 1,025 ops/s +FromJsonBenchmark.parseFromStringToCaseClass thrpt 10 12,974 ± 0,333 ops/s +FromJsonBenchmark.seqReader thrpt 10 66,626 ± 1,235 ops/s +FromJsonBenchmark.vectorReader thrpt 10 67,702 ± 2,501 ops/s + */ + + @Benchmark + def parseFromStringToCaseClass(): Unit = { + val product = getFromJSON[Product](JsonBenchmark.json) + assert(product.version == 2) + } + + @Benchmark + def vectorReader(): Unit = { + fromJSON[Vector[Int]](JsonBenchmark.lotsOfIntsAsJson) + } + + @Benchmark + def listReader(): Unit = { + fromJSON[List[Int]](JsonBenchmark.lotsOfIntsAsJson) + } + + @Benchmark + def seqReader(): Unit = { + fromJSON[Seq[Int]](JsonBenchmark.lotsOfIntsAsJson) + } + +} + diff --git a/benchmarks/src/main/scala/json/JsonBenchmark.scala b/benchmarks/src/main/scala/json/JsonBenchmark.scala index 78c30550..8d9736ca 100644 --- a/benchmarks/src/main/scala/json/JsonBenchmark.scala +++ b/benchmarks/src/main/scala/json/JsonBenchmark.scala @@ -5,63 +5,9 @@ import java.util.UUID import io.sphere.json._ import io.sphere.json.generic._ import io.sphere.util.BaseMoney -import org.json4s.StringInput -import org.json4s.jackson._ -import org.openjdk.jmh.annotations._ - -@State(Scope.Benchmark) -@BenchmarkMode(Array(Mode.Throughput)) -@Warmup(iterations = 10, time = 1) -@Measurement(iterations = 10, time = 1) -@Fork(value = 1) -class JsonBenchmark { - - /* on local mac - jmh:run - -Benchmark Mode Cnt Score Error Units -JsonBenchmark.listReader thrpt 5 65,248 ± 17,094 ops/s -JsonBenchmark.parseFromStringToCaseClass thrpt 5 13,365 ± 0,467 ops/s -JsonBenchmark.parseFromStringToJValue thrpt 5 84,705 ± 12,377 ops/s -JsonBenchmark.seqReader thrpt 5 64,475 ± 14,184 ops/s -JsonBenchmark.serializeCaseClassToString thrpt 5 40,563 ± 4,731 ops/s -JsonBenchmark.vectorReader thrpt 5 66,068 ± 7,377 ops/s - */ - - @Benchmark - def parseFromStringToJValue(): Unit = { - val jvalue = parseJson(StringInput(JsonBenchmark.json)) - assert(jvalue != null) - } - - @Benchmark - def parseFromStringToCaseClass(): Unit = { - val product = getFromJSON[Product](JsonBenchmark.json) - assert(product.version == 2) - } - - @Benchmark - def serializeCaseClassToString(): Unit = { - val json = toJSON[Product](JsonBenchmark.product) - assert(json != null) - } - - @Benchmark - def vectorReader(): Unit = { - fromJSON[Vector[Int]](JsonBenchmark.lotsOfInts) - } - - @Benchmark - def listReader(): Unit = { - fromJSON[List[Int]](JsonBenchmark.lotsOfInts) - } - - @Benchmark - def seqReader(): Unit = { - fromJSON[Seq[Int]](JsonBenchmark.lotsOfInts) - } -} +import scala.collection.generic.CanBuildFrom +import scala.language.higherKinds case class Reference(typeId: String, id: UUID) @@ -93,7 +39,10 @@ object Product { object JsonBenchmark { - val lotsOfInts = Range(1, 100000).mkString("[", ",", "]") + val lotsOfIntsList = Range(1, 100000).toList + val lotsOfIntsSeq = Range(1, 100000).toSeq + val lotsOfIntsVector = Range(1, 100000).toVector + val lotsOfIntsAsJson = Range(1, 100000).mkString("[", ",", "]") val prices = for (i ← 1 to 200) yield s""" diff --git a/benchmarks/src/main/scala/json/ParseJsonBenchmark.scala b/benchmarks/src/main/scala/json/ParseJsonBenchmark.scala new file mode 100644 index 00000000..60ebf5af --- /dev/null +++ b/benchmarks/src/main/scala/json/ParseJsonBenchmark.scala @@ -0,0 +1,27 @@ +package json + +import org.json4s.StringInput +import org.json4s.jackson._ +import org.openjdk.jmh.annotations._ + +@State(Scope.Benchmark) +@BenchmarkMode(Array(Mode.Throughput)) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) +@Fork(value = 1) +class ParseJsonBenchmark { + + /* on local mac + jmh:run + +Benchmark Mode Cnt Score Error Units +ParseJsonBenchmark.parseFromStringToJValue thrpt 10 85,322 ± 1,073 ops/s + */ + + @Benchmark + def parseFromStringToJValue(): Unit = { + val jvalue = parseJson(StringInput(JsonBenchmark.json)) + assert(jvalue != null) + } +} + diff --git a/benchmarks/src/main/scala/json/ToJsonBenchmark.scala b/benchmarks/src/main/scala/json/ToJsonBenchmark.scala new file mode 100644 index 00000000..f7ce764c --- /dev/null +++ b/benchmarks/src/main/scala/json/ToJsonBenchmark.scala @@ -0,0 +1,50 @@ +package json + +import java.util.UUID + +import io.sphere.json._ +import io.sphere.json.generic._ +import io.sphere.util.BaseMoney +import org.json4s.StringInput +import org.json4s.jackson._ +import org.openjdk.jmh.annotations._ + +@State(Scope.Benchmark) +@BenchmarkMode(Array(Mode.Throughput)) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 10, time = 1) +@Fork(value = 1) +class ToJsonBenchmark { + + /* on local mac + jmh:run + +Benchmark Mode Cnt Score Error Units +ToJsonBenchmark.listWriter thrpt 10 70,065 ± 0,967 ops/s +ToJsonBenchmark.seqWriter thrpt 10 63,512 ± 3,889 ops/s +ToJsonBenchmark.serializeCaseClassToString thrpt 10 37,925 ± 2,252 ops/s +ToJsonBenchmark.vectorWriter thrpt 10 63,762 ± 1,470 ops/s + */ + + @Benchmark + def serializeCaseClassToString(): Unit = { + val json = toJSON[Product](JsonBenchmark.product) + assert(json != null) + } + + @Benchmark + def vectorWriter(): Unit = { + toJSON[Vector[Int]](JsonBenchmark.lotsOfIntsVector) + } + + @Benchmark + def listWriter(): Unit = { + toJSON[List[Int]](JsonBenchmark.lotsOfIntsList) + } + + @Benchmark + def seqWriter(): Unit = { + toJSON[Seq[Int]](JsonBenchmark.lotsOfIntsSeq) + } + +} From 598f940f0b35f4f51f799c99d5b306235461495e Mon Sep 17 00:00:00 2001 From: Yann Simon Date: Wed, 20 Mar 2019 11:41:38 +0100 Subject: [PATCH 2/2] remove 'collection.breakOut' The performances stay similar --- benchmarks/src/main/scala/json/ToJsonBenchmark.scala | 10 +++++----- json/src/main/scala/io/sphere/json/ToJSON.scala | 11 ++++++----- util/src/main/scala/Reflect.scala | 3 ++- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/benchmarks/src/main/scala/json/ToJsonBenchmark.scala b/benchmarks/src/main/scala/json/ToJsonBenchmark.scala index f7ce764c..78ae2d9e 100644 --- a/benchmarks/src/main/scala/json/ToJsonBenchmark.scala +++ b/benchmarks/src/main/scala/json/ToJsonBenchmark.scala @@ -19,11 +19,11 @@ class ToJsonBenchmark { /* on local mac jmh:run -Benchmark Mode Cnt Score Error Units -ToJsonBenchmark.listWriter thrpt 10 70,065 ± 0,967 ops/s -ToJsonBenchmark.seqWriter thrpt 10 63,512 ± 3,889 ops/s -ToJsonBenchmark.serializeCaseClassToString thrpt 10 37,925 ± 2,252 ops/s -ToJsonBenchmark.vectorWriter thrpt 10 63,762 ± 1,470 ops/s +Benchmark Mode Cnt Score Error Units +ToJsonBenchmark.listWriter thrpt 10 68,770 ± 1,157 ops/s +ToJsonBenchmark.seqWriter thrpt 10 65,792 ± 1,191 ops/s +ToJsonBenchmark.serializeCaseClassToString thrpt 10 39,142 ± 0,574 ops/s +ToJsonBenchmark.vectorWriter thrpt 10 64,359 ± 2,162 ops/s */ @Benchmark diff --git a/json/src/main/scala/io/sphere/json/ToJSON.scala b/json/src/main/scala/io/sphere/json/ToJSON.scala index 870f415e..3257f5bb 100644 --- a/json/src/main/scala/io/sphere/json/ToJSON.scala +++ b/json/src/main/scala/io/sphere/json/ToJSON.scala @@ -2,7 +2,6 @@ package io.sphere.json import cats.data.NonEmptyList -import scala.collection.breakOut import java.util.{Currency, Locale, UUID} import io.sphere.util.{BaseMoney, HighPrecisionMoney, Money} @@ -44,15 +43,17 @@ object ToJSON { } implicit def seqWriter[@specialized A](implicit w: ToJSON[A]): ToJSON[Seq[A]] = new ToJSON[Seq[A]] { - def write(s: Seq[A]): JValue = JArray(s.map(w.write)(breakOut)) + def write(s: Seq[A]): JValue = JArray(s.iterator.map(w.write).toList) } implicit def setWriter[@specialized A](implicit w: ToJSON[A]): ToJSON[Set[A]] = new ToJSON[Set[A]] { - def write(s: Set[A]): JValue = JArray(s.map(w.write)(breakOut)) + def write(s: Set[A]): JValue = JArray(s.iterator.map(w.write).toList) } implicit def vectorWriter[@specialized A](implicit w: ToJSON[A]): ToJSON[Vector[A]] = new ToJSON[Vector[A]] { - def write(v: Vector[A]): JValue = JArray(v.map(w.write)(breakOut)) + def write(v: Vector[A]): JValue = { + JArray(v.iterator.map(w.write).toList) + } } implicit val intWriter: ToJSON[Int] = new ToJSON[Int] { @@ -88,7 +89,7 @@ object ToJSON { } implicit def mapWriter[A: ToJSON]: ToJSON[Map[String, A]] = new ToJSON[Map[String, A]] { - def write(m: Map[String, A]) = JObject(m.map { case (k, v) => JField(k, toJValue(v)) }(breakOut): _*) + def write(m: Map[String, A]) = JObject(m.iterator.map { case (k, v) => JField(k, toJValue(v)) }.toList) } implicit val moneyWriter: ToJSON[Money] = new ToJSON[Money] { diff --git a/util/src/main/scala/Reflect.scala b/util/src/main/scala/Reflect.scala index e562fb68..9b01aa06 100644 --- a/util/src/main/scala/Reflect.scala +++ b/util/src/main/scala/Reflect.scala @@ -43,6 +43,7 @@ object Reflect extends Logging { } sym.children + .iterator .collect { case m: MethodSymbol if m.isCaseAccessor && !m.isPrivate => m } .zipWithIndex .map { case (ms, idx) => @@ -52,7 +53,7 @@ object Reflect extends Logging { case _: NoSuchMethodException => None } CaseClassFieldMeta(ms.name, defaultValue) - }(collection.breakOut) + }.toIndexedSeq } } }