目标:在java中测试虚假共享
问题:我在字段上添加了@Contended 注释,但类布局没有显示填充字节。虚假分享仍然发生。
我有 3 个测试:
- 没有填充
- 添加长变量作为填充字节
- 使用@Contended 注解添加填充字节
环境:
- macos Monterey 12.1 MacBookPro m1 max
- OpenJDK 运行时环境 (Zulu 8.52.0.23-CA-macos-aarch64) (build 1.8.0_282-b08)
ps:我已经尝试添加-XX:-RestrictContended
选项,但仍然无法正常工作。
这是我的测试代码:
public class FalseSharing {
public final static int NUM_THREADS = 4; // change
public static class FalseSharingTestBase {
public final static long ITERATIONS = 500*1000*1000L;
protected final int arrayIndex;
public FalseSharingTestBase(final int arrayIndex) {
this.arrayIndex = arrayIndex;
}
}
static class TestCase1 extends FalseSharingTestBase implements Runnable {
protected static VolatileLong1[] longs1 = new VolatileLong1[NUM_THREADS];
static {
for (int i = 0; i < longs1.length; i++) {
longs1[i] = new VolatileLong1();
}
}
public TestCase1(int arrayIndex) {
super(arrayIndex);
}
@Override
public void run() {
long i = ITERATIONS + 1;
while (0 != --i) {
longs1[arrayIndex].value = i;
}
}
}
static class TestCase2 extends FalseSharingTestBase implements Runnable {
protected static VolatileLong2[] longs2 = new VolatileLong2[NUM_THREADS];
static {
for (int i = 0; i < longs2.length; i++) {
longs2[i] = new VolatileLong2();
}
}
public TestCase2(int arrayIndex) {
super(arrayIndex);
}
@Override
public void run() {
long i = ITERATIONS + 1;
while (0 != --i) {
longs2[arrayIndex].value = i;
}
}
}
static class TestCase3 extends FalseSharingTestBase implements Runnable {
protected static VolatileLong3[] longs3 = new VolatileLong3[NUM_THREADS];
static {
for (int i = 0; i < longs3.length; i++) {
longs3[i] = new VolatileLong3();
}
}
public TestCase3(int arrayIndex) {
super(arrayIndex);
}
@Override
public void run() {
long i = ITERATIONS + 1;
while (0 <= --i) {
longs3[arrayIndex].value = i;
}
}
}
public final static class VolatileLong1 {
public volatile long value = 0L;
}
// long padding避免false sharing
public final static class VolatileLong2 {
volatile long p0, p1, p2, p3, p4, p5, p6, p7;
volatile long p10, p11, p12, p13, p14, p15, p16, p17;
public volatile long value = 0L;
volatile long q0, q1, q2, q3, q4, q5, q6, q7;
volatile long q10, q11, q12, q13, q14, q15, q16, q17;
}
public final static class VolatileLong3 {
@sun.misc.Contended
public volatile long value = 0L;
}
public static void main(final String[] args) throws Exception {
System.out.println("volatile1 layout: ");
ObjectUtil.printCls(VolatileLong1.class);
System.out.println("volatile2 layout: ");
ObjectUtil.printCls(VolatileLong2.class);
System.out.println("volatile3 layout: ");
ObjectUtil.printCls(VolatileLong3.class);
long start = System.nanoTime();
Thread[] threads = new Thread[NUM_THREADS];
for (int i = 0; i < threads.length; i++) {
// threads[i] = new Thread(new TestCase1(i));
// threads[i] = new Thread(new TestCase2(i));
threads[i] = new Thread(new TestCase3(i));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
System.out.println("duration = " + (System.nanoTime() - start));
}
}
输出:
volatile1 layout:
# WARNING: Unable to attach Serviceability Agent. Unable to attach even with module exceptions: [org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed., org.openjdk.jol.vm.sa.SASupportException: Sense failed.]
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong1 object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) N/A
8 4 (object header: class) N/A
12 4 (alignment/padding gap)
16 8 long VolatileLong1.value N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
volatile2 layout:
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong2 object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) N/A
8 4 (object header: class) N/A
12 4 (alignment/padding gap)
16 8 long VolatileLong2.p0 N/A
24 8 long VolatileLong2.p1 N/A
32 8 long VolatileLong2.p2 N/A
40 8 long VolatileLong2.p3 N/A
48 8 long VolatileLong2.p4 N/A
56 8 long VolatileLong2.p5 N/A
64 8 long VolatileLong2.p6 N/A
72 8 long VolatileLong2.p7 N/A
80 8 long VolatileLong2.p10 N/A
88 8 long VolatileLong2.p11 N/A
96 8 long VolatileLong2.p12 N/A
104 8 long VolatileLong2.p13 N/A
112 8 long VolatileLong2.p14 N/A
120 8 long VolatileLong2.p15 N/A
128 8 long VolatileLong2.p16 N/A
136 8 long VolatileLong2.p17 N/A
144 8 long VolatileLong2.value N/A
152 8 long VolatileLong2.q0 N/A
160 8 long VolatileLong2.q1 N/A
168 8 long VolatileLong2.q2 N/A
176 8 long VolatileLong2.q3 N/A
184 8 long VolatileLong2.q4 N/A
192 8 long VolatileLong2.q5 N/A
200 8 long VolatileLong2.q6 N/A
208 8 long VolatileLong2.q7 N/A
216 8 long VolatileLong2.q10 N/A
224 8 long VolatileLong2.q11 N/A
232 8 long VolatileLong2.q12 N/A
240 8 long VolatileLong2.q13 N/A
248 8 long VolatileLong2.q14 N/A
256 8 long VolatileLong2.q15 N/A
264 8 long VolatileLong2.q16 N/A
272 8 long VolatileLong2.q17 N/A
Instance size: 280 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
volatile3 layout:
cn.windery.learning.jvm.cache.FalseSharing$VolatileLong3 object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) N/A
8 4 (object header: class) N/A
12 4 (alignment/padding gap)
16 8 long VolatileLong3.value N/A
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
duration = 1468214167