ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/CASLoops.java
(Generate patch)

Comparing jsr166/src/test/loops/CASLoops.java (file contents):
Revision 1.1 by dl, Fri Jun 10 15:45:19 2005 UTC vs.
Revision 1.5 by jsr166, Tue Nov 3 01:04:02 2009 UTC

# Line 11 | Line 11
11   * just compare and conditionally store (int) values, so are
12   * not intended to measure the "raw" cost of a CAS.
13   *
14 < * Outputs, for runs using 1 ... #cpus threads are, in nanoseconds:
14 > * Outputs, in nanoseconds:
15   *  "Atomic CAS"      AtomicInteger.compareAndSet
16 + *  "Updater CAS"     CAS first comparing args
17   *  "Volatile"        pseudo-CAS using volatile store if comparison succeeds
18   *  "Mutex"           emulated compare and set done under AQS-based mutex lock
19   *  "Synchronized"    emulated compare and set done under a synchronized block.
20   *
21 < * The last two are done only if this program is called with (any) argument
21 > * By default, these are printed for 1..#cpus threads, but you can
22 > * change the upper bound number of threads by providing the
23 > * first argument to this program.
24 > *
25 > * The last two kinds of runs (mutex and synchronized) are done only
26 > * if this program is called with (any) second argument
27   */
28  
29  
30   import java.util.concurrent.atomic.AtomicInteger;
31   import java.util.concurrent.atomic.AtomicLong;
32 + import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
33   import java.util.concurrent.*;
34   import java.util.concurrent.locks.*;
35  
# Line 31 | Line 38 | public class CASLoops {
38      static final int TRIALS = 2;
39      static final long BASE_SECS_PER_RUN = 4;
40      static final int NCPUS = Runtime.getRuntime().availableProcessors();
41 +    static int maxThreads = NCPUS;
42  
43      static boolean includeLocks = false;
44  
45      public static void main(String[] args) throws Exception {
46          if (args.length > 0)
47 +            maxThreads = Integer.parseInt(args[0]);
48 +
49 +        loopIters = new long[maxThreads+1];
50 +
51 +        if (args.length > 1)
52              includeLocks = true;
53  
54          System.out.println("Warmup...");
55 +        for (int i = maxThreads; i > 0; --i) {
56 +            runCalibration(i, 10);
57 +            oneRun(i, loopIters[i] / 4, false);
58 +            System.out.print(".");
59 +        }
60 +
61 +        for (int i = 1; i <= maxThreads; ++i)
62 +            loopIters[i] = 0;
63 +
64          for (int j = 0; j < 2; ++j) {
65 <            for (int i = 1; i <= NCPUS; ++i) {
65 >            for (int i = 1; i <= maxThreads; ++i) {
66                  runCalibration(i, 1000);
67                  oneRun(i, loopIters[i] / 8, false);
68 +                System.out.print(".");
69              }
70          }
71  
72 <        for (int i = 1; i <= NCPUS; ++i)
72 >        for (int i = 1; i <= maxThreads; ++i)
73              loopIters[i] = 0;
74  
75          for (int j = 0; j < TRIALS; ++j) {
76              System.out.println("Trial " + j);
77 <            for (int i = 1; i <= NCPUS; ++i) {
77 >            for (int i = 1; i <= maxThreads; ++i) {
78                  runCalibration(i, BASE_SECS_PER_RUN * 1000L);
79                  oneRun(i, loopIters[i], true);
80              }
# Line 64 | Line 87 | public class CASLoops {
87  
88      static final LoopHelpers.MarsagliaRandom rng = new LoopHelpers.MarsagliaRandom();
89  
90 <    static final long[] loopIters = new long[NCPUS+1];
90 >    static long[] loopIters;
91  
92      static final class NonAtomicInteger {
93          volatile int readBarrier;
# Line 85 | Line 108 | public class CASLoops {
108          void set(int val) { value = val; }
109      }
110  
111 +    static final class UpdaterAtomicInteger {
112 +        volatile int value;
113 +
114 +        static final AtomicIntegerFieldUpdater<UpdaterAtomicInteger>
115 +                valueUpdater = AtomicIntegerFieldUpdater.newUpdater
116 +                (UpdaterAtomicInteger.class, "value");
117 +
118 +
119 +        UpdaterAtomicInteger() {}
120 +        int get() {
121 +            return value;
122 +        }
123 +        boolean compareAndSet(int cmp, int val) {
124 +            return valueUpdater.compareAndSet(this, cmp, val);
125 +        }
126 +
127 +        void set(int val) { value = val; }
128 +    }
129 +
130      static final class VolatileInteger {
131          volatile int value;
132  
# Line 149 | Line 191 | public class CASLoops {
191                  unlock();
192              }
193          }
194 <        void set(int val) {
195 <            lock();
194 >        void set(int val) {
195 >            lock();
196              try {
197 <                value = val;
197 >                value = val;
198              } finally {
199                  unlock();
200              }
201          }
202      }
203  
204 <    // All these versions are copy-paste-hacked to avoid
204 >    // All these versions are copy-paste-hacked to avoid
205      // contamination with virtual call resolution etc.
206  
207      // Use fixed-length unrollable inner loops to reduce safepoint checks
# Line 178 | Line 220 | public class CASLoops {
220  
221          public void run() {
222              try {
223 <                barrier.await();
223 >                barrier.await();
224                  long i = iters;
225                  int y = 0;
226                  int succ = 0;
# Line 196 | Line 238 | public class CASLoops {
238                  successes.getAndAdd(succ);
239                  barrier.await();
240              }
241 <            catch (Exception ie) {
242 <                return;
241 >            catch (Exception ie) {
242 >                return;
243              }
244          }
245      }
# Line 215 | Line 257 | public class CASLoops {
257  
258          public void run() {
259              try {
260 <                barrier.await();
260 >                barrier.await();
261                  long i = iters;
262                  int y = 0;
263                  int succ = 0;
# Line 233 | Line 275 | public class CASLoops {
275                  successes.getAndAdd(succ);
276                  barrier.await();
277              }
278 <            catch (Exception ie) {
279 <                return;
278 >            catch (Exception ie) {
279 >                return;
280 >            }
281 >        }
282 >    }
283 >
284 >    static final class UpdaterAtomicLoop implements Runnable {
285 >        final long iters;
286 >        final UpdaterAtomicInteger obj;
287 >        final CyclicBarrier barrier;
288 >        UpdaterAtomicLoop(long iters, UpdaterAtomicInteger obj, CyclicBarrier b) {
289 >            this.iters = iters;
290 >            this.obj = obj;
291 >            this.barrier = b;
292 >            obj.set(rng.next());
293 >        }
294 >
295 >        public void run() {
296 >            try {
297 >                barrier.await();
298 >                long i = iters;
299 >                int y = 0;
300 >                int succ = 0;
301 >                while (i > 0) {
302 >                    for (int k = 0; k < innerPerOuter; ++k) {
303 >                        int x = obj.get();
304 >                        int z = y + LoopHelpers.compute6(x);
305 >                        if (obj.compareAndSet(x, z))
306 >                            ++succ;
307 >                        y = LoopHelpers.compute7(z);
308 >                    }
309 >                    i -= innerPerOuter;
310 >                }
311 >                sum.getAndAdd(obj.get());
312 >                successes.getAndAdd(succ);
313 >                barrier.await();
314 >            }
315 >            catch (Exception ie) {
316 >                return;
317              }
318          }
319      }
# Line 252 | Line 331 | public class CASLoops {
331  
332          public void run() {
333              try {
334 <                barrier.await();
334 >                barrier.await();
335                  long i = iters;
336                  int y = 0;
337                  int succ = 0;
# Line 270 | Line 349 | public class CASLoops {
349                  successes.getAndAdd(succ);
350                  barrier.await();
351              }
352 <            catch (Exception ie) {
353 <                return;
352 >            catch (Exception ie) {
353 >                return;
354              }
355          }
356      }
# Line 289 | Line 368 | public class CASLoops {
368  
369          public void run() {
370              try {
371 <                barrier.await();
371 >                barrier.await();
372                  long i = iters;
373                  int y = 0;
374                  int succ = 0;
# Line 307 | Line 386 | public class CASLoops {
386                  successes.getAndAdd(succ);
387                  barrier.await();
388              }
389 <            catch (Exception ie) {
390 <                return;
389 >            catch (Exception ie) {
390 >                return;
391              }
392          }
393      }
# Line 326 | Line 405 | public class CASLoops {
405  
406          public void run() {
407              try {
408 <                barrier.await();
408 >                barrier.await();
409                  long i = iters;
410                  int y = 0;
411                  int succ = 0;
# Line 344 | Line 423 | public class CASLoops {
423                  successes.getAndAdd(succ);
424                  barrier.await();
425              }
426 <            catch (Exception ie) {
427 <                return;
426 >            catch (Exception ie) {
427 >                return;
428              }
429          }
430      }
# Line 365 | Line 444 | public class CASLoops {
444  
445          public void run() {
446              try {
447 <                barrier.await();
447 >                barrier.await();
448                  long iters = 0;
449                  int y = 0;
450                  int succ = 0;
# Line 388 | Line 467 | public class CASLoops {
467                  successes.getAndAdd(succ);
468                  barrier.await();
469              }
470 <            catch (Exception ie) {
471 <                return;
470 >            catch (Exception ie) {
471 >                return;
472              }
473          }
474      }
# Line 400 | Line 479 | public class CASLoops {
479          CyclicBarrier b = new CyclicBarrier(n+1);
480          totalIters.set(0);
481          NonAtomicInteger a = new NonAtomicInteger();
482 <        for (int j = 0; j < n; ++j)
482 >        for (int j = 0; j < n; ++j)
483              new Thread(new NACalibrationLoop(endTime, a, b)).start();
484          b.await();
485          b.await();
# Line 414 | Line 493 | public class CASLoops {
493          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
494          CyclicBarrier b = new CyclicBarrier(n+1, timer);
495          NonAtomicInteger a = new NonAtomicInteger();
496 <        for (int j = 0; j < n; ++j)
496 >        for (int j = 0; j < n; ++j)
497              new Thread(new NonAtomicLoop(iters, a, b)).start();
498          b.await();
499          b.await();
# Line 422 | Line 501 | public class CASLoops {
501          return timer.getTime();
502      }
503  
504 +    static long runUpdaterAtomic(int n, long iters) throws Exception {
505 +        LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
506 +        CyclicBarrier b = new CyclicBarrier(n+1, timer);
507 +        UpdaterAtomicInteger a = new UpdaterAtomicInteger();
508 +        for (int j = 0; j < n; ++j)
509 +            new Thread(new UpdaterAtomicLoop(iters, a, b)).start();
510 +        b.await();
511 +        b.await();
512 +        if (sum.get() == 0) System.out.print(" ");
513 +        return timer.getTime();
514 +    }
515 +
516      static long runAtomic(int n, long iters) throws Exception {
517          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
518          CyclicBarrier b = new CyclicBarrier(n+1, timer);
519          AtomicInteger a = new AtomicInteger();
520 <        for (int j = 0; j < n; ++j)
520 >        for (int j = 0; j < n; ++j)
521              new Thread(new AtomicLoop(iters, a, b)).start();
522          b.await();
523          b.await();
# Line 438 | Line 529 | public class CASLoops {
529          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
530          CyclicBarrier b = new CyclicBarrier(n+1, timer);
531          VolatileInteger a = new VolatileInteger();
532 <        for (int j = 0; j < n; ++j)
532 >        for (int j = 0; j < n; ++j)
533              new Thread(new VolatileLoop(iters, a, b)).start();
534          b.await();
535          b.await();
# Line 451 | Line 542 | public class CASLoops {
542          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
543          CyclicBarrier b = new CyclicBarrier(n+1, timer);
544          SynchedInteger a = new SynchedInteger();
545 <        for (int j = 0; j < n; ++j)
545 >        for (int j = 0; j < n; ++j)
546              new Thread(new SynchedLoop(iters, a, b)).start();
547          b.await();
548          b.await();
# Line 463 | Line 554 | public class CASLoops {
554          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
555          CyclicBarrier b = new CyclicBarrier(n+1, timer);
556          LockedInteger a = new LockedInteger();
557 <        for (int j = 0; j < n; ++j)
557 >        for (int j = 0; j < n; ++j)
558              new Thread(new LockedLoop(iters, a, b)).start();
559          b.await();
560          b.await();
# Line 471 | Line 562 | public class CASLoops {
562          return timer.getTime();
563      }
564  
565 <    static void report(String tag, long runtime, long basetime, long iters) {
565 >    static void report(String tag, long runtime, long basetime,
566 >                       int nthreads, long iters) {
567          System.out.print(tag);
568 <        System.out.print(LoopHelpers.rightJustify((runtime - basetime) / iters) + " ns");
569 <        double secs = (double)(runtime) / 1000000000.0;
568 >        long t = (runtime - basetime) / iters;
569 >        if (nthreads > NCPUS)
570 >            t = t * NCPUS / nthreads;
571 >        System.out.print(LoopHelpers.rightJustify(t));
572 >        double secs = (double) runtime / 1000000000.0;
573          System.out.println("\t " + secs + "s run time");
574      }
575 <        
575 >
576  
577      static void oneRun(int i, long iters, boolean print) throws Exception {
578 <        System.out.println("threads : " + i +
579 <                           " base iters per thread per run : " +
580 <                           LoopHelpers.rightJustify(loopIters[i]));
578 >        if (print)
579 >            System.out.println("threads : " + i +
580 >                               " base iters per thread per run : " +
581 >                               LoopHelpers.rightJustify(loopIters[i]));
582          long ntime = runNonAtomic(i,  iters);
583          if (print)
584 <            report("Base        : ", ntime, ntime, iters);
584 >            report("Base        : ", ntime, ntime, i, iters);
585          Thread.sleep(100L);
586          long atime = runAtomic(i, iters);
587          if (print)
588 <            report("Atomic CAS  : ", atime, ntime, iters);
588 >            report("Atomic CAS  : ", atime, ntime, i, iters);
589 >        Thread.sleep(100L);
590 >        long gtime = runUpdaterAtomic(i, iters);
591 >        if (print)
592 >            report("Updater CAS : ", gtime, ntime, i, iters);
593          Thread.sleep(100L);
594          long vtime = runVolatile(i, iters);
595          if (print)
596 <            report("Volatile    : ", vtime, ntime, iters);
596 >            report("Volatile    : ", vtime, ntime, i, iters);
597  
598          Thread.sleep(100L);
599          if (!includeLocks) return;
600          long mtime = runLocked(i, iters);
601          if (print)
602 <            report("Mutex       : ", mtime, ntime, iters);
602 >            report("Mutex       : ", mtime, ntime, i, iters);
603          Thread.sleep(100L);
604          long stime = runSynched(i, iters);
605 <        if (print)
606 <            report("Synchronized: ", stime, ntime, iters);
605 >        if (print)
606 >            report("Synchronized: ", stime, ntime, i, iters);
607          Thread.sleep(100L);
608      }
609  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines