--- /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();
+ }
+ }
+
+}