/
benchmarks.scala
132 lines (99 loc) · 4.2 KB
/
benchmarks.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package io.finch
import com.twitter.io.Buf
import com.twitter.util.Future
import io.finch.data.Foo
import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations._
import shapeless._
@BenchmarkMode(Array(Mode.AverageTime))
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(2)
abstract class FinchBenchmark {
val postPayload: Input = Input.post("/").withBody[Text.Plain](Buf.Utf8("x" * 1024))
val getRoot: Input = Input.get("/")
val getFooBarBaz: Input = Input.get("/foo/bar/baz")
val getTenTwenty: Input = Input.get("/10/20")
val getTrueFalse: Input = Input.get("/true/false")
}
@State(Scope.Benchmark)
class BodyBenchmark extends FinchBenchmark {
val fooOptionAsText: Endpoint[Option[Foo]] = bodyOption[Foo, Text.Plain]
val fooAsText: Endpoint[Foo] = body[Foo, Text.Plain]
@Benchmark
def fooOption: Option[Option[Foo]] = fooOptionAsText(postPayload).awaitValueUnsafe()
@Benchmark
def foo: Option[Foo] = fooAsText(postPayload).awaitValueUnsafe()
@Benchmark
def stringOption: Option[Option[String]] = stringBodyOption(postPayload).awaitValueUnsafe()
@Benchmark
def string: Option[String] = stringBody(postPayload).awaitValueUnsafe()
@Benchmark
def byteArrayOption: Option[Option[Array[Byte]]] = binaryBodyOption(postPayload).awaitValueUnsafe()
@Benchmark
def byteArray: Option[Array[Byte]] = binaryBody(postPayload).awaitValueUnsafe()
}
@State(Scope.Benchmark)
class MatchPathBenchmark extends FinchBenchmark {
val foo: Endpoint[HNil] = "foo"
@Benchmark
def stringSome: Option[HNil] = foo(getFooBarBaz).awaitValueUnsafe()
@Benchmark
def stringNone: Option[HNil] = foo(getRoot).awaitValueUnsafe()
}
@State(Scope.Benchmark)
class ExtractPathBenchmark extends FinchBenchmark {
@Benchmark
def stringSome: Option[String] = string(getFooBarBaz).awaitValueUnsafe()
@Benchmark
def stringNone: Option[String] = string(getRoot).awaitValueUnsafe()
@Benchmark
def intSome: Option[Int] = int(getTenTwenty).awaitValueUnsafe()
@Benchmark
def intNone: Option[Int] = int(getFooBarBaz).awaitValueUnsafe()
@Benchmark
def booleanSome: Option[Boolean] = boolean(getTrueFalse).awaitValueUnsafe()
@Benchmark
def booleanNone: Option[Boolean] = boolean(getTenTwenty).awaitValueUnsafe()
}
@State(Scope.Benchmark)
class ProductBenchmark extends FinchBenchmark {
val both: Endpoint[(Int, String)] = Endpoint.const(42).product(Endpoint.const("foo"))
val left: Endpoint[(Int, String)] = Endpoint.const(42).product(Endpoint.empty[String])
val right: Endpoint[(Int, String)] = Endpoint.empty[Int].product(Endpoint.const("foo"))
@Benchmark
def bothMatched: Option[(Int, String)] = both(getRoot).awaitValueUnsafe()
@Benchmark
def leftMatched: Option[(Int, String)] = left(getRoot).awaitValueUnsafe()
@Benchmark
def rightMatched: Option[(Int, String)] = right(getRoot).awaitValueUnsafe()
}
@State(Scope.Benchmark)
class CoproductBenchmark extends FinchBenchmark {
val both: Endpoint[String] = Endpoint.const("foo") | Endpoint.const("bar")
val left: Endpoint[String] = Endpoint.const("foo") | Endpoint.empty[String]
val right: Endpoint[String] = Endpoint.empty[String] | Endpoint.const("bar")
@Benchmark
def bothMatched: Option[String] = both(getRoot).awaitValueUnsafe()
@Benchmark
def leftMatched: Option[String] = left(getRoot).awaitValueUnsafe()
@Benchmark
def rightMatched: Option[String] = right(getRoot).awaitValueUnsafe()
}
@State(Scope.Benchmark)
class MapBenchmark extends FinchBenchmark {
val ten: Endpoint[Int] = Endpoint.const(10)
val mapTen: Endpoint[Int] = ten.map(a => a + 20)
val mapTenAsync: Endpoint[Int] = ten.mapAsync(a => Future.value(a + 20))
val mapTenOutput: Endpoint[Int] = ten.mapOutput(a => Ok(a + 10))
val mapTenOutputAsync: Endpoint[Int] = ten.mapOutputAsync(a => Future.value(Ok(a + 10)))
@Benchmark
def map: Option[Int] = mapTen(getRoot).awaitValueUnsafe()
@Benchmark
def mapAsync: Option[Int] = mapTenAsync(getRoot).awaitValueUnsafe()
@Benchmark
def mapOutput: Option[Int] = mapTenOutput(getRoot).awaitValueUnsafe()
@Benchmark
def mapOutputAsync: Option[Int] = mapTenOutputAsync(getRoot).awaitValueUnsafe()
}