changeset 336:819b9ca864a2

Runners: optimize StateHolder and generated code against false sharing.
author shade
date Fri, 21 Oct 2016 21:41:32 +0200
parents 5415383d3d3e
children 474614a894d4
files jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/StateHolder.java jcstress-core/src/main/java/org/openjdk/jcstress/vm/ContendedTestMain.java jcstress-core/src/main/java/org/openjdk/jcstress/vm/VMSupport.java
diffstat 4 files changed, 75 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java	Fri Oct 21 20:46:34 2016 +0200
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/processors/JCStressTestProcessor.java	Fri Oct 21 21:41:32 2016 +0200
@@ -430,7 +430,7 @@
         pw.println("    }");
         pw.println();
 
-        pw.println("    public final void jcstress_consume(StateHolder<Pair> holder, Counter<" + r + "> cnt, int a, int actors) {");
+        pw.println("    public final void jcstress_consume(StateHolder<Pair> holder, OpenAddressHashCounter<" + r + "> cnt, int a, int actors) {");
         pw.println("        Pair[] pairs = holder.pairs;");
         pw.println("        int len = pairs.length;");
         pw.println("        int left = a * len / actors;");
@@ -504,6 +504,9 @@
             if (!isStateItself) {
                 pw.println("        " + t + " lt = test;");
             }
+
+            pw.println("        OpenAddressHashCounter<" + r + "> counter = counter_" + a.getSimpleName() + ";");
+
             pw.println("        while (true) {");
             pw.println("            StateHolder<Pair> holder = version;");
             pw.println("            if (holder.stopped) {");
@@ -541,7 +544,7 @@
             pw.println();
             pw.println("            holder.postRun();");
             pw.println();
-            pw.println("            jcstress_consume(holder, counter_" + a.getSimpleName() + ", " + n + ", " + actorsCount + ");");
+            pw.println("            jcstress_consume(holder, counter, " + n + ", " + actorsCount + ");");
             pw.println("            jcstress_updateHolder(holder);");
             pw.println();
             pw.println("            holder.postUpdate();");
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/StateHolder.java	Fri Oct 21 20:46:34 2016 +0200
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/infra/runners/StateHolder.java	Fri Oct 21 21:41:32 2016 +0200
@@ -24,20 +24,70 @@
  */
 package org.openjdk.jcstress.infra.runners;
 
-import java.util.concurrent.atomic.AtomicInteger;
+
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
 /**
  * @author Aleksey Shipilev (aleksey.shipilev@oracle.com)
  */
 public class StateHolder<P> {
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
     public final boolean stopped;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
     public final P[] pairs;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
     public final int countWorkers;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
     public final SpinLoopStyle spinStyle;
-    public final AtomicInteger started, ready, finished, consumed;
-    public volatile boolean notAllStarted, notAllReady, notAllFinished, notUpdated;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile int started;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile int ready;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile int finished;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile int consumed;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile boolean notAllStarted;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile boolean notAllReady;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile boolean notAllFinished;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
+    private volatile boolean notUpdated;
+
+    @sun.misc.Contended
+    @jdk.internal.vm.annotation.Contended
     public volatile boolean updateStride;
 
+    static final AtomicIntegerFieldUpdater<StateHolder> UPDATER_STARTED  = AtomicIntegerFieldUpdater.newUpdater(StateHolder.class, "started");
+    static final AtomicIntegerFieldUpdater<StateHolder> UPDATER_READY    = AtomicIntegerFieldUpdater.newUpdater(StateHolder.class, "ready");
+    static final AtomicIntegerFieldUpdater<StateHolder> UPDATER_FINISHED = AtomicIntegerFieldUpdater.newUpdater(StateHolder.class, "finished");
+    static final AtomicIntegerFieldUpdater<StateHolder> UPDATER_CONSUMED = AtomicIntegerFieldUpdater.newUpdater(StateHolder.class, "consumed");
+
     /**
      * Initial version
      */
@@ -54,10 +104,10 @@
         this.pairs = pairs;
         this.countWorkers = expectedWorkers;
         this.spinStyle = spinStyle;
-        this.ready = new AtomicInteger(expectedWorkers);
-        this.started = new AtomicInteger(expectedWorkers);
-        this.finished = new AtomicInteger(expectedWorkers);
-        this.consumed = new AtomicInteger(expectedWorkers);
+        UPDATER_STARTED.set(this, expectedWorkers);
+        UPDATER_READY.set(this, expectedWorkers);
+        UPDATER_FINISHED.set(this, expectedWorkers);
+        UPDATER_CONSUMED.set(this, expectedWorkers);
         this.notAllReady = true;
         this.notAllFinished = true;
         this.notAllStarted = true;
@@ -65,7 +115,7 @@
     }
 
     public void preRun() {
-        int v = ready.decrementAndGet();
+        int v = UPDATER_READY.decrementAndGet(this);
         if (v == 0) {
             notAllReady = false;
         }
@@ -81,13 +131,13 @@
                 while (notAllReady);
         }
 
-        if (started.decrementAndGet() == 0) {
+        if (UPDATER_STARTED.decrementAndGet(this) == 0) {
             notAllStarted = false;
         }
     }
 
     public void postRun() {
-        if (finished.decrementAndGet() == 0) {
+        if (UPDATER_FINISHED.decrementAndGet(this) == 0) {
             notAllFinished = false;
         }
         updateStride |= notAllStarted;
@@ -105,7 +155,7 @@
     }
 
     public boolean tryStartUpdate()  {
-        return (consumed.decrementAndGet() == 0);
+        return (UPDATER_CONSUMED.decrementAndGet(this) == 0);
     }
 
     public void finishUpdate() {
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/vm/ContendedTestMain.java	Fri Oct 21 20:46:34 2016 +0200
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/vm/ContendedTestMain.java	Fri Oct 21 21:41:32 2016 +0200
@@ -25,15 +25,15 @@
 package org.openjdk.jcstress.vm;
 
 import org.openjdk.jcstress.annotations.Result;
+import org.openjdk.jcstress.annotations.State;
+import org.openjdk.jcstress.infra.runners.StateHolder;
 import org.openjdk.jcstress.util.Reflections;
 import org.openjdk.jcstress.util.UnsafeHolder;
 
 import java.io.IOException;
 import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.lang.reflect.Modifier;
+import java.util.*;
 
 public class ContendedTestMain {
 
@@ -47,11 +47,14 @@
             throw new IllegalStateException("Classes not found");
         }
 
+        Set<Class> infraClasses = Collections.singleton(StateHolder.class);
+
         for (Class<?> cl : classes) {
-            if (cl.getAnnotation(Result.class) == null) continue;
+            if (!infraClasses.contains(cl) && cl.getAnnotation(Result.class) == null) continue;
 
             List<FieldDef> fdefs = new ArrayList<>();
             for (Field f : cl.getDeclaredFields()) {
+                if (Modifier.isStatic(f.getModifiers())) continue;
                 fdefs.add(new FieldDef(f));
             }
 
--- a/jcstress-core/src/main/java/org/openjdk/jcstress/vm/VMSupport.java	Fri Oct 21 20:46:34 2016 +0200
+++ b/jcstress-core/src/main/java/org/openjdk/jcstress/vm/VMSupport.java	Fri Oct 21 21:41:32 2016 +0200
@@ -78,7 +78,7 @@
                 "-XX:G1ConcRefinementThreads=4",
                 SimpleTestMain.class);
 
-        detect("Testing @Contended works on all results",
+        detect("Testing @Contended works on all results and infra objects",
                 "-XX:-RestrictContended",
                 ContendedTestMain.class);