test/jdk/java/util/concurrent/atomic/DoubleAdderDemo.java
changeset 47216 71c04702a3d5
parent 15283 e331a847ff27
child 58138 1e4270f875ee
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/util/concurrent/atomic/DoubleAdderDemo.java	Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Adapted from Dougs CVS test/jsr166e/DoubleAdderDemo.java
+ *
+ * The demo is a micro-benchmark to compare synchronized access to a primitive
+ * double and DoubleAdder (run without any args), this restricted version simply
+ * exercises the basic functionality of DoubleAdder, suitable for automated
+ * testing (-shortrun).
+ */
+
+/*
+ * @test
+ * @bug 8005311
+ * @run main DoubleAdderDemo -shortrun
+ * @summary Basic test for Doubledder
+ */
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.atomic.DoubleAdder;
+
+public class DoubleAdderDemo {
+    static final int INCS_PER_THREAD = 10000000;
+    static final int NCPU = Runtime.getRuntime().availableProcessors();
+    static final int SHORT_RUN_MAX_THREADS = NCPU > 1 ? NCPU / 2 : 1;
+    static final int LONG_RUN_MAX_THREADS = NCPU * 2;
+    static final ExecutorService pool = Executors.newCachedThreadPool();
+
+    static final class SynchronizedDoubleAdder {
+        double value;
+        synchronized double sum() { return value; }
+        synchronized void add(double x) { value += x; }
+    }
+
+    public static void main(String[] args) {
+        boolean shortRun = args.length > 0 && args[0].equals("-shortrun");
+        int maxNumThreads = shortRun ? SHORT_RUN_MAX_THREADS : LONG_RUN_MAX_THREADS;
+
+        System.out.println("Warmup...");
+        int half = NCPU > 1 ? NCPU / 2 : 1;
+        if (!shortRun)
+            syncTest(half, 1000);
+        adderTest(half, 1000);
+
+        for (int reps = 0; reps < 2; ++reps) {
+            System.out.println("Running...");
+            for (int i = 1; i <= maxNumThreads; i <<= 1) {
+                if (!shortRun)
+                    syncTest(i, INCS_PER_THREAD);
+                adderTest(i, INCS_PER_THREAD);
+            }
+        }
+        pool.shutdown();
+    }
+
+    static void syncTest(int nthreads, int incs) {
+        System.out.print("Synchronized ");
+        Phaser phaser = new Phaser(nthreads + 1);
+        SynchronizedDoubleAdder a = new SynchronizedDoubleAdder();
+        for (int i = 0; i < nthreads; ++i)
+            pool.execute(new SyncTask(a, phaser, incs));
+        report(nthreads, incs, timeTasks(phaser), a.sum());
+    }
+
+    static void adderTest(int nthreads, int incs) {
+        System.out.print("DoubleAdder  ");
+        Phaser phaser = new Phaser(nthreads + 1);
+        DoubleAdder a = new DoubleAdder();
+        for (int i = 0; i < nthreads; ++i)
+            pool.execute(new AdderTask(a, phaser, incs));
+        report(nthreads, incs, timeTasks(phaser), a.sum());
+    }
+
+    static void report(int nthreads, int incs, long time, double sum) {
+        long total = (long)nthreads * incs;
+        if (sum != (double)total)
+            throw new Error(sum + " != " + total);
+        double secs = (double)time / (1000L * 1000 * 1000);
+        long rate = total * (1000L) / time;
+        System.out.printf("threads:%3d  Time: %7.3fsec  Incs per microsec: %4d\n",
+                          nthreads, secs, rate);
+    }
+
+    static long timeTasks(Phaser phaser) {
+        phaser.arriveAndAwaitAdvance();
+        long start = System.nanoTime();
+        phaser.arriveAndAwaitAdvance();
+        phaser.arriveAndAwaitAdvance();
+        return System.nanoTime() - start;
+    }
+
+    static final class AdderTask implements Runnable {
+        final DoubleAdder adder;
+        final Phaser phaser;
+        final int incs;
+        volatile double result;
+        AdderTask(DoubleAdder adder, Phaser phaser, int incs) {
+            this.adder = adder;
+            this.phaser = phaser;
+            this.incs = incs;
+        }
+
+        public void run() {
+            phaser.arriveAndAwaitAdvance();
+            phaser.arriveAndAwaitAdvance();
+            DoubleAdder a = adder;
+            for (int i = 0; i < incs; ++i)
+                a.add(1.0);
+            result = a.sum();
+            phaser.arrive();
+        }
+    }
+
+    static final class SyncTask implements Runnable {
+        final SynchronizedDoubleAdder adder;
+        final Phaser phaser;
+        final int incs;
+        volatile double result;
+        SyncTask(SynchronizedDoubleAdder adder, Phaser phaser, int incs) {
+            this.adder = adder;
+            this.phaser = phaser;
+            this.incs = incs;
+        }
+
+        public void run() {
+            phaser.arriveAndAwaitAdvance();
+            phaser.arriveAndAwaitAdvance();
+            SynchronizedDoubleAdder a = adder;
+            for (int i = 0; i < incs; ++i)
+                a.add(1.0);
+            result = a.sum();
+            phaser.arrive();
+        }
+    }
+
+}