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.2 by dl, Sun Aug 7 19:25:55 2005 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)
46 >        if (args.length > 0)
47 >            maxThreads = Integer.parseInt(args[0]);
48 >
49 >        if (args.length > 1)
50              includeLocks = true;
51  
52          System.out.println("Warmup...");
53 +        for (int i = maxThreads; i > 0; --i) {
54 +            runCalibration(i, 10);
55 +            oneRun(i, loopIters[i] / 4, false);
56 +            System.out.print(".");
57 +        }
58 +
59 +        for (int i = 1; i <= maxThreads; ++i)
60 +            loopIters[i] = 0;
61 +
62          for (int j = 0; j < 2; ++j) {
63 <            for (int i = 1; i <= NCPUS; ++i) {
63 >            for (int i = 1; i <= maxThreads; ++i) {
64                  runCalibration(i, 1000);
65                  oneRun(i, loopIters[i] / 8, false);
66 +                System.out.print(".");
67              }
68          }
69  
70 <        for (int i = 1; i <= NCPUS; ++i)
70 >        for (int i = 1; i <= maxThreads; ++i)
71              loopIters[i] = 0;
72  
73          for (int j = 0; j < TRIALS; ++j) {
74              System.out.println("Trial " + j);
75 <            for (int i = 1; i <= NCPUS; ++i) {
75 >            for (int i = 1; i <= maxThreads; ++i) {
76                  runCalibration(i, BASE_SECS_PER_RUN * 1000L);
77                  oneRun(i, loopIters[i], true);
78              }
# Line 64 | Line 85 | public class CASLoops {
85  
86      static final LoopHelpers.MarsagliaRandom rng = new LoopHelpers.MarsagliaRandom();
87  
88 <    static final long[] loopIters = new long[NCPUS+1];
88 >    static final long[] loopIters = new long[maxThreads+1];
89  
90      static final class NonAtomicInteger {
91          volatile int readBarrier;
# Line 85 | Line 106 | public class CASLoops {
106          void set(int val) { value = val; }
107      }
108  
109 +    static final class UpdaterAtomicInteger {
110 +        volatile int value;
111 +
112 +        static final AtomicIntegerFieldUpdater<UpdaterAtomicInteger>
113 +                valueUpdater = AtomicIntegerFieldUpdater.newUpdater
114 +                (UpdaterAtomicInteger.class, "value");
115 +
116 +
117 +        UpdaterAtomicInteger() {}
118 +        int get() {
119 +            return value;
120 +        }
121 +        boolean compareAndSet(int cmp, int val) {
122 +            return valueUpdater.compareAndSet(this, cmp, val);
123 +        }
124 +
125 +        void set(int val) { value = val; }
126 +    }
127 +
128      static final class VolatileInteger {
129          volatile int value;
130  
# Line 239 | Line 279 | public class CASLoops {
279          }
280      }
281  
282 +    static final class UpdaterAtomicLoop implements Runnable {
283 +        final long iters;
284 +        final UpdaterAtomicInteger obj;
285 +        final CyclicBarrier barrier;
286 +        UpdaterAtomicLoop(long iters, UpdaterAtomicInteger obj, CyclicBarrier b) {
287 +            this.iters = iters;
288 +            this.obj = obj;
289 +            this.barrier = b;
290 +            obj.set(rng.next());
291 +        }
292 +
293 +        public void run() {
294 +            try {
295 +                barrier.await();
296 +                long i = iters;
297 +                int y = 0;
298 +                int succ = 0;
299 +                while (i > 0) {
300 +                    for (int k = 0; k < innerPerOuter; ++k) {
301 +                        int x = obj.get();
302 +                        int z = y + LoopHelpers.compute6(x);
303 +                        if (obj.compareAndSet(x, z))
304 +                            ++succ;
305 +                        y = LoopHelpers.compute7(z);
306 +                    }
307 +                    i -= innerPerOuter;
308 +                }
309 +                sum.getAndAdd(obj.get());
310 +                successes.getAndAdd(succ);
311 +                barrier.await();
312 +            }
313 +            catch (Exception ie) {
314 +                return;
315 +            }
316 +        }
317 +    }
318 +
319      static final class VolatileLoop implements Runnable {
320          final long iters;
321          final VolatileInteger obj;
# Line 422 | Line 499 | public class CASLoops {
499          return timer.getTime();
500      }
501  
502 +    static long runUpdaterAtomic(int n, long iters) throws Exception {
503 +        LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
504 +        CyclicBarrier b = new CyclicBarrier(n+1, timer);
505 +        UpdaterAtomicInteger a = new UpdaterAtomicInteger();
506 +        for (int j = 0; j < n; ++j)
507 +            new Thread(new UpdaterAtomicLoop(iters, a, b)).start();
508 +        b.await();
509 +        b.await();
510 +        if (sum.get() == 0) System.out.print(" ");
511 +        return timer.getTime();
512 +    }
513 +
514      static long runAtomic(int n, long iters) throws Exception {
515          LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
516          CyclicBarrier b = new CyclicBarrier(n+1, timer);
# Line 471 | Line 560 | public class CASLoops {
560          return timer.getTime();
561      }
562  
563 <    static void report(String tag, long runtime, long basetime, long iters) {
563 >    static void report(String tag, long runtime, long basetime,
564 >                       int nthreads, long iters) {
565          System.out.print(tag);
566 <        System.out.print(LoopHelpers.rightJustify((runtime - basetime) / iters) + " ns");
566 >        long t = (runtime - basetime) / iters;
567 >        if (nthreads > NCPUS)
568 >            t = t * NCPUS / nthreads;
569 >        System.out.print(LoopHelpers.rightJustify(t));
570          double secs = (double)(runtime) / 1000000000.0;
571          System.out.println("\t " + secs + "s run time");
572      }
573          
574  
575      static void oneRun(int i, long iters, boolean print) throws Exception {
576 <        System.out.println("threads : " + i +
577 <                           " base iters per thread per run : " +
578 <                           LoopHelpers.rightJustify(loopIters[i]));
576 >        if (print)
577 >            System.out.println("threads : " + i +
578 >                               " base iters per thread per run : " +
579 >                               LoopHelpers.rightJustify(loopIters[i]));
580          long ntime = runNonAtomic(i,  iters);
581          if (print)
582 <            report("Base        : ", ntime, ntime, iters);
582 >            report("Base        : ", ntime, ntime, i, iters);
583          Thread.sleep(100L);
584          long atime = runAtomic(i, iters);
585          if (print)
586 <            report("Atomic CAS  : ", atime, ntime, iters);
586 >            report("Atomic CAS  : ", atime, ntime, i, iters);
587 >        Thread.sleep(100L);
588 >        long gtime = runUpdaterAtomic(i, iters);
589 >        if (print)
590 >            report("Updater CAS : ", gtime, ntime, i, iters);
591          Thread.sleep(100L);
592          long vtime = runVolatile(i, iters);
593          if (print)
594 <            report("Volatile    : ", vtime, ntime, iters);
594 >            report("Volatile    : ", vtime, ntime, i, iters);
595  
596          Thread.sleep(100L);
597          if (!includeLocks) return;
598          long mtime = runLocked(i, iters);
599          if (print)
600 <            report("Mutex       : ", mtime, ntime, iters);
600 >            report("Mutex       : ", mtime, ntime, i, iters);
601          Thread.sleep(100L);
602          long stime = runSynched(i, iters);
603          if (print)
604 <            report("Synchronized: ", stime, ntime, iters);
604 >            report("Synchronized: ", stime, ntime, i, iters);
605          Thread.sleep(100L);
606      }
607  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines