Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Алексей	Федоров,	
Одноклассники
Counter	Wars
Зачем	вы	здесь?
3
Много интересных докладов в других залах
4
Counter
public interface Counter {
long get();
void increment();
}
5
Simple Counter
class SimpleCounter implements Counter {
private long value = 0;
public long get() {
return value;
}
publ...
6
Volatile Counter
class VolatileCounter implements Counter {
volatile long value = 0;
public long get() {
return value;
}...
7
Volatile Counter
class VolatileCounter implements Counter {
volatile long value = 0;
public long get() {
return value;
}...
8
class SynchronizedCounter implements Counter {
volatile long value = 0;
public synchronized long get() {
return value;
}...
9
Synchronized Counter
class SynchronizedCounter implements Counter {
long value = 0;
public synchronized long get() {
ret...
10
Тестовый стенд
Core(TM) i7-4770
4 x 2 x 2.0 Ghz (downscaled)
Linux Ubuntu 14.04.4
3.13.0-86-generic x86_64
taskset -c 0...
11
Бенчмарки, op/µs
Thanks to Nitsan Wakart
http://psy-lob-saw.blogspot.ru/2014/06/jdk8-update-on-scalable-counters.html
1...
Вывод	1:	синхронизация	чего-то	стоит
13
class LockCounter implements Counter {
long value;
final Lock lock = new ReentrantLock();
public long get() {
try {
loc...
14
Lock Counter
class LockCounter implements Counter {
long value;
final Lock lock = new ReentrantLock();
public long get(...
15
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
16
class LockCounter implements Counter {
long value;
final Lock lock = new ReentrantLock();
public long get() {
try {
loc...
17
class LockCounter implements Counter {
long value;
final Lock lock = new ReentrantLock(true);
public long get() {
try {...
18
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
19
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
20
Бенчмарки, op/µs
Насколько	медленнее,	чем	unfair	lock?
На	два	порядка!
Страшно	ли	это?
1 thread 2 threads 2 threads 2 t...
21
Как устроен типичный Core i7
CPU	4
CPU	0
CPU	5
CPU	1
CPU	6
CPU	2
CPU	7
CPU	3
L1	cache
L2	cache
L1	cache L1	cache L1	cac...
Вывод	2:	честность	чего-то	стоит
Атомики и	CAS
24
Compare	and	Swap	— Hardware	Support
compare-and-swap
CAS
load-link / store-conditional
LL/SC
cmpxchg
ldrex/strex lwarx/...
25
CAS Counter
public class CasLoopCounter implements Counter {
private AtomicLong value = new AtomicLong();
public long g...
26
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
27
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
28
Get-and-Add Counter
public class CasLoopCounter implements Counter {
private AtomicLong value = new AtomicLong();
publi...
29
AtomicLong.getAndAdd()
30
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
31
True Sharing
CPU	4
CPU	0
CPU	5
CPU	1
CPU	6
CPU	2
CPU	7
CPU	3
L1	cache
L2	cache
L1	cache L1	cache L1	cache
L2	cache L2	c...
32
atomicLong.getAndAdd(5)
JDK	7u95	 JDK	8u72	
60
9 7 6
100
27 27 27
1 2 3 4
ops	/	μs
threads
33
atomicLong.getAndAdd(5)
JDK	7u95	 JDK	8u72	
60
9 7 6
100
27 27 27
1 2 3 4
ops	/	μs
threads
34
atomicLong.getAndAdd(5)
JDK	7u95	 JDK	8u72	
60
9 7 6
100
27 27 27
1 2 3 4
ops	/	μs
threads
35
loop:
mov 0x10(%rbx),%rax
mov %rax,%r11
add $0x5,%r11
lock cmpxchg %r11,0x10(%rbx)
sete %r11b
movzbl %r11b,%r11d
test %...
36
lock addq $0x5,0x10(%rbp))loop:
mov 0x10(%rbx),%rax
mov %rax,%r11
add $0x5,%r11
lock cmpxchg %r11,0x10(%rbx)
sete %r11b...
37 AtomicLong.getAndAdd()	— JDK	7
38 AtomicLong.getAndAdd()	— JDK	7
cmpxchg
39
AtomicLong.getAndAdd()	— JDK	8
40
AtomicLong.getAndAdd()	— JDK	8
lock addq
JVM	
Intrinsic
Вывод	3:	 не	верьте	всему,	что	написано	
в	исходниках	OpenJDK
JDK	8
43
StampedLock Counter
public class StampedLockCounter implements Counter {
private long value = 0;
private StampedLock lo...
44
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
45
Long Adder Counter
public class LongAdderCounter implements Counter {
private LongAdder value = new LongAdder();
public...
46
Бенчмарки, op/µs
1 thread 2 threads 2 threads 2 threads4 threads8 threads
Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 C...
47
Литература
48
Материалы
• Все-все-все	— bit.ly/concurrency-interest
• Nitsan Wakart — psy-lob-saw.blogspot.com
• Алексей	Шипилёв — sh...
Вопросы	и	ответы
Vous avez terminé ce document.
Télécharger et lire hors ligne.
Prochain SlideShare
Atomics, CAS and Nonblocking algorithms
Suivant
Prochain SlideShare
Atomics, CAS and Nonblocking algorithms
Suivant
Télécharger pour lire hors ligne et voir en mode plein écran

Partager

Counter Wars (JEEConf 2016)

Télécharger pour lire hors ligne

The talks is about several ways to implement thread-safe counters. And about implementations performance.

  • Soyez le premier à aimer ceci

Counter Wars (JEEConf 2016)

  1. 1. Алексей Федоров, Одноклассники Counter Wars
  2. 2. Зачем вы здесь?
  3. 3. 3 Много интересных докладов в других залах
  4. 4. 4 Counter public interface Counter { long get(); void increment(); }
  5. 5. 5 Simple Counter class SimpleCounter implements Counter { private long value = 0; public long get() { return value; } public void increment() { value++; } }
  6. 6. 6 Volatile Counter class VolatileCounter implements Counter { volatile long value = 0; public long get() { return value; } public void increment() { value++; } }
  7. 7. 7 Volatile Counter class VolatileCounter implements Counter { volatile long value = 0; public long get() { return value; } public void increment() { long oldValue = value; // read long newValue = oldValue + 1; // modify value = newValue; // write } }
  8. 8. 8 class SynchronizedCounter implements Counter { volatile long value = 0; public synchronized long get() { return value; } public synchronized void increment() { value++; } } Synchronized Counter
  9. 9. 9 Synchronized Counter class SynchronizedCounter implements Counter { long value = 0; public synchronized long get() { return value; } public synchronized void increment() { value++; } }
  10. 10. 10 Тестовый стенд Core(TM) i7-4770 4 x 2 x 2.0 Ghz (downscaled) Linux Ubuntu 14.04.4 3.13.0-86-generic x86_64 taskset -c 0,1,2,3 (thread affinity)
  11. 11. 11 Бенчмарки, op/µs Thanks to Nitsan Wakart http://psy-lob-saw.blogspot.ru/2014/06/jdk8-update-on-scalable-counters.html 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 LONG 308 267 182 220 180 86 VOLATILE_LONG 77 77 79 22 21 35 SYNCHRONIZED 26 43 27 12 12 13
  12. 12. Вывод 1: синхронизация чего-то стоит
  13. 13. 13 class LockCounter implements Counter { long value; final Lock lock = new ReentrantLock(); public long get() { try { lock.lock(); return value; } finally { lock.unlock(); } } } public void add() { try { lock.lock(); value += 1; } finally { lock.unlock(); } } Lock Counter
  14. 14. 14 Lock Counter class LockCounter implements Counter { long value; final Lock lock = new ReentrantLock(); public long get() { try { lock.lock(); return value; } finally { lock.unlock(); } } } public void add() { try { lock.lock(); value += 1; } finally { lock.unlock(); } }
  15. 15. 15 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 REENTRANTLOCK 32 32 18 5 20 20 http://mechanical-sympathy.blogspot.com/2011/11/java-lock-implementations.html http://mechanical-sympathy.blogspot.com/2011/11/biased-locking-osr-and-benchmarking-fun.html http://www.javaspecialist.ru/2011/11/synchronized-vs-reentrantlock.html http://dev.cheremin.info/2011/11/synchronized-vs-reentrantlock.html
  16. 16. 16 class LockCounter implements Counter { long value; final Lock lock = new ReentrantLock(); public long get() { try { lock.lock(); return value; } finally { lock.unlock(); } } } public void add() { try { lock.lock(); value += 1; } finally { lock.unlock(); } } Lock Counter
  17. 17. 17 class LockCounter implements Counter { long value; final Lock lock = new ReentrantLock(true); public long get() { try { lock.lock(); return value; } finally { lock.unlock(); } } } public void add() { try { lock.lock(); value += 1; } finally { lock.unlock(); } } Lock Counter
  18. 18. 18 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 FAIR_LOCK Насколько медленнее, чем unfair lock?
  19. 19. 19 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 FAIR_LOCK 31 5 ± 9 0.5 ± 0.3 0.26 0.24 0.23 Насколько медленнее, чем unfair lock? На два порядка!
  20. 20. 20 Бенчмарки, op/µs Насколько медленнее, чем unfair lock? На два порядка! Страшно ли это? 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 FAIR_LOCK 31 5 ± 9 0.5 ± 0.3 0.26 0.24 0.23
  21. 21. 21 Как устроен типичный Core i7 CPU 4 CPU 0 CPU 5 CPU 1 CPU 6 CPU 2 CPU 7 CPU 3 L1 cache L2 cache L1 cache L1 cache L1 cache L2 cache L2 cache L2 cache L3 cache
  22. 22. Вывод 2: честность чего-то стоит
  23. 23. Атомики и CAS
  24. 24. 24 Compare and Swap — Hardware Support compare-and-swap CAS load-link / store-conditional LL/SC cmpxchg ldrex/strex lwarx/stwcx
  25. 25. 25 CAS Counter public class CasLoopCounter implements Counter { private AtomicLong value = new AtomicLong(); public long get() { return value.get(); } public void increment() { for (;;) { long oldValue = value.get(); long newValue = oldValue + 1; if (value.compareAndSet(oldValue, newValue)) return; } } }
  26. 26. 26 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 CAS_LOOP
  27. 27. 27 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 CAS_LOOP 62 62 45 10 6 5
  28. 28. 28 Get-and-Add Counter public class CasLoopCounter implements Counter { private AtomicLong value = new AtomicLong(); public long get() { return value.get(); } public void increment() { value.getAndAdd(1); } }
  29. 29. 29 AtomicLong.getAndAdd()
  30. 30. 30 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 CAS_LOOP 62 62 45 10 6 5 GET_AND_ADD 100 100 97 27 28 28
  31. 31. 31 True Sharing CPU 4 CPU 0 CPU 5 CPU 1 CPU 6 CPU 2 CPU 7 CPU 3 L1 cache L2 cache L1 cache L1 cache L1 cache L2 cache L2 cache L2 cache L3 cache
  32. 32. 32 atomicLong.getAndAdd(5) JDK 7u95 JDK 8u72 60 9 7 6 100 27 27 27 1 2 3 4 ops / μs threads
  33. 33. 33 atomicLong.getAndAdd(5) JDK 7u95 JDK 8u72 60 9 7 6 100 27 27 27 1 2 3 4 ops / μs threads
  34. 34. 34 atomicLong.getAndAdd(5) JDK 7u95 JDK 8u72 60 9 7 6 100 27 27 27 1 2 3 4 ops / μs threads
  35. 35. 35 loop: mov 0x10(%rbx),%rax mov %rax,%r11 add $0x5,%r11 lock cmpxchg %r11,0x10(%rbx) sete %r11b movzbl %r11b,%r11d test %r10d,%r10d je loop JDK 7u95 -XX:+PrintAssembly atomicLong.getAndAdd(5)
  36. 36. 36 lock addq $0x5,0x10(%rbp))loop: mov 0x10(%rbx),%rax mov %rax,%r11 add $0x5,%r11 lock cmpxchg %r11,0x10(%rbx) sete %r11b movzbl %r11b,%r11d test %r10d,%r10d je loop JDK 7u95 -XX:+PrintAssembly JDK 8u72 -XX:+PrintAssembly atomicLong.getAndAdd(5) JDK 7u95 JDK 8u72 60 9 7 6 100 27 27 27 1 2 3 4 ops / μs threads
  37. 37. 37 AtomicLong.getAndAdd() — JDK 7
  38. 38. 38 AtomicLong.getAndAdd() — JDK 7 cmpxchg
  39. 39. 39 AtomicLong.getAndAdd() — JDK 8
  40. 40. 40 AtomicLong.getAndAdd() — JDK 8 lock addq JVM Intrinsic
  41. 41. Вывод 3: не верьте всему, что написано в исходниках OpenJDK
  42. 42. JDK 8
  43. 43. 43 StampedLock Counter public class StampedLockCounter implements Counter { private long value = 0; private StampedLock lock = new StampedLock(); public long get() { ... } public void add() { long stamp = lock.writeLock(); try { value++; } finally{ lock.unlock(stamp); } } }
  44. 44. 44 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 CAS_LOOP 62 62 45 10 6 5 GET_AND_ADD 100 100 97 27 28 28 STAMPED_LOCK 31 31 24 5 22 21
  45. 45. 45 Long Adder Counter public class LongAdderCounter implements Counter { private LongAdder value = new LongAdder(); public long get() { return value.longValue(); } public void increment() { value.add(1); } }
  46. 46. 46 Бенчмарки, op/µs 1 thread 2 threads 2 threads 2 threads4 threads8 threads Core 0 Core 0 Cores 0,4 Cores 0,1 Cores 0-3 Cores 0-7 SYNCHRONIZED 26 43 27 12 12 13 UNFAIR_LOCK 32 32 18 5 20 20 CAS_LOOP 62 62 45 10 6 5 GET_AND_ADD 100 100 97 27 28 28 STAMPED_LOCK 31 31 24 5 22 21 LONG_ADDER 62 62 85 124 248 340
  47. 47. 47 Литература
  48. 48. 48 Материалы • Все-все-все — bit.ly/concurrency-interest • Nitsan Wakart — psy-lob-saw.blogspot.com • Алексей Шипилёв — shipilev.net
  49. 49. Вопросы и ответы

The talks is about several ways to implement thread-safe counters. And about implementations performance.

Vues

Nombre de vues

446

Sur Slideshare

0

À partir des intégrations

0

Nombre d'intégrations

176

Actions

Téléchargements

13

Partages

0

Commentaires

0

Mentions J'aime

0

×