Skip to content

Commit dc1510e

Browse files
authored
Merge pull request #33 from SystemFw/add-benchmark
Improve performance
2 parents 59a7e68 + 64b5e6c commit dc1510e

File tree

9 files changed

+399
-55
lines changed

9 files changed

+399
-55
lines changed

.github/workflows/ci.yml

+8-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
strategy:
2727
matrix:
2828
os: [ubuntu-latest]
29-
scala: [2.13.10, 3.2.2, 2.12.14]
29+
scala: [2.13.10, 3.3.1, 2.12.14]
3030
java: [temurin@11]
3131
runs-on: ${{ matrix.os }}
3232
steps:
@@ -63,7 +63,7 @@ jobs:
6363
run: sbt ++${{ matrix.scala }} docs/mdoc
6464

6565
- name: Compress target directories
66-
run: tar cf targets.tar target modules/core/js/target modules/core/jvm/target project/target
66+
run: tar cf targets.tar target modules/core/js/target modules/core/jvm/target modules/benchmark/target project/target
6767

6868
- name: Upload target directories
6969
uses: actions/upload-artifact@v2
@@ -116,12 +116,12 @@ jobs:
116116
tar xf targets.tar
117117
rm targets.tar
118118
119-
- name: Download target directories (3.2.2)
119+
- name: Download target directories (3.3.1)
120120
uses: actions/download-artifact@v2
121121
with:
122-
name: target-${{ matrix.os }}-3.2.2-${{ matrix.java }}
122+
name: target-${{ matrix.os }}-3.3.1-${{ matrix.java }}
123123

124-
- name: Inflate target directories (3.2.2)
124+
- name: Inflate target directories (3.3.1)
125125
run: |
126126
tar xf targets.tar
127127
rm targets.tar
@@ -162,12 +162,12 @@ jobs:
162162
tar xf targets.tar
163163
rm targets.tar
164164
165-
- name: Download target directories (3.2.2)
165+
- name: Download target directories (3.3.1)
166166
uses: actions/download-artifact@v2
167167
with:
168-
name: target-${{ matrix.os }}-3.2.2-${{ matrix.java }}
168+
name: target-${{ matrix.os }}-3.3.1-${{ matrix.java }}
169169

170-
- name: Inflate target directories (3.2.2)
170+
- name: Inflate target directories (3.3.1)
171171
run: |
172172
tar xf targets.tar
173173
rm targets.tar

build.sbt

+32-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import com.typesafe.tools.mima.core.ReversedMissingMethodProblem
2+
import com.typesafe.tools.mima.core.ProblemFilters
13
Global / onChangedBuildSource := ReloadOnSourceChanges
24

35
ThisBuild / baseVersion := "0.3.0"
@@ -15,9 +17,10 @@ ThisBuild / startYear := Some(2020)
1517
Global / excludeLintKeys += scmInfo
1618

1719
val Scala213 = "2.13.10"
20+
val scala3 = "3.3.1"
1821
ThisBuild / spiewakMainBranches := Seq("main")
1922

20-
ThisBuild / crossScalaVersions := Seq(Scala213, "3.2.2", "2.12.14")
23+
ThisBuild / crossScalaVersions := Seq(Scala213, scala3, "2.12.14")
2124
ThisBuild / versionIntroduced := Map("3.0.0" -> "0.3.0")
2225
ThisBuild / scalaVersion := (ThisBuild / crossScalaVersions).value.head
2326
ThisBuild / initialCommands := """
@@ -28,7 +31,7 @@ ThisBuild / initialCommands := """
2831
lazy val root = project
2932
.in(file("."))
3033
.enablePlugins(NoPublishPlugin, SonatypeCiReleasePlugin)
31-
.aggregate(core.js, core.jvm)
34+
.aggregate(core.js, core.jvm, benchmark)
3235

3336
lazy val core = crossProject(JSPlatform, JVMPlatform)
3437
.crossType(CrossType.Full)
@@ -37,25 +40,45 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
3740
name := "dynosaur-core",
3841
scalafmtOnCompile := true,
3942
libraryDependencies ++= List(
40-
"org.typelevel" %%% "cats-core" % "2.6.1",
41-
"org.typelevel" %%% "cats-free" % "2.6.1",
42-
"org.typelevel" %%% "alleycats-core" % "2.6.1",
43-
"org.typelevel" %%% "paiges-core" % "0.4.2",
44-
"org.typelevel" %%% "paiges-cats" % "0.4.2",
45-
"org.scodec" %%% "scodec-bits" % "1.1.34",
43+
"org.typelevel" %%% "cats-core" % "2.10.0",
44+
"org.typelevel" %%% "cats-free" % "2.10.0",
45+
"org.typelevel" %%% "alleycats-core" % "2.10.0",
46+
"org.typelevel" %%% "paiges-core" % "0.4.3",
47+
"org.typelevel" %%% "paiges-cats" % "0.4.3",
48+
"org.scodec" %%% "scodec-bits" % "1.1.38",
4649
"org.scalameta" %%% "munit" % "0.7.29" % Test,
4750
"org.scalameta" %%% "munit-scalacheck" % "0.7.29" % Test
51+
),
52+
mimaBinaryIssueFilters ++= List(
53+
ProblemFilters.exclude[ReversedMissingMethodProblem](
54+
"dynosaur.Schema.dynosaur$Schema$$read_"
55+
),
56+
ProblemFilters.exclude[ReversedMissingMethodProblem](
57+
"dynosaur.Schema.dynosaur$Schema$$read__="
58+
),
59+
ProblemFilters.exclude[ReversedMissingMethodProblem](
60+
"dynosaur.Schema.dynosaur$Schema$$write_"
61+
),
62+
ProblemFilters.exclude[ReversedMissingMethodProblem](
63+
"dynosaur.Schema.dynosaur$Schema$$write__="
64+
)
4865
)
4966
)
5067
.jvmSettings(
5168
libraryDependencies ++= Seq(
52-
"software.amazon.awssdk" % "dynamodb" % "2.21.5"
69+
"software.amazon.awssdk" % "dynamodb" % "2.21.14"
5370
)
5471
)
5572

5673
lazy val coreJS = core.js
5774
lazy val coreJVM = core.jvm
5875

76+
lazy val benchmark = project
77+
.in(file("modules/benchmark"))
78+
.dependsOn(core.jvm)
79+
.enablePlugins(JmhPlugin)
80+
.disablePlugins(MimaPlugin)
81+
5982
lazy val jsdocs = project
6083
.dependsOn(core.js)
6184
.settings(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/*
2+
* Copyright 2020 Fabio Labella
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package dynosaur
18+
19+
import cats.syntax.all._
20+
21+
import org.openjdk.jmh.annotations.{
22+
Benchmark,
23+
BenchmarkMode,
24+
Mode
25+
}
26+
import cats.data.NonEmptyList
27+
28+
sealed trait Dynosaur
29+
object Dynosaur {
30+
case class Parasaurolophus(name: String, age: Int, songs: Int)
31+
extends Dynosaur
32+
case class TyrannosaurusRex(name: String, age: Int, victims: Int)
33+
extends Dynosaur
34+
case class Allosaurus(name: String, age: Int, attacks: Int) extends Dynosaur
35+
}
36+
37+
import Dynosaur._
38+
39+
object DecodingBench {
40+
41+
val tyrannosaurusRexDv = DynamoValue.m(
42+
"name" -> DynamoValue.s("Foolio"),
43+
"age" -> DynamoValue.n(20000000),
44+
"victims" -> DynamoValue.n(9)
45+
)
46+
47+
val parasaurolophusDv = DynamoValue.m(
48+
"name" -> DynamoValue.s("Cantolio"),
49+
"age" -> DynamoValue.n(25000000),
50+
"songs" -> DynamoValue.n(9)
51+
)
52+
53+
val allosaurusDv = DynamoValue.m(
54+
"name" -> DynamoValue.s("Cantolio"),
55+
"age" -> DynamoValue.n(25000000),
56+
"attacks" -> DynamoValue.n(99)
57+
)
58+
59+
val tyrannosaurusRexWithTagDv = DynamoValue.m(
60+
"tyrannosaurus-rex" -> tyrannosaurusRexDv
61+
)
62+
63+
val allosaurusWithTagDv = DynamoValue.m(
64+
"allosaurus" -> allosaurusDv
65+
)
66+
67+
val parasaurolophusWithTagDv = DynamoValue.m(
68+
"parasaurolophus" -> parasaurolophusDv
69+
)
70+
71+
val allosauruses = DynamoValue.l(
72+
(0 until 10)
73+
.map(_ => allosaurusDv)
74+
.toList
75+
)
76+
77+
val dynosaursWithTag = DynamoValue.l(
78+
tyrannosaurusRexWithTagDv,
79+
allosaurusWithTagDv,
80+
parasaurolophusWithTagDv
81+
)
82+
83+
val dynosaurDvWithDiscriminator = DynamoValue.m(
84+
"name" -> DynamoValue.s("Foolio"),
85+
"age" -> DynamoValue.n(20000000),
86+
"victims" -> DynamoValue.n(9),
87+
"kind" -> DynamoValue.s("tyrannosaurus-rex")
88+
)
89+
90+
val schermaForParasaurolophus: Schema[Parasaurolophus] =
91+
Schema.record[Parasaurolophus] { fields =>
92+
(
93+
fields("name", _.name),
94+
fields("age", _.age),
95+
fields("songs", _.songs)
96+
).mapN(Parasaurolophus.apply)
97+
}
98+
99+
def defSchermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
100+
Schema.record[TyrannosaurusRex] { fields =>
101+
(
102+
fields("name", _.name),
103+
fields("age", _.age),
104+
fields("victims", _.victims)
105+
).mapN(TyrannosaurusRex.apply)
106+
}
107+
108+
val schermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
109+
defSchermaForTyrannosaurusRex
110+
111+
implicit def implicitSchermaForTyrannosaurusRex: Schema[TyrannosaurusRex] =
112+
defSchermaForTyrannosaurusRex
113+
114+
val schermaForAllosaurus: Schema[Allosaurus] = Schema.record[Allosaurus] {
115+
fields =>
116+
(
117+
fields("name", _.name),
118+
fields("age", _.age),
119+
fields("attacks", _.attacks)
120+
).mapN(Allosaurus.apply)
121+
}
122+
123+
def defSchermaForAllosaurus: Schema[Allosaurus] = Schema.record[Allosaurus] {
124+
fields =>
125+
(
126+
fields("name", _.name),
127+
fields("age", _.age),
128+
fields("attacks", _.attacks)
129+
).mapN(Allosaurus.apply)
130+
}
131+
132+
implicit lazy val implicitSchermaForAllosaurus: Schema[Allosaurus] =
133+
defSchermaForAllosaurus
134+
135+
val schermaForParasaurolophusWithDiscriminator: Schema[Parasaurolophus] =
136+
Schema.record[Parasaurolophus] { fields =>
137+
fields.const("kind", "parasaurolophus") *>
138+
(
139+
fields("name", _.name),
140+
fields("age", _.age),
141+
fields("songs", _.songs)
142+
).mapN(Parasaurolophus.apply)
143+
}
144+
145+
val schermaForTyrannosaurusRexWithDiscriminator: Schema[TyrannosaurusRex] =
146+
Schema.record[TyrannosaurusRex] { fields =>
147+
fields.const("kind", "tyrannosaurus-rex") *>
148+
(
149+
fields("name", _.name),
150+
fields("age", _.age),
151+
fields("victims", _.victims)
152+
).mapN(TyrannosaurusRex.apply)
153+
}
154+
155+
val schermaForAllosaurusWithDiscriminator: Schema[Allosaurus] =
156+
Schema.record[Allosaurus] { fields =>
157+
fields.const("kind", "allosaurus") *>
158+
(
159+
fields("name", _.name),
160+
fields("age", _.age),
161+
fields("attacks", _.attacks)
162+
).mapN(Allosaurus.apply)
163+
}
164+
165+
val schemaForDynosaurWithTag: Schema[Dynosaur] = Schema.oneOf { alt =>
166+
NonEmptyList
167+
.of(
168+
alt(schermaForParasaurolophus.tag("parasaurolophus")),
169+
alt(schermaForTyrannosaurusRex.tag("tyrannosaurus-rex")),
170+
alt(schermaForAllosaurus.tag("allosaurus"))
171+
)
172+
.reduceLeft(_ |+| _)
173+
}
174+
175+
val schemaForDynosaurWithDiscriminator: Schema[Dynosaur] = Schema.oneOf {
176+
alt =>
177+
NonEmptyList
178+
.of(
179+
alt(schermaForParasaurolophusWithDiscriminator),
180+
alt(schermaForTyrannosaurusRexWithDiscriminator),
181+
alt(schermaForAllosaurusWithDiscriminator)
182+
)
183+
.reduceLeft(_ |+| _)
184+
}
185+
186+
val schermaForAllosauruses =
187+
Schema.seq(schermaForAllosaurus)
188+
189+
val string = DynamoValue.s("dynosaur")
190+
val strings = DynamoValue.l((0 until 10).map { idx =>
191+
DynamoValue.s(s"test-$idx")
192+
}.toList)
193+
194+
val schemaForStrings = Schema.seq(Schema.string)
195+
}
196+
197+
class DecodingBench {
198+
199+
import DecodingBench._
200+
201+
@Benchmark
202+
@BenchmarkMode(Array(Mode.Throughput))
203+
def decodeAnS =
204+
Schema.string.read(string)
205+
206+
@Benchmark
207+
@BenchmarkMode(Array(Mode.Throughput))
208+
def decodeAnM =
209+
schermaForAllosaurus.read(allosaurusDv)
210+
211+
@Benchmark
212+
@BenchmarkMode(Array(Mode.Throughput))
213+
def decodeOneOfWithTag =
214+
schemaForDynosaurWithTag.read(tyrannosaurusRexWithTagDv)
215+
216+
@Benchmark
217+
@BenchmarkMode(Array(Mode.Throughput))
218+
def decodeOneOfWithDiscriminator =
219+
schemaForDynosaurWithDiscriminator.read(dynosaurDvWithDiscriminator)
220+
221+
@Benchmark
222+
@BenchmarkMode(Array(Mode.Throughput))
223+
def decodeList = schemaForStrings.read(strings)
224+
225+
}

0 commit comments

Comments
 (0)