Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of encode and decode an M #35

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .sbtopts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-J-XX:+UseG1GC
-J-Xmx4G
5 changes: 3 additions & 2 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
version = "3.5.8"
align.preset = none
runner.dialect = scala213

fileOverride {
"glob:**/src/*/scala-3" {
"glob:**/src/**/scala-3/**" {
runner.dialect = scala3
}
"glob:**/src/*/scala-2.12" {
"glob:**/src/**/scala-2.12" {
runner.dialect = scala212
}
}
53 changes: 50 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ ThisBuild / scmInfo := Some(
ThisBuild / startYear := Some(2020)
Global / excludeLintKeys += scmInfo

val Scala213 = "2.13.10"
val scala3 = "3.3.1"
val Scala212 = "2.12.19"
val Scala213 = "2.13.14"
val scala33 = "3.3.4"
val scala36 = "3.6.2"
ThisBuild / spiewakMainBranches := Seq("main")

ThisBuild / crossScalaVersions := Seq(Scala213, scala3, "2.12.14")
ThisBuild / crossScalaVersions := Seq(Scala213, scala36, scala33)
ThisBuild / versionIntroduced := Map("3.0.0" -> "0.3.0")
ThisBuild / scalaVersion := (ThisBuild / crossScalaVersions).value.head
ThisBuild / initialCommands := """
Expand All @@ -32,6 +34,13 @@ lazy val root = project
.in(file("."))
.enablePlugins(NoPublishPlugin, SonatypeCiReleasePlugin)
.aggregate(core.js, core.jvm, benchmark)
.settings(
libraryDependencies --= List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full
)
)
)

lazy val core = crossProject(JSPlatform, JVMPlatform)
.crossType(CrossType.Full)
Expand All @@ -49,6 +58,23 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
"org.scalameta" %%% "munit" % "0.7.29" % Test,
"org.scalameta" %%% "munit-scalacheck" % "0.7.29" % Test
),
// TODO sbt-spiewak-sonatype adds kind-projector 0.13.2 but it does not exist anymore
libraryDependencies --= List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full
)
),
libraryDependencies ++= {
if (!scalaBinaryVersion.value.startsWith("3")) {
List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.3" cross CrossVersion.full
)
)
} else {
Nil
}
},
mimaBinaryIssueFilters ++= List(
ProblemFilters.exclude[ReversedMissingMethodProblem](
"dynosaur.Schema.dynosaur$Schema$$read_"
Expand Down Expand Up @@ -78,6 +104,13 @@ lazy val benchmark = project
.dependsOn(core.jvm)
.enablePlugins(JmhPlugin)
.disablePlugins(MimaPlugin)
.settings(
libraryDependencies --= List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full
)
)
)

lazy val jsdocs = project
.dependsOn(core.js)
Expand All @@ -86,6 +119,13 @@ lazy val jsdocs = project
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.3.0"
)
.enablePlugins(ScalaJSPlugin)
.settings(
libraryDependencies --= List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full
)
)
)

lazy val docs = project
.in(file("mdoc"))
Expand All @@ -104,6 +144,13 @@ lazy val docs = project
)
.dependsOn(core.jvm)
.enablePlugins(MdocPlugin, NoPublishPlugin)
.settings(
libraryDependencies --= List(
compilerPlugin(
"org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full
)
)
)

ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("11"))

Expand Down
184 changes: 6 additions & 178 deletions modules/benchmark/src/main/scala/DecodingBench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,190 +18,18 @@ package dynosaur

import cats.syntax.all._

import org.openjdk.jmh.annotations.{
Benchmark,
BenchmarkMode,
Mode
}
import org.openjdk.jmh.annotations.{Benchmark, BenchmarkMode, Mode}
import cats.data.NonEmptyList

sealed trait Dynosaur
object Dynosaur {
case class Parasaurolophus(name: String, age: Int, songs: Int)
extends Dynosaur
case class TyrannosaurusRex(name: String, age: Int, victims: Int)
extends Dynosaur
case class Allosaurus(name: String, age: Int, attacks: Int) extends Dynosaur
}

import Dynosaur._

object DecodingBench {

val tyrannosaurusRexDv = DynamoValue.m(
"name" -> DynamoValue.s("Foolio"),
"age" -> DynamoValue.n(20000000),
"victims" -> DynamoValue.n(9)
)

val parasaurolophusDv = DynamoValue.m(
"name" -> DynamoValue.s("Cantolio"),
"age" -> DynamoValue.n(25000000),
"songs" -> DynamoValue.n(9)
)

val allosaurusDv = DynamoValue.m(
"name" -> DynamoValue.s("Cantolio"),
"age" -> DynamoValue.n(25000000),
"attacks" -> DynamoValue.n(99)
)

val tyrannosaurusRexWithTagDv = DynamoValue.m(
"tyrannosaurus-rex" -> tyrannosaurusRexDv
)

val allosaurusWithTagDv = DynamoValue.m(
"allosaurus" -> allosaurusDv
)

val parasaurolophusWithTagDv = DynamoValue.m(
"parasaurolophus" -> parasaurolophusDv
)

val allosauruses = DynamoValue.l(
(0 until 10)
.map(_ => allosaurusDv)
.toList
)

val dynosaursWithTag = DynamoValue.l(
tyrannosaurusRexWithTagDv,
allosaurusWithTagDv,
parasaurolophusWithTagDv
)

val dynosaurDvWithDiscriminator = DynamoValue.m(
"name" -> DynamoValue.s("Foolio"),
"age" -> DynamoValue.n(20000000),
"victims" -> DynamoValue.n(9),
"kind" -> DynamoValue.s("tyrannosaurus-rex")
)

val schermaForParasaurolophus: Schema[Parasaurolophus] =
Schema.record[Parasaurolophus] { fields =>
(
fields("name", _.name),
fields("age", _.age),
fields("songs", _.songs)
).mapN(Parasaurolophus.apply)
}

def defSchermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
Schema.record[TyrannosaurusRex] { fields =>
(
fields("name", _.name),
fields("age", _.age),
fields("victims", _.victims)
).mapN(TyrannosaurusRex.apply)
}

val schermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
defSchermaForTyrannosaurusRex

implicit def implicitSchermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
defSchermaForTyrannosaurusRex

val schermaForAllosaurus: Schema[Allosaurus] = Schema.record[Allosaurus] {
fields =>
(
fields("name", _.name),
fields("age", _.age),
fields("attacks", _.attacks)
).mapN(Allosaurus.apply)
}

def defSchermaForAllosaurus: Schema[Allosaurus] = Schema.record[Allosaurus] {
fields =>
(
fields("name", _.name),
fields("age", _.age),
fields("attacks", _.attacks)
).mapN(Allosaurus.apply)
}

implicit lazy val implicitSchermaForAllosaurus: Schema[Allosaurus] =
defSchermaForAllosaurus

val schermaForParasaurolophusWithDiscriminator: Schema[Parasaurolophus] =
Schema.record[Parasaurolophus] { fields =>
fields.const("kind", "parasaurolophus") *>
(
fields("name", _.name),
fields("age", _.age),
fields("songs", _.songs)
).mapN(Parasaurolophus.apply)
}

val schermaForTyrannosaurusRexWithDiscriminator: Schema[TyrannosaurusRex] =
Schema.record[TyrannosaurusRex] { fields =>
fields.const("kind", "tyrannosaurus-rex") *>
(
fields("name", _.name),
fields("age", _.age),
fields("victims", _.victims)
).mapN(TyrannosaurusRex.apply)
}

val schermaForAllosaurusWithDiscriminator: Schema[Allosaurus] =
Schema.record[Allosaurus] { fields =>
fields.const("kind", "allosaurus") *>
(
fields("name", _.name),
fields("age", _.age),
fields("attacks", _.attacks)
).mapN(Allosaurus.apply)
}

val schemaForDynosaurWithTag: Schema[Dynosaur] = Schema.oneOf { alt =>
NonEmptyList
.of(
alt(schermaForParasaurolophus.tag("parasaurolophus")),
alt(schermaForTyrannosaurusRex.tag("tyrannosaurus-rex")),
alt(schermaForAllosaurus.tag("allosaurus"))
)
.reduceLeft(_ |+| _)
}

val schemaForDynosaurWithDiscriminator: Schema[Dynosaur] = Schema.oneOf {
alt =>
NonEmptyList
.of(
alt(schermaForParasaurolophusWithDiscriminator),
alt(schermaForTyrannosaurusRexWithDiscriminator),
alt(schermaForAllosaurusWithDiscriminator)
)
.reduceLeft(_ |+| _)
}

val schermaForAllosauruses =
Schema.seq(schermaForAllosaurus)

val string = DynamoValue.s("dynosaur")
val strings = DynamoValue.l((0 until 10).map { idx =>
DynamoValue.s(s"test-$idx")
}.toList)

val schemaForStrings = Schema.seq(Schema.string)
}
import schemas._
import data._

class DecodingBench {

import DecodingBench._

@Benchmark
@BenchmarkMode(Array(Mode.Throughput))
def decodeAnS =
Schema.string.read(string)
Schema.string.read(stringDv)

@Benchmark
@BenchmarkMode(Array(Mode.Throughput))
Expand All @@ -216,10 +44,10 @@ class DecodingBench {
@Benchmark
@BenchmarkMode(Array(Mode.Throughput))
def decodeOneOfWithDiscriminator =
schemaForDynosaurWithDiscriminator.read(dynosaurDvWithDiscriminator)
schemaForDynosaurWithDiscriminator.read(dynosaurWithDiscriminatorDv)

@Benchmark
@BenchmarkMode(Array(Mode.Throughput))
def decodeList = schemaForStrings.read(strings)
def decodeList = schemaForStrings.read(stringsDv)

}
Loading
Loading