SlideShare une entreprise Scribd logo
1  sur  38
Télécharger pour lire hors ligne
Clearpoint Techdrop
                              Concurrency

                                 @mikeb2701
                     http://bad-concurrency.blogspot.com



Friday, 8 March 13
public class OrderController {

               private Counter orderCounter; // What implementation???

               public void placeOrder(long productId,
                                      long customerId) {

                     orderCounter.increment();

                     // Place the order
               }

     }




Friday, 8 March 13
public class BrokenCounter implements Counter {

               private long value = 0;

               @Override
               public void increment() {
                   value++;
               }

               @Override
               public long getValue() {
                   return value;
               }
     }




Friday, 8 March 13
public class SynchronizedCounter implements Counter {

               private final Object mutex = new Object();

               private long value = 0;

               public void increment() {
                   synchronized (mutex) {
                       value++;
                   }
               }

               public long getValue() {
                   return value;
               }
     }




Friday, 8 March 13
public class LockedCounter implements Counter {
         private final Lock l = new ReentrantLock();
         private long value = 0;

               public void increment() {
                   l.lock();
                   try {
                       value++;
                   } finally {
                       l.unlock();
                   }
               }

               public long getValue() {
                   return value;
               }
     }




Friday, 8 March 13
Sync                     Locked

                       40



                       30
           M ops/sec




                       20



                       10



                        0
                            1   2          4             8            16   32
                                               Threads


Friday, 8 March 13
public class AtomicCounter implements Counter {
         private final AtomicLong value = new AtomicLong(0);

               @Override
               public void increment() {
                   value.incrementAndGet();
               }

               @Override
               public long getValue() {
                   return value.get();
               }
     }




Friday, 8 March 13
public final long incrementAndGet() {
         for (;;) {
             long current = get();
             long next = current + 1;
             if (compareAndSet(current, next))
                 return next;
         }
     }




Friday, 8 March 13
Sync       Locked       Atomic

                     90



               67.5



                     45



               22.5



                     0
                          1     2    4            8    16      32




Friday, 8 March 13
public class ThreadLocalCounter implements Counter {
         ConcurrentLinkedQueue<AtomicLong> values =
                 new ConcurrentLinkedQueue<AtomicLong>();

             private final ThreadLocal<AtomicLong> counterLocal =
                     new ThreadLocal<AtomicLong>() {
                 protected AtomicLong initialValue() {
                     AtomicLong value = new AtomicLong();
                     values.add(value);
                     return value;
                 }
             };

             public void increment() {
                 AtomicLong atomicLong = counterLocal.get();
                 atomicLong.lazySet(atomicLong.get() + 1);
             }

             public long getValue() {
                 long l = 0;
                 for (AtomicLong value : values) {
                     l += value.get();
                 }
                 return l;
             }
     }



Friday, 8 March 13
Sync       Locked       Atomic   Thread Local

              1500



              1125



                750



                375



                     0
                         1          2            4       8     16            32




Friday, 8 March 13
3. Write cache friendly code
                               DRAM                                   DRAM

                               DRAM                ~65ns              DRAM

                               DRAM                                   DRAM

                                                 QPI ~20ns
                                         MC                      MC


                               L3             ~42 cycles ~15ns             L3


                     L2   L2        L2   L2   ~10 cycles ~3ns    L2   L2        L2   L2
                     L1   L1        L1   L1    ~4 cycles ~1ns    L1   L1        L1   L1

                     C1   C2        C3   C4    Registers <1ns    C1   C2        C3   C4




Friday, 8 March 13
Friday, 8 March 13
Memory Models



Friday, 8 March 13
public class SimpleQueue {
              private final Object[] data = new Object[1024];
              private volatile int head, tail;

                     public boolean offer(Object e) {
                         if (head - (tail + data.length) < 0) {
                             data[head & (data.length - 1)] = e;
                             head++;
                             return true;
                         }
                         return false;
                     }

                     public Object poll() {
                         if (head - tail > 0) {
                             Object e = data[tail & (data.length - 1)];
                             tail++;
                             return e;
                         }
                         return null;
                     }
          }

Friday, 8 March 13
Happens-Before
Friday, 8 March 13
Causality
                     Causality
                       Fear will keep the
                      local systems inline.
                          instructions
                                - Grand Moff Wilhuff Tarkin


Friday, 8 March 13
1st
                                                     2nd Operation
                      Operation

                                      Normal Load    Volatile Load   Volatile Store
                                      Normal Store   Monitor Enter   Monitor Exit

                     Normal Load
                     Normal Store                                      NO
                     Volatile Load
                     Monitor Enter      NO              NO             NO
                     Volatile Store
                     Monitor Exit                       NO             NO



Friday, 8 March 13
•   Loads are not reordered with other loads.


                     •   Stores are not reordered with other stores.


                     •   Stores are not reordered with older loads.


                     •   In a multiprocessor system, memory ordering obeys causality (memory
                         ordering respects transitive visibility).


                     •   In a multiprocessor system, stores to the same location have a total order.


                     •   In a multiprocessor system, locked instructions to the same location have a
                         total order.


                     •   Loads and Stores are not reordered with locked instructions.




Friday, 8 March 13
Non-Blocking
                      Primitives


Friday, 8 March 13
Unsafe
Friday, 8 March 13
public class AtomicLong extends Number
                                             implements Serializable {

                         // ...
                         private volatile long value;

                         // ...
                         /**
                           * Sets to the given value.
                           *
                           * @param newValue the new value
                           */
                         public final void set(long newValue) {
                              value = newValue;
                         }

                         // ...
                     }



Friday, 8 March 13
# {method} 'set' '(J)V' in 'java/util/concurrent/atomic/AtomicLong'
   # this:       rsi:rsi   = 'java/util/concurrent/atomic/AtomicLong'
   # parm0:      rdx:rdx   = long
   #             [sp+0x20] (sp of caller)
     mov    0x8(%rsi),%r10d
     shl    $0x3,%r10
     cmp    %r10,%rax
     jne    0x00007f1f410378a0 ;     {runtime_call}
     xchg   %ax,%ax
     nopl   0x0(%rax,%rax,1)
     xchg   %ax,%ax
     push   %rbp
     sub    $0x10,%rsp
     nop
     mov    %rdx,0x10(%rsi)
     lock addl $0x0,(%rsp)     ;*putfield value
                               ; - j.u.c.a.AtomicLong::set@2 (line 112)
     add    $0x10,%rsp
     pop    %rbp
     test   %eax,0xa40fd06(%rip)         # 0x00007f1f4b471000
                               ;   {poll_return}




Friday, 8 March 13
public class AtomicLong extends Number
                                  implements Serializable {


                     // setup to use Unsafe.compareAndSwapLong for updates
                     private static final Unsafe unsafe = Unsafe.getUnsafe();
                     private static final long valueOffset;

                     // ...
                     /**
                       * Eventually sets to the given value.
                       *
                       * @param newValue the new value
                       * @since 1.6
                       */
                     public final void lazySet(long newValue) {
                          unsafe.putOrderedLong(this, valueOffset, newValue);
                     }

                     // ...
          }


Friday, 8 March 13
# {method} 'lazySet' '(J)V' in 'java/util/concurrent/atomic/
   AtomicLong'
   # this:       rsi:rsi   = 'java/util/concurrent/atomic/AtomicLong'
   # parm0:      rdx:rdx   = long
   #             [sp+0x20] (sp of caller)
     mov    0x8(%rsi),%r10d
     shl    $0x3,%r10
     cmp    %r10,%rax
     jne    0x00007f1f410378a0 ;     {runtime_call}
     xchg   %ax,%ax
     nopl   0x0(%rax,%rax,1)
     xchg   %ax,%ax
     push   %rbp
     sub    $0x10,%rsp
     nop
     mov    %rdx,0x10(%rsi)     ;*invokevirtual putOrderedLong
                                ; - AtomicLong::lazySet@8 (line 122)
     add    $0x10,%rsp
     pop    %rbp
     test   %eax,0xa41204b(%rip)         # 0x00007f1f4b471000
                                ;   {poll_return}




Friday, 8 March 13
public class AtomicInteger extends Number
                                     implements Serializable {

                     // setup to use Unsafe.compareAndSwapInt for updates
                     private static final Unsafe unsafe = Unsafe.getUnsafe();
                     private static final long valueOffset;

                     private volatile int value;

                     //...

                     public final boolean compareAndSet(int expect,
                                                        int update) {
                         return unsafe.compareAndSwapInt(this, valueOffset,
                                                         expect, update);
                     }
          }




Friday, 8 March 13
# {method} 'compareAndSet' '(JJ)Z' in 'java/util/concurrent/
   atomic/AtomicLong'
     # this:       rsi:rsi    = 'java/util/concurrent/atomic/AtomicLong'
     # parm0:      rdx:rdx    = long
     # parm1:      rcx:rcx    = long
     #             [sp+0x20] (sp of caller)
     mov     0x8(%rsi),%r10d
     shl     $0x3,%r10
     cmp     %r10,%rax
     jne     0x00007f6699037a60 ;      {runtime_call}
     xchg    %ax,%ax
     nopl    0x0(%rax,%rax,1)
     xchg    %ax,%ax
     sub     $0x18,%rsp
     mov     %rbp,0x10(%rsp)
     mov     %rdx,%rax
     lock cmpxchg %rcx,0x10(%rsi)
     sete    %r11b
     movzbl %r11b,%r11d ;*invokevirtual compareAndSwapLong
                           ; - j.u.c.a.AtomicLong::compareAndSet@9 (line
   149)
     mov     %r11d,%eax
     add     $0x10,%rsp
     pop     %rbp
     test    %eax,0x91df935(%rip)          # 0x00007f66a223e000
                           ;   {poll_return}

Friday, 8 March 13
set()   compareAndSet      lazySet()
                      9



               6.75



                     4.5



               2.25



                      0
                                     nanoseconds/op




Friday, 8 March 13
Example - Disruptor Multi-producer




                     private void publish(Disruptor disruptor, long value) {
                         long next = disruptor.next();
                         disruptor.setValue(next, value);
                         disruptor.publish(next);
                     }




Friday, 8 March 13
Example - Disruptor Multi-producer
                     public long next() {
                         long next;
                         long current;

                         do {
                             current = nextSequence.get();
                             next = current + 1;
                             while (next > (readSequence.get() + size)) {
                                 LockSupport.parkNanos(1L);
                                 continue;
                             }
                         } while (!nextSequence.compareAndSet(current, next));

                         return next;
                     }




Friday, 8 March 13
Algorithm: Spin - 1



                     public void publish(long sequence) {
                         long sequenceMinusOne = sequence - 1;
                         while (cursor.get() != sequenceMinusOne) {
                             // Spin
                         }

                         cursor.lazySet(sequence);
                     }




Friday, 8 March 13
Spin - 1
                                25



                              18.75
            million ops/sec




                               12.5



                               6.25



                                 0
                                      1   2   3     4         5      6   7   8
                                                  Producer Threads




Friday, 8 March 13
Algorithm: Co-Op
               public void publish(long sequence) {
                   int counter = RETRIES;
                   while (sequence - cursor.get() > pendingPublication.length()) {
                       if (--counter == 0) {
                           Thread.yield();
                           counter = RETRIES;
                       }
                   }

                     long expectedSequence = sequence - 1;
                     pendingPublication.set((int) sequence & pendingMask, sequence);

                     if (cursor.get() >= sequence) { return; }

                     long nextSequence = sequence;
                     while (cursor.compareAndSet(expectedSequence, nextSequence)) {
                         expectedSequence = nextSequence;
                         nextSequence++;
                         if (pendingPublication.get((int) nextSequence & pendingMask) != nextSequence) {
                             break;
                         }
                     }
               }




Friday, 8 March 13
Spin - 1              Co-Op
                                 30



                                22.5
              million ops/sec




                                 15



                                 7.5



                                  0
                                       1   2   3            4         5      6   7   8
                                                          Producer Threads




Friday, 8 March 13
Algorithm: Buffer
                     public long next() {
                         long next;
                         long current;

                         do {
                             current = cursor.get();
                             next = current + 1;
                             while (next > (readSequence.get() + size)) {
                                 LockSupport.parkNanos(1L);
                                 continue;
                             }
                         } while (!cursor.compareAndSet(current, next));

                         return next;
                     }




Friday, 8 March 13
Algorithm: Buffer


                     public void publish(long sequence) {
                         int publishedValue = (int) (sequence >>> indexShift);
                         published.set(indexOf(sequence), publishedValue);
                     }



                     // Get Value
                     int availableValue = (int) (current >>> indexShift);
                     int index = indexOf(current);
                     while (published.get(index) != availableValue) {
                          // Spin
                     }




Friday, 8 March 13
Spin - 1   Co-Op             Buffer
                                 70



                                52.5
              million ops/sec




                                 35



                                17.5



                                  0
                                       1   2        3     4             5       6    7   8
                                                              Threads




Friday, 8 March 13
Q&A
                     • https://github.com/mikeb01/jax2012
                     • http://yow.eventer.com/yow-2012-1012/
                       lock-free-algorithms-for-ultimate-
                       performance-by-martin-thompson-1250




Friday, 8 March 13

Contenu connexe

Tendances

Java concurrency
Java concurrencyJava concurrency
Java concurrencyducquoc_vn
 
Qt Framework Events Signals Threads
Qt Framework Events Signals ThreadsQt Framework Events Signals Threads
Qt Framework Events Signals ThreadsNeera Mital
 
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverS4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverPraveen Narayanan
 
Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Artur Latoszewski
 
Thread syncronization
Thread syncronizationThread syncronization
Thread syncronizationpriyabogra1
 
Java concurrency - Thread pools
Java concurrency - Thread poolsJava concurrency - Thread pools
Java concurrency - Thread poolsmaksym220889
 
Basics of Java Concurrency
Basics of Java ConcurrencyBasics of Java Concurrency
Basics of Java Concurrencykshanth2101
 
Java class 6
Java class 6Java class 6
Java class 6Edureka!
 
Java Multithreading and Concurrency
Java Multithreading and ConcurrencyJava Multithreading and Concurrency
Java Multithreading and ConcurrencyRajesh Ananda Kumar
 
Morena middleware2012
Morena middleware2012Morena middleware2012
Morena middleware2012alombide
 
Python multithreading session 9 - shanmugam
Python multithreading session 9 - shanmugamPython multithreading session 9 - shanmugam
Python multithreading session 9 - shanmugamNavaneethan Naveen
 
Non-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmNon-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmAlexey Fyodorov
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threadsYnon Perek
 
Java multi threading
Java multi threadingJava multi threading
Java multi threadingRaja Sekhar
 
Akka cluster overview at 010dev
Akka cluster overview at 010devAkka cluster overview at 010dev
Akka cluster overview at 010devRoland Kuhn
 
Java util concurrent
Java util concurrentJava util concurrent
Java util concurrentRoger Xia
 
Priming Java for Speed at Market Open
Priming Java for Speed at Market OpenPriming Java for Speed at Market Open
Priming Java for Speed at Market OpenAzul Systems Inc.
 
Threading in iOS / Cocoa Touch
Threading in iOS / Cocoa TouchThreading in iOS / Cocoa Touch
Threading in iOS / Cocoa Touchmobiledeveloperpl
 

Tendances (20)

Java concurrency
Java concurrencyJava concurrency
Java concurrency
 
Qt Framework Events Signals Threads
Qt Framework Events Signals ThreadsQt Framework Events Signals Threads
Qt Framework Events Signals Threads
 
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solverS4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
S4495-plasma-turbulence-sims-gyrokinetic-tokamak-solver
 
Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?Kotlin coroutine - the next step for RxJava developer?
Kotlin coroutine - the next step for RxJava developer?
 
Thread syncronization
Thread syncronizationThread syncronization
Thread syncronization
 
Java concurrency - Thread pools
Java concurrency - Thread poolsJava concurrency - Thread pools
Java concurrency - Thread pools
 
Basics of Java Concurrency
Basics of Java ConcurrencyBasics of Java Concurrency
Basics of Java Concurrency
 
Java class 6
Java class 6Java class 6
Java class 6
 
Java Multithreading and Concurrency
Java Multithreading and ConcurrencyJava Multithreading and Concurrency
Java Multithreading and Concurrency
 
Lockless
LocklessLockless
Lockless
 
Morena middleware2012
Morena middleware2012Morena middleware2012
Morena middleware2012
 
Python multithreading session 9 - shanmugam
Python multithreading session 9 - shanmugamPython multithreading session 9 - shanmugam
Python multithreading session 9 - shanmugam
 
Multi threading
Multi threadingMulti threading
Multi threading
 
Non-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithmNon-blocking Michael-Scott queue algorithm
Non-blocking Michael-Scott queue algorithm
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
 
Java multi threading
Java multi threadingJava multi threading
Java multi threading
 
Akka cluster overview at 010dev
Akka cluster overview at 010devAkka cluster overview at 010dev
Akka cluster overview at 010dev
 
Java util concurrent
Java util concurrentJava util concurrent
Java util concurrent
 
Priming Java for Speed at Market Open
Priming Java for Speed at Market OpenPriming Java for Speed at Market Open
Priming Java for Speed at Market Open
 
Threading in iOS / Cocoa Touch
Threading in iOS / Cocoa TouchThreading in iOS / Cocoa Touch
Threading in iOS / Cocoa Touch
 

En vedette

Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)Kris Mok
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMKris Mok
 
Refactoring for Software Design Smells - Tech Talk
Refactoring for Software Design Smells - Tech TalkRefactoring for Software Design Smells - Tech Talk
Refactoring for Software Design Smells - Tech TalkCodeOps Technologies LLP
 
Implementing a JavaScript Engine
Implementing a JavaScript EngineImplementing a JavaScript Engine
Implementing a JavaScript EngineKris Mok
 

En vedette (6)

Marketing_SBI_Booklet_NEW
Marketing_SBI_Booklet_NEWMarketing_SBI_Booklet_NEW
Marketing_SBI_Booklet_NEW
 
Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)Nashorn on JDK 8 (ADC2013)
Nashorn on JDK 8 (ADC2013)
 
Intrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VMIntrinsic Methods in HotSpot VM
Intrinsic Methods in HotSpot VM
 
Refactoring for Software Design Smells - Tech Talk
Refactoring for Software Design Smells - Tech TalkRefactoring for Software Design Smells - Tech Talk
Refactoring for Software Design Smells - Tech Talk
 
Java Concurrency by Example
Java Concurrency by ExampleJava Concurrency by Example
Java Concurrency by Example
 
Implementing a JavaScript Engine
Implementing a JavaScript EngineImplementing a JavaScript Engine
Implementing a JavaScript Engine
 

Similaire à Concurrecy techdrop

Java synchronizers
Java synchronizersJava synchronizers
Java synchronizersts_v_murthy
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrencyfeng lee
 
Concurrent talk
Concurrent talkConcurrent talk
Concurrent talkrahulrevo
 
Java concurrency begining
Java concurrency   beginingJava concurrency   begining
Java concurrency beginingmaksym220889
 
Core Java Programming Language (JSE) : Chapter XII - Threads
Core Java Programming Language (JSE) : Chapter XII -  ThreadsCore Java Programming Language (JSE) : Chapter XII -  Threads
Core Java Programming Language (JSE) : Chapter XII - ThreadsWebStackAcademy
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency GotchasAlex Miller
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à DartSOAT
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency IdiomsAlex Miller
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel GeheugenDevnology
 
Introduction to Concurrent Data Structures
Introduction to Concurrent Data StructuresIntroduction to Concurrent Data Structures
Introduction to Concurrent Data StructuresDilum Bandara
 
Closures for Java
Closures for JavaClosures for Java
Closures for Javanextlib
 
ikh331-06-distributed-programming
ikh331-06-distributed-programmingikh331-06-distributed-programming
ikh331-06-distributed-programmingAnung Ariwibowo
 

Similaire à Concurrecy techdrop (20)

Java synchronizers
Java synchronizersJava synchronizers
Java synchronizers
 
Effective java - concurrency
Effective java - concurrencyEffective java - concurrency
Effective java - concurrency
 
Concurrent talk
Concurrent talkConcurrent talk
Concurrent talk
 
Java concurrency begining
Java concurrency   beginingJava concurrency   begining
Java concurrency begining
 
Core Java Programming Language (JSE) : Chapter XII - Threads
Core Java Programming Language (JSE) : Chapter XII -  ThreadsCore Java Programming Language (JSE) : Chapter XII -  Threads
Core Java Programming Language (JSE) : Chapter XII - Threads
 
Circuit breaker
Circuit breakerCircuit breaker
Circuit breaker
 
JUnit PowerUp
JUnit PowerUpJUnit PowerUp
JUnit PowerUp
 
Java Concurrency Gotchas
Java Concurrency GotchasJava Concurrency Gotchas
Java Concurrency Gotchas
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à Dart
 
Concurrency gotchas
Concurrency gotchasConcurrency gotchas
Concurrency gotchas
 
concurrency_c#_public
concurrency_c#_publicconcurrency_c#_public
concurrency_c#_public
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency Idioms
 
Software Transactioneel Geheugen
Software Transactioneel GeheugenSoftware Transactioneel Geheugen
Software Transactioneel Geheugen
 
Introduction to Concurrent Data Structures
Introduction to Concurrent Data StructuresIntroduction to Concurrent Data Structures
Introduction to Concurrent Data Structures
 
Multithreading in Java
Multithreading in JavaMultithreading in Java
Multithreading in Java
 
Closures for Java
Closures for JavaClosures for Java
Closures for Java
 
Thread
ThreadThread
Thread
 
Threads in java
Threads in javaThreads in java
Threads in java
 
ikh331-06-distributed-programming
ikh331-06-distributed-programmingikh331-06-distributed-programming
ikh331-06-distributed-programming
 
Threads
ThreadsThreads
Threads
 

Plus de Michael Barker

Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About PerformanceMichael Barker
 
Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!Michael Barker
 
Beginners guide-concurrency
Beginners guide-concurrencyBeginners guide-concurrency
Beginners guide-concurrencyMichael Barker
 
Disruptor tools in action
Disruptor   tools in actionDisruptor   tools in action
Disruptor tools in actionMichael Barker
 

Plus de Michael Barker (7)

Value Types
Value TypesValue Types
Value Types
 
Stuff I Learned About Performance
Stuff I Learned About PerformanceStuff I Learned About Performance
Stuff I Learned About Performance
 
Test automation 3
Test automation 3Test automation 3
Test automation 3
 
Disruptor yow2013 v2
Disruptor yow2013 v2Disruptor yow2013 v2
Disruptor yow2013 v2
 
Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!Lock? We don't need no stinkin' locks!
Lock? We don't need no stinkin' locks!
 
Beginners guide-concurrency
Beginners guide-concurrencyBeginners guide-concurrency
Beginners guide-concurrency
 
Disruptor tools in action
Disruptor   tools in actionDisruptor   tools in action
Disruptor tools in action
 

Concurrecy techdrop

  • 1. Clearpoint Techdrop Concurrency @mikeb2701 http://bad-concurrency.blogspot.com Friday, 8 March 13
  • 2. public class OrderController { private Counter orderCounter; // What implementation??? public void placeOrder(long productId, long customerId) { orderCounter.increment(); // Place the order } } Friday, 8 March 13
  • 3. public class BrokenCounter implements Counter { private long value = 0; @Override public void increment() { value++; } @Override public long getValue() { return value; } } Friday, 8 March 13
  • 4. public class SynchronizedCounter implements Counter { private final Object mutex = new Object(); private long value = 0; public void increment() { synchronized (mutex) { value++; } } public long getValue() { return value; } } Friday, 8 March 13
  • 5. public class LockedCounter implements Counter { private final Lock l = new ReentrantLock(); private long value = 0; public void increment() { l.lock(); try { value++; } finally { l.unlock(); } } public long getValue() { return value; } } Friday, 8 March 13
  • 6. Sync Locked 40 30 M ops/sec 20 10 0 1 2 4 8 16 32 Threads Friday, 8 March 13
  • 7. public class AtomicCounter implements Counter { private final AtomicLong value = new AtomicLong(0); @Override public void increment() { value.incrementAndGet(); } @Override public long getValue() { return value.get(); } } Friday, 8 March 13
  • 8. public final long incrementAndGet() { for (;;) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return next; } } Friday, 8 March 13
  • 9. Sync Locked Atomic 90 67.5 45 22.5 0 1 2 4 8 16 32 Friday, 8 March 13
  • 10. public class ThreadLocalCounter implements Counter { ConcurrentLinkedQueue<AtomicLong> values = new ConcurrentLinkedQueue<AtomicLong>(); private final ThreadLocal<AtomicLong> counterLocal = new ThreadLocal<AtomicLong>() { protected AtomicLong initialValue() { AtomicLong value = new AtomicLong(); values.add(value); return value; } }; public void increment() { AtomicLong atomicLong = counterLocal.get(); atomicLong.lazySet(atomicLong.get() + 1); } public long getValue() { long l = 0; for (AtomicLong value : values) { l += value.get(); } return l; } } Friday, 8 March 13
  • 11. Sync Locked Atomic Thread Local 1500 1125 750 375 0 1 2 4 8 16 32 Friday, 8 March 13
  • 12. 3. Write cache friendly code DRAM DRAM DRAM ~65ns DRAM DRAM DRAM QPI ~20ns MC MC L3 ~42 cycles ~15ns L3 L2 L2 L2 L2 ~10 cycles ~3ns L2 L2 L2 L2 L1 L1 L1 L1 ~4 cycles ~1ns L1 L1 L1 L1 C1 C2 C3 C4 Registers <1ns C1 C2 C3 C4 Friday, 8 March 13
  • 15. public class SimpleQueue { private final Object[] data = new Object[1024]; private volatile int head, tail; public boolean offer(Object e) { if (head - (tail + data.length) < 0) { data[head & (data.length - 1)] = e; head++; return true; } return false; } public Object poll() { if (head - tail > 0) { Object e = data[tail & (data.length - 1)]; tail++; return e; } return null; } } Friday, 8 March 13
  • 17. Causality Causality Fear will keep the local systems inline. instructions - Grand Moff Wilhuff Tarkin Friday, 8 March 13
  • 18. 1st 2nd Operation Operation Normal Load Volatile Load Volatile Store Normal Store Monitor Enter Monitor Exit Normal Load Normal Store NO Volatile Load Monitor Enter NO NO NO Volatile Store Monitor Exit NO NO Friday, 8 March 13
  • 19. Loads are not reordered with other loads. • Stores are not reordered with other stores. • Stores are not reordered with older loads. • In a multiprocessor system, memory ordering obeys causality (memory ordering respects transitive visibility). • In a multiprocessor system, stores to the same location have a total order. • In a multiprocessor system, locked instructions to the same location have a total order. • Loads and Stores are not reordered with locked instructions. Friday, 8 March 13
  • 20. Non-Blocking Primitives Friday, 8 March 13
  • 22. public class AtomicLong extends Number implements Serializable { // ... private volatile long value; // ... /** * Sets to the given value. * * @param newValue the new value */ public final void set(long newValue) { value = newValue; } // ... } Friday, 8 March 13
  • 23. # {method} 'set' '(J)V' in 'java/util/concurrent/atomic/AtomicLong' # this: rsi:rsi = 'java/util/concurrent/atomic/AtomicLong' # parm0: rdx:rdx = long # [sp+0x20] (sp of caller) mov 0x8(%rsi),%r10d shl $0x3,%r10 cmp %r10,%rax jne 0x00007f1f410378a0 ; {runtime_call} xchg %ax,%ax nopl 0x0(%rax,%rax,1) xchg %ax,%ax push %rbp sub $0x10,%rsp nop mov %rdx,0x10(%rsi) lock addl $0x0,(%rsp) ;*putfield value ; - j.u.c.a.AtomicLong::set@2 (line 112) add $0x10,%rsp pop %rbp test %eax,0xa40fd06(%rip) # 0x00007f1f4b471000 ; {poll_return} Friday, 8 March 13
  • 24. public class AtomicLong extends Number implements Serializable { // setup to use Unsafe.compareAndSwapLong for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; // ... /** * Eventually sets to the given value. * * @param newValue the new value * @since 1.6 */ public final void lazySet(long newValue) { unsafe.putOrderedLong(this, valueOffset, newValue); } // ... } Friday, 8 March 13
  • 25. # {method} 'lazySet' '(J)V' in 'java/util/concurrent/atomic/ AtomicLong' # this: rsi:rsi = 'java/util/concurrent/atomic/AtomicLong' # parm0: rdx:rdx = long # [sp+0x20] (sp of caller) mov 0x8(%rsi),%r10d shl $0x3,%r10 cmp %r10,%rax jne 0x00007f1f410378a0 ; {runtime_call} xchg %ax,%ax nopl 0x0(%rax,%rax,1) xchg %ax,%ax push %rbp sub $0x10,%rsp nop mov %rdx,0x10(%rsi) ;*invokevirtual putOrderedLong ; - AtomicLong::lazySet@8 (line 122) add $0x10,%rsp pop %rbp test %eax,0xa41204b(%rip) # 0x00007f1f4b471000 ; {poll_return} Friday, 8 March 13
  • 26. public class AtomicInteger extends Number implements Serializable { // setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value; //... public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } } Friday, 8 March 13
  • 27. # {method} 'compareAndSet' '(JJ)Z' in 'java/util/concurrent/ atomic/AtomicLong' # this: rsi:rsi = 'java/util/concurrent/atomic/AtomicLong' # parm0: rdx:rdx = long # parm1: rcx:rcx = long # [sp+0x20] (sp of caller) mov 0x8(%rsi),%r10d shl $0x3,%r10 cmp %r10,%rax jne 0x00007f6699037a60 ; {runtime_call} xchg %ax,%ax nopl 0x0(%rax,%rax,1) xchg %ax,%ax sub $0x18,%rsp mov %rbp,0x10(%rsp) mov %rdx,%rax lock cmpxchg %rcx,0x10(%rsi) sete %r11b movzbl %r11b,%r11d ;*invokevirtual compareAndSwapLong ; - j.u.c.a.AtomicLong::compareAndSet@9 (line 149) mov %r11d,%eax add $0x10,%rsp pop %rbp test %eax,0x91df935(%rip) # 0x00007f66a223e000 ; {poll_return} Friday, 8 March 13
  • 28. set() compareAndSet lazySet() 9 6.75 4.5 2.25 0 nanoseconds/op Friday, 8 March 13
  • 29. Example - Disruptor Multi-producer private void publish(Disruptor disruptor, long value) { long next = disruptor.next(); disruptor.setValue(next, value); disruptor.publish(next); } Friday, 8 March 13
  • 30. Example - Disruptor Multi-producer public long next() { long next; long current; do { current = nextSequence.get(); next = current + 1; while (next > (readSequence.get() + size)) { LockSupport.parkNanos(1L); continue; } } while (!nextSequence.compareAndSet(current, next)); return next; } Friday, 8 March 13
  • 31. Algorithm: Spin - 1 public void publish(long sequence) { long sequenceMinusOne = sequence - 1; while (cursor.get() != sequenceMinusOne) { // Spin } cursor.lazySet(sequence); } Friday, 8 March 13
  • 32. Spin - 1 25 18.75 million ops/sec 12.5 6.25 0 1 2 3 4 5 6 7 8 Producer Threads Friday, 8 March 13
  • 33. Algorithm: Co-Op public void publish(long sequence) { int counter = RETRIES; while (sequence - cursor.get() > pendingPublication.length()) { if (--counter == 0) { Thread.yield(); counter = RETRIES; } } long expectedSequence = sequence - 1; pendingPublication.set((int) sequence & pendingMask, sequence); if (cursor.get() >= sequence) { return; } long nextSequence = sequence; while (cursor.compareAndSet(expectedSequence, nextSequence)) { expectedSequence = nextSequence; nextSequence++; if (pendingPublication.get((int) nextSequence & pendingMask) != nextSequence) { break; } } } Friday, 8 March 13
  • 34. Spin - 1 Co-Op 30 22.5 million ops/sec 15 7.5 0 1 2 3 4 5 6 7 8 Producer Threads Friday, 8 March 13
  • 35. Algorithm: Buffer public long next() { long next; long current; do { current = cursor.get(); next = current + 1; while (next > (readSequence.get() + size)) { LockSupport.parkNanos(1L); continue; } } while (!cursor.compareAndSet(current, next)); return next; } Friday, 8 March 13
  • 36. Algorithm: Buffer public void publish(long sequence) { int publishedValue = (int) (sequence >>> indexShift); published.set(indexOf(sequence), publishedValue); } // Get Value int availableValue = (int) (current >>> indexShift); int index = indexOf(current); while (published.get(index) != availableValue) { // Spin } Friday, 8 March 13
  • 37. Spin - 1 Co-Op Buffer 70 52.5 million ops/sec 35 17.5 0 1 2 3 4 5 6 7 8 Threads Friday, 8 March 13
  • 38. Q&A • https://github.com/mikeb01/jax2012 • http://yow.eventer.com/yow-2012-1012/ lock-free-algorithms-for-ultimate- performance-by-martin-thompson-1250 Friday, 8 March 13