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