Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.

Commit b15d7d4

Browse files
committed
Add a JMH benchmark for ArrayDeque
1 parent 920d291 commit b15d7d4

File tree

1 file changed

+302
-43
lines changed

1 file changed

+302
-43
lines changed
Lines changed: 302 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,304 @@
11
package strawman.collection.mutable
22

3-
import scala._
4-
import scala.collection.mutable
5-
import scala.Predef._
6-
7-
import java.lang.System.nanoTime
8-
9-
object ArrayDequeBenchmark extends App {
10-
val candidates = Seq(
11-
strawman.collection.mutable.ArrayDeque.empty[Int],
12-
scala.collection.mutable.ArrayBuffer.empty[Int]
13-
)
14-
15-
def benchmark[U](name: String, f: mutable.Buffer[Int] => U) = {
16-
def profile(buffer: mutable.Buffer[Int]) = {
17-
val t1 = nanoTime()
18-
f(buffer)
19-
(nanoTime() - t1)/1e6
20-
}
21-
println(s"===============[$name]=================")
22-
candidates foreach (c =>
23-
println(f"${c.getClass.getSimpleName}%12s: ${profile(c)}%8.2f ms")
24-
)
25-
candidates.sliding(2) foreach {case Seq(a, b) =>
26-
assert(a == b, s"Operations are not same [$name] for ${a.getClass.getName} and ${b.getClass.getName}")
27-
}
28-
}
29-
30-
val range10m = (1 to 1e7.toInt).toArray
31-
32-
benchmark("Insert lots of items", _ ++= range10m)
33-
benchmark("Drop some items from an head index", _.remove(5, 10000))
34-
benchmark("Drop some items from a tail index", b => b.remove(b.length - 10000, 10000))
35-
benchmark("Append lots of items one by one", b => range10m.foreach(b.+=))
36-
benchmark("Prepend few items one by one", b => (1 to 1000).foreach(_ +=: b))
37-
benchmark("Prepend lots of items at once", range10m ++=: _)
38-
benchmark("Insert items near head", _.insertAll(1000, range10m))
39-
benchmark("Reversal", _.reverse)
40-
benchmark("Insert items near tail", b => b.insertAll(b.size - 1000, range10m))
41-
benchmark("Sliding", _.sliding(size = 1000, step = 1000).size)
42-
benchmark("Random indexing", b => range10m.foreach(i => if (b.isDefinedAt(i)) b(i)))
43-
benchmark("toArray", _.toArray)
44-
benchmark("Clear lots of items", _.clear())
45-
}
3+
import strawman.collection.arrayToArrayOps
4+
5+
import java.util.concurrent.TimeUnit
6+
7+
import org.openjdk.jmh.annotations._
8+
import org.openjdk.jmh.infra.Blackhole
9+
10+
import scala.{Any, AnyRef, Int, Long, Unit, math}
11+
import scala.Predef.{intWrapper, $conforms}
12+
13+
@BenchmarkMode(scala.Array(Mode.AverageTime))
14+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
15+
@Fork(1)
16+
@Warmup(iterations = 8)
17+
@Measurement(iterations = 8)
18+
@State(Scope.Benchmark)
19+
class ArrayDequeBenchmark {
20+
@Param(scala.Array("0", "1", "2", "3", "4", "7", "8", "15", "16", "17", "39", "282", "4096", "131070", "7312102"))
21+
var size: Int = _
22+
23+
var xs: ArrayDeque[Long] = _
24+
var zs: ArrayDeque[Long] = _
25+
var zipped: ArrayDeque[(Long, Long)] = _
26+
var randomIndices: scala.Array[Int] = _
27+
def fresh(n: Int) = ArrayDeque((1 to n).map(_.toLong): _*)
28+
29+
@Setup(Level.Trial)
30+
def initTrial(): Unit = {
31+
xs = fresh(size)
32+
zs = fresh((size / 1000) max 2).map(-_)
33+
zipped = xs.map(x => (x, x))
34+
if (size > 0) {
35+
randomIndices = scala.Array.fill(1000)(scala.util.Random.nextInt(size))
36+
}
37+
}
38+
39+
@Benchmark
40+
def create(bh: Blackhole): Unit = bh.consume(fresh(size))
41+
42+
@Benchmark
43+
@OperationsPerInvocation(1000)
44+
def expand_prepend(bh: Blackhole): Unit = {
45+
val ys = xs
46+
var i = 0L
47+
while (i < 1000) {
48+
ys.prepend(i)
49+
i += 1
50+
}
51+
bh.consume(ys)
52+
}
53+
54+
@Benchmark
55+
@OperationsPerInvocation(1000)
56+
def expand_prependTail(bh: Blackhole): Unit = {
57+
var ys = xs
58+
var i = 0L
59+
while (i < 1000) {
60+
ys.insert(0, i)
61+
i += 1
62+
ys = ys.tail
63+
}
64+
bh.consume(ys)
65+
}
66+
67+
@Benchmark
68+
@OperationsPerInvocation(1000)
69+
def expand_append(bh: Blackhole): Unit = {
70+
val ys = xs
71+
var i = 0L
72+
while (i < 1000) {
73+
ys.addOne(i)
74+
i += 1
75+
}
76+
bh.consume(ys)
77+
}
78+
79+
@Benchmark
80+
@OperationsPerInvocation(1000)
81+
def expand_appendInit(bh: Blackhole): Unit = {
82+
var ys = xs
83+
var i = 0L
84+
while (i < 1000) {
85+
ys.addOne(i)
86+
i += 1
87+
ys = ys.init
88+
}
89+
bh.consume(ys)
90+
}
91+
92+
@Benchmark
93+
@OperationsPerInvocation(1000)
94+
def expand_prependAppend(bh: Blackhole): Unit = {
95+
val ys = xs
96+
var i = 0L
97+
while (i < 1000) {
98+
if ((i & 1) == 1) ys.addOne(i)
99+
else ys.insert(0, i)
100+
i += 1
101+
}
102+
bh.consume(ys)
103+
}
104+
105+
@Benchmark
106+
@OperationsPerInvocation(1000)
107+
def expand_prependAll(bh: Blackhole): Unit = {
108+
val ys = xs
109+
var i = 0L
110+
while (i < 1000) {
111+
ys.insertAll(0, zs)
112+
i += 1
113+
}
114+
bh.consume(ys)
115+
}
116+
117+
@Benchmark
118+
@OperationsPerInvocation(1000)
119+
def expand_appendAll(bh: Blackhole): Unit = {
120+
val ys = xs
121+
var i = 0L
122+
while (i < 1000) {
123+
ys.addAll(zs)
124+
i += 1
125+
}
126+
bh.consume(ys)
127+
}
128+
129+
@Benchmark
130+
@OperationsPerInvocation(1000)
131+
def expand_prependAllAppendAll(bh: Blackhole): Unit = {
132+
val ys = xs
133+
var i = 0L
134+
while (i < 1000) {
135+
if ((i & 1) == 1) ys.addAll(zs)
136+
else ys.insertAll(0, zs)
137+
i += 1
138+
}
139+
bh.consume(ys)
140+
}
141+
142+
@Benchmark
143+
def expand_padTo(bh: Blackhole): Unit = bh.consume(xs.padTo(size * 2, 42))
144+
145+
@Benchmark
146+
def traverse_foreach(bh: Blackhole): Unit = xs.foreach(x => bh.consume(x))
147+
148+
@Benchmark
149+
def traverse_headTail(bh: Blackhole): Unit = {
150+
var ys = xs
151+
while (ys.nonEmpty) {
152+
bh.consume(ys.head)
153+
ys = ys.tail
154+
}
155+
}
156+
157+
@Benchmark
158+
def traverse_initLast(bh: Blackhole): Unit = {
159+
var ys = xs
160+
while (ys.nonEmpty) {
161+
bh.consume(ys.last)
162+
ys = ys.init
163+
}
164+
}
165+
166+
@Benchmark
167+
def traverse_iterator(bh: Blackhole): Unit = {
168+
val it = xs.iterator()
169+
while (it.hasNext) {
170+
bh.consume(it.next())
171+
}
172+
}
173+
174+
@Benchmark
175+
def traverse_foldLeft(bh: Blackhole): Unit = bh.consume(xs.foldLeft(0) {
176+
case (acc, n) =>
177+
bh.consume(n)
178+
acc + 1
179+
})
180+
181+
@Benchmark
182+
def traverse_foldRight(bh: Blackhole): Unit = bh.consume(xs.foldRight(0) {
183+
case (n, acc) =>
184+
bh.consume(n)
185+
acc - 1
186+
})
187+
188+
@Benchmark
189+
@OperationsPerInvocation(1000)
190+
def access_last(bh: Blackhole): Unit = {
191+
var i = 0
192+
while (i < 1000) {
193+
bh.consume(xs(size - 1))
194+
i += 1
195+
}
196+
}
197+
198+
@Benchmark
199+
@OperationsPerInvocation(1000)
200+
def access_random(bh: Blackhole): Unit = {
201+
var i = 0
202+
while (i < 1000) {
203+
bh.consume(xs(randomIndices(i)))
204+
i += 1
205+
}
206+
}
207+
208+
@Benchmark
209+
def access_tail(bh: Blackhole): Unit = bh.consume(xs.tail)
210+
211+
@Benchmark
212+
def access_init(bh: Blackhole): Unit = bh.consume(xs.init)
213+
214+
@Benchmark
215+
@OperationsPerInvocation(100)
216+
def access_slice(bh: Blackhole): Unit = {
217+
var i = 0
218+
while (i < 100) {
219+
bh.consume(xs.slice(size - size / (i + 1), size))
220+
i += 1
221+
}
222+
}
223+
224+
@Benchmark
225+
@OperationsPerInvocation(1000)
226+
def transform_updateLast(bh: Blackhole): Unit = {
227+
var i = 0
228+
while (i < 1000) {
229+
bh.consume(xs.update(size - 1, i))
230+
i += 1
231+
}
232+
}
233+
234+
@Benchmark
235+
@OperationsPerInvocation(1000)
236+
def transform_updateRandom(bh: Blackhole): Unit = {
237+
var i = 0
238+
while (i < 1000) {
239+
bh.consume(xs.update(randomIndices(i), i))
240+
i += 1
241+
}
242+
}
243+
244+
@Benchmark
245+
@OperationsPerInvocation(100)
246+
def transform_patch(bh: Blackhole): Unit = {
247+
var i = 0
248+
while (i < 100) {
249+
val from = randomIndices(i)
250+
val replaced = randomIndices(if (i > 0) i - 1 else math.min(i + 1, size - 1))
251+
val length = randomIndices(if (i > 1) i - 2 else math.min(i + 2, size - 1))
252+
bh.consume(xs.patchInPlace(from, xs.take(length), replaced))
253+
i += 1
254+
}
255+
}
256+
257+
@Benchmark
258+
def transform_distinct(bh: Blackhole): Unit = bh.consume(xs.distinct)
259+
260+
@Benchmark
261+
def transform_distinctBy(bh: Blackhole): Unit = bh.consume(xs.distinctBy(_ % 2))
262+
263+
@Benchmark
264+
def transform_map(bh: Blackhole): Unit = bh.consume(xs.map(x => x + 1))
265+
266+
@Benchmark
267+
@OperationsPerInvocation(100)
268+
def transform_span(bh: Blackhole): Unit = {
269+
var i = 0
270+
while (i < 100) {
271+
val (xs1, xs2) = xs.span(x => x < randomIndices(i))
272+
bh.consume(xs1)
273+
bh.consume(xs2)
274+
i += 1
275+
}
276+
}
277+
278+
@Benchmark
279+
def transform_zip(bh: Blackhole): Unit = bh.consume(xs.zip(xs))
280+
281+
@Benchmark
282+
def transform_zipMapTupled(bh: Blackhole): Unit = {
283+
val f = (a: Long, b: Long) => (a, b)
284+
bh.consume(xs.zip(xs).map(f.tupled))
285+
}
286+
287+
@Benchmark
288+
def transform_zipWithIndex(bh: Blackhole): Unit = bh.consume(xs.zipWithIndex)
289+
290+
@Benchmark
291+
def transform_lazyZip(bh: Blackhole): Unit = bh.consume(xs.lazyZip(xs).map((_, _)))
292+
293+
@Benchmark
294+
def transform_unzip(bh: Blackhole): Unit = bh.consume(zipped.unzip)
295+
296+
@Benchmark
297+
def transform_reverse(bh: Blackhole): Unit = bh.consume(xs.reverse)
298+
299+
@Benchmark
300+
def transform_groupBy(bh: Blackhole): Unit = {
301+
val result = xs.groupBy(_ % 5)
302+
bh.consume(result)
303+
}
304+
}

0 commit comments

Comments
 (0)