Skip to content

Instantly share code, notes, and snippets.

@lotabout
Last active August 20, 2018 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lotabout/7224af60e26d912ab04722e2ddb9b20f to your computer and use it in GitHub Desktop.
Save lotabout/7224af60e26d912ab04722e2ddb9b20f to your computer and use it in GitHub Desktop.
Test the performance of different concurrency mechanism.
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAdder;
public class ConcurrencyTest {
private enum TestType {
LONG_ADDER,
INC_AND_GET,
GET_AND_ADD,
CAS,
SYNC,
}
public static class LongAdderThread extends Thread {
private static LongAdder longAdder = new LongAdder();
public void run() {
int i = 1;
while(i <= LOOP_COUNT) {
longAdder.increment();
i++;
}
}
}
public static class IncrementAndGetThread extends Thread {
private static AtomicInteger atomicInteger = new AtomicInteger(0);
public void run() {
int i = 1;
while(i <= LOOP_COUNT) {
atomicInteger.incrementAndGet();
i++;
}
}
}
public static class GetAndAddThread extends Thread {
private static volatile int cas = 0;
private static long casOffset;
private static Unsafe UNSAFE;
static {
try {
@SuppressWarnings("ALL")
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
casOffset = UNSAFE.staticFieldOffset(GetAndAddThread.class.getDeclaredField("cas"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void atomicInteger() {
UNSAFE.getAndAddInt(this, casOffset, 1);
}
public void run() {
int i = 1;
while(i <= LOOP_COUNT) {
atomicInteger();
i++;
}
}
}
public static class CASThread extends Thread {
private static volatile int cas = 0;
private static long casOffset;
private static Unsafe UNSAFE;
static {
try {
@SuppressWarnings("ALL")
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
casOffset = UNSAFE.staticFieldOffset(CASThread.class.getDeclaredField("cas"));
} catch (Exception e) {
e.printStackTrace();
}
}
public void cas() {
boolean bl = false;
int tmp;
while (!bl) {
tmp = cas;
bl = UNSAFE.compareAndSwapInt(CASThread.class, casOffset, tmp, tmp + 1);
}
}
public void run() {
int i = 1;
while(i <= LOOP_COUNT) {
cas();
i++;
}
}
}
public static class SynchronizedThread extends Thread {
private static int $synchronized = 0;
public void run() {
int i = 1;
while(i <= LOOP_COUNT) {
synchronized (SynchronizedThread.class) {
$synchronized ++;
}
i++;
}
}
}
public static long test(int threadCount, TestType type) {
List<Thread> threads = new ArrayList<>();
for (int i = 1; i <= threadCount; i++) {
Thread thread = null;
switch (type) {
case LONG_ADDER:
thread = new LongAdderThread();
break;
case INC_AND_GET:
thread = new IncrementAndGetThread();
break;
case GET_AND_ADD:
thread = new GetAndAddThread();
break;
case CAS:
thread = new CASThread();
break;
case SYNC:
thread = new SynchronizedThread();
break;
}
threads.add(thread);
}
long start = System.currentTimeMillis();
for (Thread thread: threads) {
thread.start();
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return System.currentTimeMillis() - start;
}
private static int LOOP_COUNT = 10_000_000;
public static void main(String[] args) {
for (int thread_count=1; thread_count < 50; thread_count++) {
for (int thousands = 1; thousands<= 1000; thousands += 1) {
LOOP_COUNT = 1000 * thousands;
System.out.println("" + thread_count + ","
+ thousands + ","
+ test(thread_count, TestType.CAS) + ","
+ test(thread_count, TestType.SYNC));
}
}
// int THREAD_COUNT = 50;
// System.out.println("" + test(THREAD_COUNT, TestType.LONG_ADDER) + "\t"
// + test(THREAD_COUNT, TestType.INC_AND_GET) + "\t"
// + test(THREAD_COUNT, TestType.GET_AND_ADD) + "\t"
// + test(THREAD_COUNT, TestType.CAS) + "\t"
// + test(THREAD_COUNT, TestType.SYNC));
}
}
@lotabout
Copy link
Author

This is the test result that runs on [2,5,10,50,100] threads and [10, 100, 1000, 10,000] k loop counts.
https://docs.google.com/spreadsheets/d/1erii-UBG6-OEdRB2L2Of16q4BQGlSTv5GdGH1H3bY7I/edit?usp=sharing

@lotabout
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment