# Beginners guide-concurrency

## by Michael Barker on Feb 10, 2012

• 12,344 views

More...

### Statistics

Likes
15
100
0
Embed Views
10,311
Views on SlideShare
2,033
Total Views
12,344

## Beginners guide-concurrencyPresentation Transcript

• Trisha Gee & Michael Barker / LMAX The Disruptor - A Beginners Guide to Hardcore ConcurrencySunday, 13 November 11
• Why is Concurrency So Difficult ?Sunday, 13 November 11
• Program Order: Execution Order (maybe): int w = 10; int x = 20; int x = 20; int y = 30; int y = 30; int b = x * y; int z = 40; int w = 10; int a = w + z; int z = 40; int b = x * y; int a = w + z;Sunday, 13 November 11
• Sunday, 13 November 11
• Why Should We Care About the Details ?Sunday, 13 November 11
• static long foo = 0; private static void increment() { for (long l = 0; l < 500000000L; l++) { foo++; } }Sunday, 13 November 11
• public static long foo = 0; public static Lock lock = new Lock(); private static void increment() { for (long l = 0; l < 500000000L; l++){ lock.lock(); try { foo++; } finally { lock.unlock(); } } }Sunday, 13 November 11
• static AtomicLong foo = new AtomicLong(0); private static void increment() { for (long l = 0; l < 500000000L; l++) { foo.getAndIncrement(); } }Sunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 msSunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 ms • One Thread (volatile): 4 700 ms (15x)Sunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 ms • One Thread (volatile): 4 700 ms (15x) • One Thread (Atomic) : 5 700 ms (19x)Sunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 ms • One Thread (volatile): 4 700 ms (15x) • One Thread (Atomic) : 5 700 ms (19x) • One Thread (Lock) : 10 000 ms (33x)Sunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 ms • One Thread (volatile): 4 700 ms (15x) • One Thread (Atomic) : 5 700 ms (19x) • One Thread (Lock) : 10 000 ms (33x) • Two Threads (Atomic) : 30 000 ms (100x)Sunday, 13 November 11
• Cost of Contention Increment a counter 500 000 000 times. • One Thread : 300 ms • One Thread (volatile): 4 700 ms (15x) • One Thread (Atomic) : 5 700 ms (19x) • One Thread (Lock) : 10 000 ms (33x) • Two Threads (Atomic) : 30 000 ms (100x) • Two Threads (Lock) : 224 000 ms (746x) ^^^^^^^^ ~4 minutes!!!Sunday, 13 November 11
• Parallel v. Serial - String Split Guy Steele @ Strangle Loop: http://www.infoq.com/presentations/Thinking-Parallel- Programming Scala Implementation and Brute Force version in Java: https://github.com/mikeb01/folklore/ 15Sunday, 13 November 11
• Parallel (Scala) Serial (Java) 2000.0 1500.0 1000.0 500.0 0 String Split (ops/sec) higher is betterSunday, 13 November 11
• CPUs Are Getting Faster 17Sunday, 13 November 11
• Ya Rly! P8600 (Core 2 Duo) E5620 (Nehalem EP) i7 2667M (Sandy Bridge ULV) i7 2720QM (Sandy Bride) 3000.0 2250.0 1500.0 750.0 0 String Split 18Sunday, 13 November 11
• What Problem Were Trying To Solve ?Sunday, 13 November 11
• 20Sunday, 13 November 11
• 21Sunday, 13 November 11
• Why Queues Suck - Array Backed 22Sunday, 13 November 11
• Why Queues Suck - Linked List 23Sunday, 13 November 11
• Why Queues Suck - Linked List 24Sunday, 13 November 11
• Contention Free Design 25Sunday, 13 November 11
• 26Sunday, 13 November 11
• How Fast Is It - Throughput ABQ Disruptor 30000000.0 22500000.0 15000000.0 7500000.0 0 Unicast Diamond 27Sunday, 13 November 11
• How Fast Is It - Latency ABQ Disruptor Min 145 29 Mean 32,757 52 99 Percentile 2,097,152 128 99.99 Percentile 4,194,304 8,192 Max 5,069,086 175,567 28Sunday, 13 November 11
• How Does It Work ?Sunday, 13 November 11
• Ordering and Visibility private static final int SIZE = 32; private final Object[] data = new Object[SIZE]; private volatile long sequence = -1; private long nextValue = -1; public void publish(Object value) { long index = ++nextValue; data[(int)(index % SIZE)] = value; sequence = index; } public Object get(long index) { if (index <= sequence) { return data[(int)(index % SIZE)]; } return null; } 30Sunday, 13 November 11
• Ordering and Visibility - Store mov \$0x1,%ecx add 0x18(%rsi),%rcx ;*ladd ;... lea (%r12,%r8,8),%r11 ;*getfield data ;... mov %r12b,(%r11,%r10,1) mov %rcx,0x10(%rsi) lock addl \$0x0,(%rsp) ;*ladd 31Sunday, 13 November 11
• Ordering and Visibility - Load mov %eax,-0x6000(%rsp) push %rbp sub \$0x20,%rsp ;*synchronization entry ; - RingBuffer::get@-1 mov 0x10(%rsi),%r10 ;*getfield sequence ; - RingBuffer::get@2 cmp %r10,%rdx jl 0x00007ff92505f22d ;*iflt ; - RingBuffer::get@6 mov %edx,%r11d ;*l2i ; - RingBuffer::get@14 32Sunday, 13 November 11
• Look Ma’ No Memory Barrier AtomicLong sequence = new AtomicLong(-1); public void publish(Object value) { long index = ++nextValue; data[(int)(index % SIZE)] = value; sequence.lazySet(index); } 33Sunday, 13 November 11
• False Sharing - Hidden Contention 34Sunday, 13 November 11
• Cache Line Padding public class PaddedAtomicLong extends AtomicLong { public volatile long p1, p2, p3, p4, p5, p6 = 7L; //... lines omitted public long sumPaddingToPreventOptimisation() { return p1 + p2 + p3 + p4 + p5 + p6; } } 35Sunday, 13 November 11
• Summary • Concurrency is a tool • Ordering and visibility are the key challenges • For performance the details matter • Dont believe everything you read o Come up with your own theories and test them! 36Sunday, 13 November 11
• Q&A recruitment@lmax.comSunday, 13 November 11