Hi,
I'm trying to get my hands dirty at Java micro-benchmarking. Hence, I wrote a small benchmark comparing the performance of LongAdder from Java 8 to a plain AtomicLong.
I wanted to show that LongAdder is good for write heavy workload, but is falling short if you mostly read the counter.
I'm not versed with micro-benchmarking techniques, so I probably made some embarrassing measurement errors. My main technique is pretty primitive - run the benchmark 100 times, and take the minimal results. I verified that the JIT have jumped into action by using -XX:+PrintCompilation. I measured duration with System.getNanos(). Of course, benchmark themselves ran without JIT logging, and with -server.
I tried to avoid too much work in the hot loop, by using a small amount of randomization per the benchmark, hoping the total amount of irrelevant work would not be too high, and yet, hoping the input would still be enough random to get meaningful results.
Also, I took a look at
Caliper's FAQ, it looks like running multiple times and picking the minimum will solve the problems mentioned there.
The end results are as expected:
for 1% writes=16,000 (16 threads * 100,000 ops each=1,600,000):
LongAdder 1.518ms
AtomicLong 0.319ms
AtomicLong faster than LongAdder by 78.99%
for 90% writes=1,440,000 (16 threads * 100,000 ops each=1,600,000):
LongAdder 3.258ms
AtomicLong 28.892ms
LongAdder faster than AtomicLong by 786.80%
Here's the code, I'll be happy to understand any faults, or anything I could do better.
Thanks,