Skip to content

Commit 960e273

Browse files
authored
Merge pull request #19 from scala/benchmark
Add micro-benchmarks
2 parents b396f5f + 8958d26 commit 960e273

File tree

15 files changed

+525
-15
lines changed

15 files changed

+525
-15
lines changed

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Collection-Strawman
1+
# Collection-Strawman
22

33
[![Join the chat at https://gitter.im/scala/collection-strawman](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/scala/collection-strawman?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
44

@@ -7,3 +7,19 @@ Prototype improvements for Scala collections.
77
- [Gitter Discussion](https://gitter.im/scala/collection-strawman)
88
- [Dotty Issue](https://github.com/lampepfl/dotty/issues/818)
99
- [Scala Center Proposal](https://github.com/scalacenter/advisoryboard/blob/master/proposals/007-collections.md)
10+
11+
## Build
12+
13+
- Compile the collections and run the
14+
tests:
15+
~~~
16+
>; compile; test
17+
~~~
18+
- Run the memory benchmark:
19+
~~~
20+
> memoryBenchmark/run
21+
~~~
22+
- Run the execution time benchmark:
23+
~~~
24+
> timeBenchmark/jmh:run
25+
~~~
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package bench
2+
3+
import strawman.collection.immutable.{LazyList, List}
4+
5+
import scala.{Any, AnyRef, App, Int, Long}
6+
import scala.Predef.{println, ArrowAssoc}
7+
import scala.compat.Platform
8+
import java.lang.Runtime
9+
10+
import strawman.collection.mutable.{ArrayBuffer, ListBuffer}
11+
12+
object MemoryFootprint extends App {
13+
14+
val sizes = scala.List(8, 64, 512, 4096, 32768, 262144, 2097152)
15+
16+
val runtime = Runtime.getRuntime
17+
val obj: AnyRef = null
18+
var placeholder: Any = _
19+
20+
def benchmark[A](gen: Int => A): scala.List[(Int, Long)] = (
21+
// We run 5 iterations and pick the last result only
22+
for (_ <- scala.Range(0, 5)) yield {
23+
for (size <- sizes) yield {
24+
placeholder = null
25+
Platform.collectGarbage()
26+
val memBefore = runtime.totalMemory() - runtime.freeMemory()
27+
placeholder = gen(size)
28+
Platform.collectGarbage()
29+
val memAfter = runtime.totalMemory() - runtime.freeMemory()
30+
size -> (memAfter - memBefore)
31+
}
32+
}
33+
).last
34+
35+
val memories =
36+
scala.Predef.Map(
37+
"scala.List" -> benchmark(scala.List.fill(_)(obj)),
38+
"List" -> benchmark(List.fill(_)(obj)),
39+
"LazyList" -> benchmark(LazyList.fill(_)(obj)),
40+
"ArrayBuffer" -> benchmark(ArrayBuffer.fill(_)(obj)),
41+
"ListBuffer" -> benchmark(ListBuffer.fill(_)(obj))
42+
)
43+
44+
// Print the results as a CSV document
45+
println("Collection;" + sizes.mkString(";"))
46+
for ((name, values) <- memories) {
47+
println(name + ";" + values.map(_._2).mkString(";"))
48+
}
49+
50+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package strawman.collection.immutable
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.openjdk.jmh.annotations._
6+
import scala.{Any, AnyRef, Int, Unit}
7+
8+
@BenchmarkMode(scala.Array(Mode.AverageTime))
9+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
10+
@Fork(1)
11+
@Warmup(iterations = 12)
12+
@Measurement(iterations = 12)
13+
@State(Scope.Benchmark)
14+
class LazyListBenchmark {
15+
16+
@Param(scala.Array("8", "64", "512", "4096", "32768", "262144"/*, "2097152"*/))
17+
var size: Int = _
18+
19+
var xs: LazyList[AnyRef] = _
20+
var obj: Any = _
21+
22+
@Setup(Level.Trial)
23+
def initData(): Unit = {
24+
xs = LazyList.fill(size)("")
25+
obj = ""
26+
}
27+
28+
@Benchmark
29+
def cons(): Any = {
30+
var ys = LazyList.empty[Any]
31+
var i = 0
32+
while (i < size) {
33+
ys = obj #:: ys
34+
i += 1
35+
}
36+
ys
37+
}
38+
39+
@Benchmark
40+
def uncons(): Any = xs.tail
41+
42+
@Benchmark
43+
def concat(): Any = xs ++ xs
44+
45+
@Benchmark
46+
def foreach(): Any = {
47+
var n = 0
48+
xs.foreach(x => if (x eq null) n += 1)
49+
n
50+
}
51+
52+
@Benchmark
53+
def lookup(): Any = xs(size - 1)
54+
55+
@Benchmark
56+
def map(): Any = xs.map(x => if (x eq null) "foo" else "bar")
57+
58+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package strawman.collection.immutable
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.openjdk.jmh.annotations._
6+
7+
import scala.{Any, AnyRef, Int, Unit}
8+
9+
@BenchmarkMode(scala.Array(Mode.AverageTime))
10+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
11+
@Fork(1)
12+
@Warmup(iterations = 12)
13+
@Measurement(iterations = 12)
14+
@State(Scope.Benchmark)
15+
class ListBenchmark {
16+
17+
@Param(scala.Array("8", "64", "512", "4096", "32768", "262144"/*, "2097152"*/))
18+
var size: Int = _
19+
20+
var xs: List[AnyRef] = _
21+
var obj: Any = _
22+
23+
@Setup(Level.Trial)
24+
def initData(): Unit = {
25+
xs = List.fill(size)("")
26+
obj = ""
27+
}
28+
29+
@Benchmark
30+
def cons(): Any = {
31+
var ys = List.empty[Any]
32+
var i = 0
33+
while (i < size) {
34+
ys = obj :: ys
35+
i += 1
36+
}
37+
ys
38+
}
39+
40+
@Benchmark
41+
def uncons(): Any = xs.tail
42+
43+
@Benchmark
44+
def concat(): Any = xs ++ xs
45+
46+
@Benchmark
47+
def foreach(): Any = {
48+
var n = 0
49+
xs.foreach(x => if (x eq null) n += 1)
50+
n
51+
}
52+
53+
@Benchmark
54+
def foreach_while(): Any = {
55+
var n = 0
56+
var ys = xs
57+
while (ys.nonEmpty) {
58+
if (ys.head eq null) n += 1
59+
ys = ys.tail
60+
}
61+
n
62+
}
63+
64+
@Benchmark
65+
def lookup(): Any = xs(size - 1)
66+
67+
@Benchmark
68+
def map(): Any = xs.map(x => if (x eq null) "foo" else "bar")
69+
70+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package strawman.collection.immutable
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.openjdk.jmh.annotations._
6+
import scala.{Any, AnyRef, Int, Unit}
7+
8+
@BenchmarkMode(scala.Array(Mode.AverageTime))
9+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
10+
@Fork(1)
11+
@Warmup(iterations = 12)
12+
@Measurement(iterations = 12)
13+
@State(Scope.Benchmark)
14+
class ScalaListBenchmark {
15+
16+
@Param(scala.Array("8", "64", "512", "4096", "32768", "262144"/*, "2097152"*/))
17+
var size: Int = _
18+
19+
var xs: scala.List[AnyRef] = _
20+
var obj: Any = _
21+
22+
@Setup(Level.Trial)
23+
def initData(): Unit = {
24+
xs = scala.List.fill(size)("")
25+
obj = ""
26+
}
27+
28+
@Benchmark
29+
def cons(): Any = {
30+
var ys = scala.List.empty[Any]
31+
var i = 0
32+
while (i < size) {
33+
ys = obj :: ys
34+
i += 1
35+
}
36+
ys
37+
}
38+
39+
@Benchmark
40+
def uncons(): Any = xs.tail
41+
42+
@Benchmark
43+
def concat(): Any = xs ++ xs
44+
45+
@Benchmark
46+
def foreach(): Any = {
47+
var n = 0
48+
xs.foreach(x => if (x eq null) n += 1)
49+
n
50+
}
51+
52+
@Benchmark
53+
def lookup(): Any = xs(size - 1)
54+
55+
@Benchmark
56+
def map(): Any = xs.map(x => if (x eq null) "foo" else "bar")
57+
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package strawman.collection.mutable
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.openjdk.jmh.annotations._
6+
import scala.{Any, AnyRef, Int, Unit}
7+
8+
@BenchmarkMode(scala.Array(Mode.AverageTime))
9+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
10+
@Fork(1)
11+
@Warmup(iterations = 12)
12+
@Measurement(iterations = 12)
13+
@State(Scope.Benchmark)
14+
class ArrayBufferBenchmark {
15+
16+
@Param(scala.Array("8", "64", "512", "4096", "32768", "262144"/*, "2097152"*/))
17+
var size: Int = _
18+
19+
var xs: ArrayBuffer[AnyRef] = _
20+
var obj: Any = _
21+
22+
@Setup(Level.Trial)
23+
def initData(): Unit = {
24+
xs = ArrayBuffer.fill(size)("")
25+
obj = ""
26+
}
27+
28+
@Benchmark
29+
def cons(): Any = {
30+
var ys = ArrayBuffer.empty[Any]
31+
var i = 0
32+
while (i < size) {
33+
ys += obj
34+
i += 1
35+
}
36+
ys
37+
}
38+
39+
@Benchmark
40+
def uncons(): Any = xs.tail
41+
42+
@Benchmark
43+
def concat(): Any = xs ++ xs
44+
45+
@Benchmark
46+
def foreach(): Any = {
47+
var n = 0
48+
xs.foreach(x => if (x eq null) n += 1)
49+
n
50+
}
51+
52+
@Benchmark
53+
def lookup(): Any = xs(size - 1)
54+
55+
@Benchmark
56+
def map(): Any = xs.map(x => if (x eq null) "foo" else "bar")
57+
58+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package strawman.collection.mutable
2+
3+
import java.util.concurrent.TimeUnit
4+
5+
import org.openjdk.jmh.annotations._
6+
import scala.{Any, AnyRef, Int, Unit}
7+
8+
@BenchmarkMode(scala.Array(Mode.AverageTime))
9+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
10+
@Fork(1)
11+
@Warmup(iterations = 12)
12+
@Measurement(iterations = 12)
13+
@State(Scope.Benchmark)
14+
class ListBufferBenchmark {
15+
16+
@Param(scala.Array("8", "64", "512", "4096", "32768", "262144"/*, "2097152"*/))
17+
var size: Int = _
18+
19+
var xs: ListBuffer[AnyRef] = _
20+
var obj: Any = _
21+
22+
@Setup(Level.Trial)
23+
def initData(): Unit = {
24+
xs = ListBuffer.fill(size)("")
25+
obj = ""
26+
}
27+
28+
@Benchmark
29+
def cons(): Any = {
30+
var ys = ListBuffer.empty[Any]
31+
var i = 0
32+
while (i < size) {
33+
ys += obj
34+
i += 1
35+
}
36+
ys
37+
}
38+
39+
@Benchmark
40+
def uncons(): Any = xs.tail
41+
42+
@Benchmark
43+
def concat(): Any = xs ++ xs
44+
45+
@Benchmark
46+
def foreach(): Any = {
47+
var n = 0
48+
xs.foreach(x => if (x eq null) n += 1)
49+
n
50+
}
51+
52+
@Benchmark
53+
def lookup(): Any = xs(size - 1)
54+
55+
@Benchmark
56+
def map(): Any = xs.map(x => if (x eq null) "foo" else "bar")
57+
58+
}

0 commit comments

Comments
 (0)