Skip to content

Commit edbd76c

Browse files
committed
8344951: Stabilize write barrier micro-benchmarks
Reviewed-by: kvn, tschatzl
1 parent 842f801 commit edbd76c

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

test/micro/org/openjdk/bench/vm/compiler/WriteBarrier.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
2424

2525
import org.openjdk.jmh.annotations.Benchmark;
2626
import org.openjdk.jmh.annotations.BenchmarkMode;
27+
import org.openjdk.jmh.annotations.CompilerControl;
2728
import org.openjdk.jmh.annotations.Fork;
2829
import org.openjdk.jmh.annotations.Measurement;
2930
import org.openjdk.jmh.annotations.Mode;
@@ -42,23 +43,22 @@
4243
@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
4344
@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
4445
@Fork(value = 3)
45-
public class WriteBarrier {
46+
public abstract class WriteBarrier {
4647

4748
// For array references
4849
public static final int NUM_REFERENCES_SMALL = 32;
4950
public static final int NUM_REFERENCES_LARGE = 2048;
5051

5152
// For array update tests
5253
private Object[] theArraySmall;
53-
private Object[] realReferencesSmall;
54-
private Object[] nullReferencesSmall;
5554
private int[] indicesSmall;
5655

5756
private Object[] theArrayLarge;
58-
private Object[] realReferencesLarge;
59-
private Object[] nullReferencesLarge;
6057
private int[] indicesLarge;
6158

59+
private Object nullRef;
60+
private Object realRef;
61+
6262
// For field update tests
6363
public Referencer head = null;
6464
public Referencer tail = null;
@@ -84,13 +84,9 @@ void clear() {
8484
@Setup
8585
public void setup() {
8686
theArraySmall = new Object[NUM_REFERENCES_SMALL];
87-
realReferencesSmall = new Object[NUM_REFERENCES_SMALL];
88-
nullReferencesSmall = new Object[NUM_REFERENCES_SMALL];
8987
indicesSmall = new int[NUM_REFERENCES_SMALL];
9088

9189
theArrayLarge = new Object[NUM_REFERENCES_LARGE];
92-
realReferencesLarge = new Object[NUM_REFERENCES_LARGE];
93-
nullReferencesLarge = new Object[NUM_REFERENCES_LARGE];
9490
indicesLarge = new int[NUM_REFERENCES_LARGE];
9591

9692
m_w = (int) System.currentTimeMillis();
@@ -99,14 +95,14 @@ public void setup() {
9995

10096
for (int i = 0; i < NUM_REFERENCES_SMALL; i++) {
10197
indicesSmall[i] = get_random() % (NUM_REFERENCES_SMALL - 1);
102-
realReferencesSmall[i] = new Object();
10398
}
10499

105100
for (int i = 0; i < NUM_REFERENCES_LARGE; i++) {
106101
indicesLarge[i] = get_random() % (NUM_REFERENCES_LARGE - 1);
107-
realReferencesLarge[i] = new Object();
108102
}
109103

104+
realRef = new Object();
105+
110106
// Build a small linked structure
111107
this.head = new Referencer();
112108
this.tail = new Referencer();
@@ -124,31 +120,40 @@ private int get_random() {
124120
return Math.abs((m_z << 16) + m_w); /* 32-bit result */
125121
}
126122

123+
// This and the other testArrayWriteBarrierFast benchmarks below should not
124+
// be inlined into the JMH-generated harness method. If the methods were
125+
// inlined, we might spill in the main loop (on x64) depending on very
126+
// subtle conditions (such as whether LinuxPerfAsmProfiler is enabled!),
127+
// which could distort the results.
127128
@Benchmark
129+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
128130
public void testArrayWriteBarrierFastPathRealSmall() {
129131
for (int i = 0; i < NUM_REFERENCES_SMALL; i++) {
130-
theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = realReferencesSmall[indicesSmall[i]];
132+
theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = realRef;
131133
}
132134
}
133135

134136
@Benchmark
137+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
135138
public void testArrayWriteBarrierFastPathNullSmall() {
136139
for (int i = 0; i < NUM_REFERENCES_SMALL; i++) {
137-
theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = nullReferencesSmall[indicesSmall[i]];
140+
theArraySmall[indicesSmall[NUM_REFERENCES_SMALL - i - 1]] = nullRef;
138141
}
139142
}
140143

141144
@Benchmark
145+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
142146
public void testArrayWriteBarrierFastPathRealLarge() {
143147
for (int i = 0; i < NUM_REFERENCES_LARGE; i++) {
144-
theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = realReferencesLarge[indicesLarge[i]];
148+
theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = realRef;
145149
}
146150
}
147151

148152
@Benchmark
153+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
149154
public void testArrayWriteBarrierFastPathNullLarge() {
150155
for (int i = 0; i < NUM_REFERENCES_LARGE; i++) {
151-
theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = nullReferencesLarge[indicesLarge[i]];
156+
theArrayLarge[indicesLarge[NUM_REFERENCES_LARGE - i - 1]] = nullRef;
152157
}
153158
}
154159

@@ -160,4 +165,15 @@ public void testFieldWriteBarrierFastPath() {
160165
this.head.append(this.tail);
161166
this.tail.clear();
162167
}
168+
169+
// This run is useful to compare different GC barrier models without being
170+
// affected by C2 unrolling the main loop differently for each model.
171+
@Fork(value = 3, jvmArgs = {"-XX:LoopUnrollLimit=1"})
172+
public static class WithoutUnrolling extends WriteBarrier {}
173+
174+
// This run is useful to study the interaction of GC barriers and loop
175+
// unrolling. Check that the main loop in the testArray benchmarks is
176+
// unrolled (or not) as expected for the studied GC barrier model.
177+
@Fork(value = 3)
178+
public static class WithDefaultUnrolling extends WriteBarrier {}
163179
}

0 commit comments

Comments
 (0)