java


how to test the performance of compareAndSet between synchronized


I wnat to use CAS to improve my code ,but i doubt it can get better performance,so i do a test. here is the test code,this jmh code is reliable?
#OutputTimeUnit(TimeUnit.MILLISECONDS)
#BenchmarkMode(Mode.SampleTime)
#Warmup(iterations = 5)
#Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS)
#Threads(20)
#Fork(1)
#State(Scope.Benchmark)
public class CASBench {
private int id=24;
private static Object[] lockObj;
private static AtomicReference<Integer>[] locks;
static {
lockObj = new Object[100];
for (int i = 0; i < lockObj.length; i++) {
lockObj[i] = new Object();
}
locks = new AtomicReference[100];
for (int i = 0; i < locks.length; i++) {
locks[i] = new AtomicReference<Integer>(null);
}
}
#Benchmark
public void sync() throws Exception {
int index = id % 100;
synchronized (lockObj[index]) {
test();
}
}
#Benchmark
public void cas() throws Exception {
AtomicReference<Integer> lock = locks[id % 100];
while (!lock.compareAndSet(null, id)) {
}
test();
lock.compareAndSet(id, null);
}
public void test() throws Exception {
int sum=0;
for(int i=0;i<100;i++){
sum += i;
}
}
}
and i get jmh test result:
Benchmark Mode Cnt Score Error Units
CASBench.cas sample 25866638 0.014 ± 0.001 ms/op
CASBench.cas:cas·p0.00 sample ≈ 10⁻⁶ ms/op
CASBench.cas:cas·p0.50 sample ≈ 10⁻⁴ ms/op
CASBench.cas:cas·p0.90 sample 0.001 ms/op
CASBench.cas:cas·p0.95 sample 0.001 ms/op
CASBench.cas:cas·p0.99 sample 0.001 ms/op
CASBench.cas:cas·p0.999 sample 0.002 ms/op
CASBench.cas:cas·p0.9999 sample 38.164 ms/op
CASBench.cas:cas·p1.00 sample 813.695 ms/op
CASBench.sync sample 26257757 0.011 ± 0.001 ms/op
CASBench.sync:sync·p0.00 sample ≈ 10⁻⁶ ms/op
CASBench.sync:sync·p0.50 sample ≈ 10⁻⁴ ms/op
CASBench.sync:sync·p0.90 sample 0.001 ms/op
CASBench.sync:sync·p0.95 sample 0.001 ms/op
CASBench.sync:sync·p0.99 sample 0.005 ms/op
CASBench.sync:sync·p0.999 sample 1.883 ms/op
CASBench.sync:sync·p0.9999 sample 15.270 ms/op
CASBench.sync:sync·p1.00 sample 45.810 ms/op
can I get this conclusion,in this case synchronized is better?
Well your test are incorrect indeed as far as I can tell. First your benchmarks should return a value, as specified in the samples here or use BlackHoles.
Than there are two ways to test this, first when there is contention and there isn't.
Let's see what happens under contention, it's simpler to grasp:
#OutputTimeUnit(TimeUnit.NANOSECONDS)
#BenchmarkMode(Mode.AverageTime)
#Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
#Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
#State(Scope.Benchmark)
public class Contention {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.jvmArgs("-ea")
.shouldFailOnError(true)
.include(Contention.class.getSimpleName()).build();
new Runner(opt).run();
}
private AtomicInteger atomic;
private Object lock = new Object();
private int i = 0;
#Setup
public void setUp() {
atomic = new AtomicInteger(0);
}
#Fork(1)
#Threads(10)
#Benchmark
public int incrementAtomic() {
return atomic.incrementAndGet();
}
#Fork(1)
#Threads(10)
#Benchmark
public int incrementSync() {
synchronized (lock) {
++i;
}
return i;
}
}
The code should be pretty much self-explanatory; with a slight explanation here :
State(Scope.Benchmark)
If you change that to : State(Scope.Thread) each thread will get it's own lock and as such this code would be skewed by biased-locking.
What that means that if you would run this code with :
State(Scope.Thread)
Your output would be very much the same. Something like this:
Benchmark Mode Cnt Score Error Units
casVSsynchronized.Contention.incrementAtomic avgt 5 36.526 ± 6.548 ns/op
casVSsynchronized.Contention.incrementSync avgt 5 23.655 ± 3.393 ns/op
Running it with:
#State(Scope.Benchmark)
Shows an entire different picture. Under contention CAS performs way better as you can see from results:
Benchmark Mode Cnt Score Error Units
casVSsynchronized.Contention.incrementAtomic avgt 5 212.997 ± 42.902 ns/op
casVSsynchronized.Contention.incrementSync avgt 5 457.896 ± 46.811 ns/op
Than I have a bit of a more complicated test (which might need more restrictive reviews from jmh devs probably):
import java.util.concurrent.TimeUnit;
#OutputTimeUnit(TimeUnit.NANOSECONDS)
#BenchmarkMode(Mode.AverageTime)
#Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
#Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS)
public class CASSync {
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.jvmArgs("-ea")
.shouldFailOnError(true)
.include(CASSync.class.getSimpleName()).build();
new Runner(opt).run();
}
#State(Scope.Thread)
static public class AtomicHolder {
AtomicInteger i = null;
#Setup(Level.Invocation)
public void setUp() {
i = new AtomicInteger(0);
}
#TearDown(Level.Invocation)
public void tearDown() {
assert i.intValue() == 1;
i = null;
}
}
#State(Scope.Thread)
static public class SyncHolder {
int i = 0;
Object lock = null;
#Setup(Level.Invocation)
public void setUp() {
lock = new Object();
i = 0;
}
#TearDown(Level.Invocation)
public void tearDown() {
assert i == 1;
lock = null;
}
}
#Benchmark
#Fork(1)
public boolean cas(AtomicHolder holder) {
return holder.i.compareAndSet(0, 1);
}
#Benchmark
#Fork(1)
public boolean sync(SyncHolder holder) {
synchronized (holder.lock) {
++holder.i;
}
return holder.i == 1;
}
}
This one tests the case when there is no contention at all (just like the first one), but this time getting rid of biased-locking. And the results:
Benchmark Mode Cnt Score Error Units
casVSsynchronized.CASSync.cas avgt 5 44.003 ± 1.343 ns/op
casVSsynchronized.CASSync.sync avgt 5 50.744 ± 1.370 ns/o
My conclusion: for contended environments, CAS is way better. For the rest it's debatable.

Related Links

Android JSON Parsing - End of input at character 0 of error
Using generics for a class how can I convert the values from one type to another?
JtextArea Not Updating Itself
Executing multiple shell scripts on multiple remote servers at the same time using a java program
Fail testNG #Test before assertion is evaluated
Spring Data JPA: Cannot save entity with composite primary key which contains foreign key
Android ListView can't scroll more, bad custom Adapter?
Multiple clauses in MERGE for Oracle SQL: UPSERT AND DELETE in a single statement
EasyMock test an exception is thrown in the middle of code
Twitter4j vs Twitter hbc
Why is it recommended to use setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)?
Cannot be cast to com.android.tools.idea.gradle.invoker.GradleInvoker
xtext, content assist unwanted suggestions
Alternative for AuthenticationException.getAuthentication();
Java annotation capturing with reflection will not work when execuete jacoco prepare agent
java.sql.SQLException: Output parameters have not yet been processed. Call getMoreResults()

Categories

HOME
atom-editor
amazon-ec2
deezer
fluentd
comparison
smarty
appx
fft
cplex
leon
infragistics
rdf
installshield
in-app-purchase
contact
facebook-messenger-bot
contextmenu
emulator
plunker
java-3d
cloudhub
css-animations
accessor
wkwebview
chromium-embedded
numerical-methods
applozic
elasticsearch-net
saas
preg-match
ecto
exuberant-ctags
siesta-swift
winrt-xaml-toolkit
wallpaper
mmenu
file-format
vxworks
git-merge
restlet
preconditions
optix
android-tabhost
no-www
reactive-cocoa-5
eclipse-gef
hls.js
powercli
rdfs
lift-json
python-cryptography
gridpane
savon
bonobo
fputcsv
lua-5.1
moveit
ios4
independentsoft
cloudbees
energy
lib.web.mvc
marching-cubes
ibaction
method-parameters
mono-embedding
createprocessasuser
oberon
mdt
socketexception
issuu
rdl
eol
starcluster
valuechangelistener
didselectrowatindexpath
quartz-graphics
clipper
isnullorempty
automount
code-cleanup
infobox
android-sdk-2.1
sudzc
zend-translate
web-architecture
mdac
paul-graham

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App