1+ package org .dataloader .performance ;
2+
3+ import java .time .Duration ;
4+ import java .util .ArrayList ;
5+ import java .util .List ;
6+ import java .util .concurrent .ExecutionException ;
7+ import java .util .concurrent .ExecutorService ;
8+ import java .util .concurrent .Executors ;
9+ import java .util .concurrent .Future ;
10+ import java .util .concurrent .atomic .AtomicLong ;
11+ import java .util .concurrent .atomic .LongAdder ;
12+
13+ public class AtomicVsAdder {
14+
15+ private static final ExecutorService EXECUTOR = Executors .newCachedThreadPool ();
16+
17+ public static void main (final String [] args ) throws Exception {
18+ // knobs
19+ final var iterationsList = List .of (1 << 20L , 1 << 24L );
20+ final var numberOfThreadsList = List .of (1 , 2 , 4 , 8 , 16 );
21+ final var strategies = List .of (new LongAdderStrategy (), new AtomicLongStrategy ());
22+
23+ // test
24+ System .out .println ("testing with #cpu=" + Runtime .getRuntime ().availableProcessors ());
25+ for (int iterations : iterationsList ) {
26+ for (int numberOfThreads : numberOfThreadsList ) {
27+ for (Strategy strategy : strategies ) {
28+ performTest (iterations , numberOfThreads , strategy );
29+ }
30+ }
31+ }
32+
33+ EXECUTOR .shutdownNow ();
34+
35+ }
36+
37+ private static void performTest (final long iterations , final int numberOfThreads , Strategy strategy ) throws Exception {
38+ final List <Future <?>> futures = new ArrayList <>();
39+ System .out .println ("start test with " + iterations + " iterations using " + numberOfThreads + " threads and strategy " + strategy .getClass ().getSimpleName ());
40+ final long start = System .nanoTime ();
41+
42+ for (int i = 0 ; i < numberOfThreads ; i ++) {
43+ Future <?> submit = EXECUTOR .submit (() -> concurrentWork (strategy , iterations ));
44+ futures .add (submit );
45+ }
46+ for (final Future <?> future : futures ) {
47+ future .get (); // wait for all
48+ }
49+ final long end = System .nanoTime ();
50+ System .out .println ("done in " + Duration .ofNanos (end - start ).toMillis () + "ms => result " + strategy .get ());
51+ System .out .println ("----" );
52+ strategy .reset ();
53+ }
54+
55+ @ SuppressWarnings ("SameParameterValue" )
56+ private static void concurrentWork (final Strategy strategy , final long iterations ) {
57+ long work = iterations ;
58+ while (work -- > 0 ) {
59+ strategy .increment ();
60+ }
61+ }
62+
63+ interface Strategy {
64+ void increment ();
65+
66+ long get ();
67+
68+ void reset ();
69+ }
70+
71+ static class LongAdderStrategy implements Strategy {
72+
73+ private LongAdder longAdder = new LongAdder ();
74+
75+ @ Override
76+ public void increment () {
77+ longAdder .increment ();
78+ }
79+
80+ @ Override
81+ public long get () {
82+ return longAdder .sum ();
83+ }
84+
85+ @ Override
86+ public void reset () {
87+ longAdder = new LongAdder ();
88+ }
89+ }
90+
91+ static class AtomicLongStrategy implements Strategy {
92+
93+ private final AtomicLong atomicLong = new AtomicLong (0 );
94+
95+ @ Override
96+ public void increment () {
97+ atomicLong .incrementAndGet ();
98+ }
99+
100+ @ Override
101+ public long get () {
102+ return atomicLong .get ();
103+ }
104+
105+ @ Override
106+ public void reset () {
107+ atomicLong .set (0 );
108+ }
109+ }
110+
111+ }
0 commit comments