Skip to content

Commit 3b4594c

Browse files
committed
Looking at the cost of trait fowarders
Hypothesis is that the forwarders in subclasses impose a cost due to megamorphic virtual calls. // Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode) > jmh:run -i 10 -wi 5 -f2 -t1 .*Mixin.* [info] Benchmark (count) Mode Cnt Score Error Units [info] MixinForwarderBenchmark.baseClass_1 16 thrpt 20 18537399.061 ± 521221.353 ops/s [info] MixinForwarderBenchmark.baseClass_16 16 thrpt 20 19137762.320 ± 510049.157 ops/s [info] MixinForwarderBenchmark.baseTrait_1 16 thrpt 20 18178697.687 ± 404180.617 ops/s [info] MixinForwarderBenchmark.baseTrait_16 16 thrpt 20 10786408.479 ± 162705.033 ops/s [info] MixinForwarderBenchmark.jbaseInterface_1 16 thrpt 20 18531993.312 ± 401611.669 ops/s [info] MixinForwarderBenchmark.jbaseInterface_16 16 thrpt 20 9642052.651 ± 228326.457 ops/s [success] Total time: 188 s, completed 22/04/2016 6:39:08 PM
1 parent 637d3d8 commit 3b4594c

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package scala.tools.nsc
2+
3+
import java.util.Random
4+
5+
import org.openjdk.jmh.annotations._
6+
import org.openjdk.jmh.infra.Blackhole
7+
8+
import scala.annotation.meta.{field, getter}
9+
10+
@State(Scope.Thread)
11+
class MixinForwarderBenchmark {
12+
class C {
13+
def foo = 42
14+
}
15+
class C_1 extends C
16+
class C_2 extends C
17+
class C_3 extends C
18+
class C_4 extends C
19+
class C_5 extends C
20+
class C_6 extends C
21+
class C_7 extends C
22+
class C_8 extends C
23+
class C_9 extends C
24+
class C_10 extends C
25+
class C_11 extends C
26+
class C_12 extends C
27+
class C_13 extends C
28+
class C_14 extends C
29+
class C_15 extends C
30+
class C_16 extends C
31+
trait T {
32+
def foo = 42
33+
}
34+
class T_1 extends T
35+
class T_2 extends T
36+
class T_3 extends T
37+
class T_4 extends T
38+
class T_5 extends T
39+
class T_6 extends T
40+
class T_7 extends T
41+
class T_8 extends T
42+
class T_9 extends T
43+
class T_10 extends T
44+
class T_11 extends T
45+
class T_12 extends T
46+
class T_13 extends T
47+
class T_14 extends T
48+
class T_15 extends T
49+
class T_16 extends T
50+
51+
@(Param @field)(Array("16"))
52+
private[this] var count: Int = 0
53+
54+
private[this] var zero: Int = 0
55+
56+
private[this] val cs_16 = Array(new C_1, new C_2, new C_3, new C_4, new C_5, new C_6, new C_7, new C_8, new C_9, new C_10, new C_11, new C_12, new C_13, new C_14, new C_15, new C_16)
57+
private[this] val ts_16 = Array(new T_1, new T_2, new T_3, new T_4, new T_5, new T_6, new T_7, new T_8, new T_9, new T_10, new T_11, new T_12, new T_13, new T_14, new T_15, new T_16)
58+
import MixinForwarderBenchmarkSupport._
59+
private[this] val js_16 = Array[J](new J_1, new J_2, new J_3, new J_4, new J_5, new J_6, new J_7, new J_8, new J_9, new J_10, new J_11, new J_12, new J_13, new J_14, new J_15, new J_16)
60+
61+
private[this] var cs_16_random: Array[C] = _
62+
private[this] var ts_16_random: Array[T] = _
63+
private[this] var js_16_random: Array[J] = _
64+
65+
@Setup
66+
def create(): Unit = {
67+
val r = new Random()
68+
cs_16_random = Array.tabulate(count) {
69+
_ => cs_16.apply(r.nextInt(cs_16.length))
70+
}
71+
72+
ts_16_random = Array.tabulate(count) {
73+
_ => ts_16.apply(r.nextInt(ts_16.length))
74+
}
75+
76+
js_16_random = Array.tabulate(count) {
77+
_ => js_16.apply(r.nextInt(js_16.length))
78+
}
79+
}
80+
81+
@Benchmark
82+
def baseClass_1(bh: Blackhole): Unit = {
83+
var i = 0
84+
val c = count
85+
while (i < c) {
86+
bh.consume(cs_16_random(zero))
87+
i += 1
88+
}
89+
}
90+
91+
@Benchmark
92+
def baseClass_16(bh: Blackhole): Unit = {
93+
var i = 0
94+
val c = count
95+
while (i < c) {
96+
bh.consume(cs_16_random(i).foo)
97+
i += 1
98+
}
99+
}
100+
101+
@Benchmark
102+
def baseTrait_1(bh: Blackhole): Unit = {
103+
var i = 0
104+
val c = count
105+
while (i < c) {
106+
bh.consume(ts_16_random(zero).foo)
107+
i += 1
108+
}
109+
}
110+
111+
@Benchmark
112+
def baseTrait_16(bh: Blackhole): Unit = {
113+
var i = 0
114+
val c = count
115+
while (i < c) {
116+
bh.consume(ts_16_random(i).foo)
117+
i += 1
118+
}
119+
}
120+
121+
@Benchmark
122+
def jbaseInterface_1(bh: Blackhole): Unit = {
123+
var i = 0
124+
val c = count
125+
while (i < c) {
126+
bh.consume(js_16_random(zero).foo)
127+
i += 1
128+
}
129+
}
130+
131+
@Benchmark
132+
def jbaseInterface_16(bh: Blackhole): Unit = {
133+
var i = 0
134+
val c = count
135+
while (i < c) {
136+
bh.consume(js_16_random(i).foo)
137+
i += 1
138+
}
139+
}
140+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package scala.tools.nsc;
2+
3+
public class MixinForwarderBenchmarkSupport {
4+
interface J {
5+
default int foo() { return 42; }
6+
}
7+
public static class J_1 implements J {}
8+
public static class J_2 implements J {}
9+
public static class J_3 implements J {}
10+
public static class J_4 implements J {}
11+
public static class J_5 implements J {}
12+
public static class J_6 implements J {}
13+
public static class J_7 implements J {}
14+
public static class J_8 implements J {}
15+
public static class J_9 implements J {}
16+
public static class J_10 implements J {}
17+
public static class J_11 implements J {}
18+
public static class J_12 implements J {}
19+
public static class J_13 implements J {}
20+
public static class J_14 implements J {}
21+
public static class J_15 implements J {}
22+
public static class J_16 implements J {}
23+
}

0 commit comments

Comments
 (0)