Skip to content

Commit

Permalink
more perf tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Zoller committed Mar 4, 2024
1 parent b08f70f commit b19ecd8
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 175 deletions.
2 changes: 1 addition & 1 deletion benchmark/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ lazy val benchmark = project
libraryDependencies ++= Seq(
"org.playframework" %% "play-json" % "3.0.1",
"io.argonaut" %% "argonaut" % "6.3.9",
"co.blocke" %% "scalajack" % "54f0b4_unknown",
"co.blocke" %% "scalajack" % "b08f70_unknown",
"co.blocke" %% "scala-reflection" % "sj_fixes_f43af7",
"dev.zio" %% "zio-json" % "0.6.1",
"org.typelevel" %% "fabric-core" % "1.12.6",
Expand Down
22 changes: 11 additions & 11 deletions benchmark/src/main/scala/co.blocke/Argonaut.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ import org.openjdk.jmh.annotations._
object ArgonautZ:
import argonaut._, Argonaut._

implicit val CodecPet: CodecJson[Pet] =
casecodec3(Pet.apply, (a: Pet) => Option((a.name, a.species, a.age)))("name","species","age")
implicit val CodecPet: CodecJson[Pet2] =
casecodec3(Pet2.apply, (a: Pet2) => Option((a.name, a.species, a.age)))("name","species","age")

implicit val CodecFriend: CodecJson[Friend] =
casecodec3(Friend.apply, (a: Friend) => Option((a.name, a.age, a.email)))("name","age","email")
implicit val CodecFriend: CodecJson[Friend2] =
casecodec3(Friend2.apply, (a: Friend2) => Option((a.name, a.age, a.email)))("name","age","email")

implicit val CodecAddress: CodecJson[Address] =
casecodec4(Address.apply, (a: Address) => Option((a.street, a.city, a.state, a.postal_code)))("street","city","state","postal_code")
implicit val CodecAddress: CodecJson[Address2] =
casecodec4(Address2.apply, (a: Address2) => Option((a.street, a.city, a.state, a.postal_code)))("street","city","state","postal_code")

implicit val CodecPerson: CodecJson[Person] =
casecodec6(Person.apply, (a: Person) => Option((a.name, a.age, a.address, a.email, a.phone_numbers, a.is_employed)))("name", "age","address","email","phone_numbers","is_employed")
implicit val CodecPerson: CodecJson[Person2] =
casecodec6(Person2.apply, (a: Person2) => Option((a.name, a.age, a.address, a.email, a.phone_numbers, a.is_employed)))("name", "age","address","email","phone_numbers","is_employed")

implicit val CodecRecord: CodecJson[Record] =
casecodec4(Record.apply, (a: Record) => Option((a.person, a.hobbies, a.friends, a.pets)))("person", "hobbies", "friends", "pets")
implicit val CodecRecord: CodecJson[Record2] =
casecodec4(Record2.apply, (a: Record2) => Option((a.person, a.hobbies, a.friends, a.pets)))("person", "hobbies", "friends", "pets")


trait ArgonautReadingBenchmark {
@Benchmark
def readRecordArgonaut = Parse.decodeEither[Record](jsData)
def readRecordArgonaut = Parse.decodeEither[Record2](jsData2)
}

trait ArgonautWritingBenchmark {
Expand Down
6 changes: 3 additions & 3 deletions benchmark/src/main/scala/co.blocke/Benchmark.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import java.util.concurrent.TimeUnit

import ZIOZ.*
import zio.json._
val record = jsData.fromJson[Record] match
val record = jsData2.fromJson[Record2] match
case Right(r) => r
case Left(_) => null.asInstanceOf[Record]
case Left(_) => null.asInstanceOf[Record2]


trait HandTooledWritingBenchmark {
Expand Down Expand Up @@ -45,7 +45,7 @@ trait HandTooledWritingBenchmark {
class ReadingBenchmark
extends ScalaJackZ.ScalaJackReadingBenchmark
// with CirceZ.CirceReadingBenchmark
// with JsoniterZ.JsoniterReadingBenchmark
// extends JsoniterZ.JsoniterReadingBenchmark
// with ZIOZ.ZIOJsonReadingBenchmark
// with PlayZ.PlayReadingBenchmark
// with ArgonautZ.ArgonautReadingBenchmark
Expand Down
22 changes: 11 additions & 11 deletions benchmark/src/main/scala/co.blocke/Circe.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@ object CirceZ:
import io.circe.generic.semiauto.*
import io.circe.parser.*

implicit val recordDecoder: Decoder[Record] = deriveDecoder[Record]
implicit val recordEncoder: Encoder[Record] = deriveEncoder[Record]
implicit val recordDecoder: Decoder[Record2] = deriveDecoder[Record2]
implicit val recordEncoder: Encoder[Record2] = deriveEncoder[Record2]

implicit val personDecoder: Decoder[Person] = deriveDecoder[Person]
implicit val personEncoder: Encoder[Person] = deriveEncoder[Person]
implicit val personDecoder: Decoder[Person2] = deriveDecoder[Person2]
implicit val personEncoder: Encoder[Person2] = deriveEncoder[Person2]

implicit val addressDecoder: Decoder[Address] = deriveDecoder[Address]
implicit val addressEncoder: Encoder[Address] = deriveEncoder[Address]
implicit val addressDecoder: Decoder[Address2] = deriveDecoder[Address2]
implicit val addressEncoder: Encoder[Address2] = deriveEncoder[Address2]

implicit val friendDecoder: Decoder[Friend] = deriveDecoder[Friend]
implicit val friendEncoder: Encoder[Friend] = deriveEncoder[Friend]
implicit val friendDecoder: Decoder[Friend2] = deriveDecoder[Friend2]
implicit val friendEncoder: Encoder[Friend2] = deriveEncoder[Friend2]

implicit val petDecoder: Decoder[Pet] = deriveDecoder[Pet]
implicit val petEncoder: Encoder[Pet] = deriveEncoder[Pet]
implicit val petDecoder: Decoder[Pet2] = deriveDecoder[Pet2]
implicit val petEncoder: Encoder[Pet2] = deriveEncoder[Pet2]

trait CirceReadingBenchmark{
@Benchmark
def readRecordCirce = parse(jsData).flatMap(_.as[Record])
def readRecordCirce = parse(jsData2).flatMap(_.as[Record2])
}

trait CirceWritingBenchmark {
Expand Down
4 changes: 2 additions & 2 deletions benchmark/src/main/scala/co.blocke/Jsoniter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ object JsoniterZ:
import com.github.plokhotnyuk.jsoniter_scala.core._
import com.github.plokhotnyuk.jsoniter_scala.macros._

given codec: JsonValueCodec[Record] = JsonCodecMaker.make
given codec: JsonValueCodec[Record2] = JsonCodecMaker.make
trait JsoniterReadingBenchmark{
@Benchmark
def readRecordJsoniter = readFromString[Record](jsData)
def readRecordJsoniter = readFromString[Record2](jsData2)
}

trait JsoniterWritingBenchmark{
Expand Down
42 changes: 21 additions & 21 deletions benchmark/src/main/scala/co.blocke/PlayJson.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,46 @@ object PlayZ:
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._

implicit val friendWrites: Writes[Friend] = (
implicit val friendWrites: Writes[Friend2] = (
(JsPath \ "name").write[String] and
(JsPath \ "age").write[Int] and
(JsPath \ "email").write[String]
)(unlift((a: Friend) => Option((a.name, a.age, a.email))))
)(unlift((a: Friend2) => Option((a.name, a.age, a.email))))

implicit val petWrites: Writes[Pet] = (
implicit val petWrites: Writes[Pet2] = (
(JsPath \ "name").write[String] and
(JsPath \ "species").write[String] and
(JsPath \ "age").write[Int]
)(unlift((a: Pet) => Option((a.name, a.species, a.age))))
)(unlift((a: Pet2) => Option((a.name, a.species, a.age))))

implicit val addressWrites: Writes[Address] = (
implicit val addressWrites: Writes[Address2] = (
(JsPath \ "street").write[String] and
(JsPath \ "city").write[String] and
(JsPath \ "state").write[String] and
(JsPath \ "postal_code").write[String]
)(unlift((a: Address) => Option((a.street, a.city, a.state, a.postal_code))))
)(unlift((a: Address2) => Option((a.street, a.city, a.state, a.postal_code))))

implicit val personWrites: Writes[Person] = (
(JsPath \ "namet").write[String] and
implicit val personWrites: Writes[Person2] = (
(JsPath \ "name").write[String] and
(JsPath \ "age").write[Int] and
(JsPath \ "address").write[Address] and
(JsPath \ "address").write[Address2] and
(JsPath \ "email").write[String] and
(JsPath \ "phone_numbers").write[List[String]] and
(JsPath \ "is_employed").write[Boolean]
)(unlift((a: Person) => Option((a.name, a.age, a.address, a.email, a.phone_numbers, a.is_employed))))
)(unlift((a: Person2) => Option((a.name, a.age, a.address, a.email, a.phone_numbers, a.is_employed))))

implicit val recordWrites: Writes[Record] = (
(JsPath \ "person").write[Person] and
implicit val recordWrites: Writes[Record2] = (
(JsPath \ "person").write[Person2] and
(JsPath \ "hobbies").write[List[String]] and
(JsPath \ "friends").write[List[Friend]] and
(JsPath \ "pets").write[List[Pet]]
)(unlift((a: Record) => Option((a.person, a.hobbies, a.friends, a.pets))))
(JsPath \ "friends").write[List[Friend2]] and
(JsPath \ "pets").write[List[Pet2]]
)(unlift((a: Record2) => Option((a.person, a.hobbies, a.friends, a.pets))))

implicit val friendReads: play.api.libs.json.Reads[co.blocke.Friend] = Json.reads[Friend]
implicit val petReads: play.api.libs.json.Reads[co.blocke.Pet] = Json.reads[Pet]
implicit val addressReads: play.api.libs.json.Reads[co.blocke.Address] = Json.reads[Address]
implicit val personReads: play.api.libs.json.Reads[co.blocke.Person] = Json.reads[Person]
implicit val recordReads: play.api.libs.json.Reads[co.blocke.Record] = Json.reads[Record]
implicit val friendReads: play.api.libs.json.Reads[co.blocke.Friend2] = Json.reads[Friend2]
implicit val petReads: play.api.libs.json.Reads[co.blocke.Pet2] = Json.reads[Pet2]
implicit val addressReads: play.api.libs.json.Reads[co.blocke.Address2] = Json.reads[Address2]
implicit val personReads: play.api.libs.json.Reads[co.blocke.Person2] = Json.reads[Person2]
implicit val recordReads: play.api.libs.json.Reads[co.blocke.Record2] = Json.reads[Record2]

trait PlayWritingBenchmark {
@Benchmark
Expand All @@ -56,5 +56,5 @@ object PlayZ:
// val playJS = Json.toJson(record)
trait PlayReadingBenchmark {
@Benchmark
def readRecordPlay = Json.fromJson[Record](Json.parse(jsData)) //Json.fromJson[Record](playJS)
def readRecordPlay = Json.fromJson[Record2](Json.parse(jsData2)) //Json.fromJson[Record](playJS)
}
20 changes: 10 additions & 10 deletions benchmark/src/main/scala/co.blocke/Record.scala
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
package co.blocke

case class Person(
case class Person2(
name: String,
age: Int,
address: Address,
address: Address2,
email: String,
phone_numbers: List[String],
is_employed: Boolean
)

case class Address(
case class Address2(
street: String,
city: String,
state: String,
postal_code: String
)

case class Friend(
case class Friend2(
name: String,
age: Int,
email: String
)

case class Pet(
case class Pet2(
name: String,
species: String,
age: Int
)

case class Record(
person: Person,
case class Record2(
person: Person2,
hobbies: List[String],
friends: List[Friend],
pets: List[Pet]
friends: List[Friend2],
pets: List[Pet2]
)


val jsData =
val jsData2 =
"""{
"person": {
"name": "John Doe",
Expand Down
6 changes: 3 additions & 3 deletions benchmark/src/main/scala/co.blocke/ScalaJack.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ object ScalaJackZ:
import co.blocke.scalajack.ScalaJack.*
import co.blocke.scalajack.*

implicit val blah: ScalaJack[Record] = sj[Record]
implicit val blah: ScalaJack[co.blocke.Record2] = sj[co.blocke.Record2]

trait ScalaJackReadingBenchmark{
@Benchmark
// def readRecordScalaJack = sj[Record].fromJson(jsData) // 500K
def readRecordScalaJack = ScalaJack[Record].fromJson(jsData) // 515K :-(
def readRecordScalaJack = ScalaJack[co.blocke.Record2].fromJson(jsData2) // 515K :-(
}

trait ScalaJackWritingBenchmark {
@Benchmark
// def writeRecordScalaJack = sj[Record].toJson(record) // 677K score
def writeRecordScalaJack = ScalaJack[Record].toJson(record) // 1.7M score <- faster
def writeRecordScalaJack = ScalaJack[co.blocke.Record2].toJson(record) // 1.7M score <- faster
}
22 changes: 11 additions & 11 deletions benchmark/src/main/scala/co.blocke/ZIOJson.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import org.openjdk.jmh.annotations._
object ZIOZ:
import zio.json._

implicit val decoder1: JsonDecoder[Address] = DeriveJsonDecoder.gen[Address]
implicit val decoder2: JsonDecoder[Pet] = DeriveJsonDecoder.gen[Pet]
implicit val decoder3: JsonDecoder[Friend] = DeriveJsonDecoder.gen[Friend]
implicit val decoder4: JsonDecoder[Person] = DeriveJsonDecoder.gen[Person]
implicit val decoder5: JsonDecoder[Record] = DeriveJsonDecoder.gen[Record]
implicit val encoder1: JsonEncoder[Address] = DeriveJsonEncoder.gen[Address]
implicit val encoder2: JsonEncoder[Pet] = DeriveJsonEncoder.gen[Pet]
implicit val encoder3: JsonEncoder[Friend] = DeriveJsonEncoder.gen[Friend]
implicit val encoder4: JsonEncoder[Person] = DeriveJsonEncoder.gen[Person]
implicit val encoder5: JsonEncoder[Record] = DeriveJsonEncoder.gen[Record]
implicit val decoder1: JsonDecoder[Address2] = DeriveJsonDecoder.gen[Address2]
implicit val decoder2: JsonDecoder[Pet2] = DeriveJsonDecoder.gen[Pet2]
implicit val decoder3: JsonDecoder[Friend2] = DeriveJsonDecoder.gen[Friend2]
implicit val decoder4: JsonDecoder[Person2] = DeriveJsonDecoder.gen[Person2]
implicit val decoder5: JsonDecoder[Record2] = DeriveJsonDecoder.gen[Record2]
implicit val encoder1: JsonEncoder[Address2] = DeriveJsonEncoder.gen[Address2]
implicit val encoder2: JsonEncoder[Pet2] = DeriveJsonEncoder.gen[Pet2]
implicit val encoder3: JsonEncoder[Friend2] = DeriveJsonEncoder.gen[Friend2]
implicit val encoder4: JsonEncoder[Person2] = DeriveJsonEncoder.gen[Person2]
implicit val encoder5: JsonEncoder[Record2] = DeriveJsonEncoder.gen[Record2]

trait ZIOJsonWritingBenchmark {
@Benchmark
Expand All @@ -23,5 +23,5 @@ object ZIOZ:

trait ZIOJsonReadingBenchmark {
@Benchmark
def readRecordZIOJson = jsData.fromJson[Record]
def readRecordZIOJson = jsData2.fromJson[Record2]
}
Loading

0 comments on commit b19ecd8

Please sign in to comment.