@jpbempel#LockFree @jpbempel#LockFree
Programmation Lock-Free :
les techniques des pros
Ullink
Architecte Performance
@jpb...
@jpbempel#LockFree
Objectif
Réduction de la contention pour une meilleure scalabilité
@jpbempel#LockFree
Agenda 1ère partie
Mesurer la contention
Copy On Write
Lock striping
Compare-And-Swap
Introduction au M...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Immutabilité
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Contention
@jpbempel#LockFree @jpbempel#LockFree
Contention
2 threads ou plus essayant d'acquérir
un lock
Threads en attente de la li...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Measure, don’t guess!
Kirk Pepperdine & Jack Shi...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Measure, don’t
premature!
@jpbempel#LockFree @jpbempel#LockFree
Bloc Synchronized
•Profilers (YourKit, JProfiler, ZVision)
•JVMTI native agent
•Résu...
@jpbempel#LockFree @jpbempel#LockFree
Mesurer la contention
@jpbempel#LockFree @jpbempel#LockFree
Mesurer la contention
@jpbempel#LockFree @jpbempel#LockFree
Mesurer la contention
java.util.concurrent.Lock
•JVM ne peut aider ici
•classes du J...
@jpbempel#LockFree @jpbempel#LockFree
Mesurer la contention
@jpbempel#LockFree @jpbempel#LockFree
Mesurer la contention
Insertion de compteur de contention
•Identifier les endroits o...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Copy On Write
@jpbempel#LockFree @jpbempel#LockFree
Copier toutes les données quand il y a modification
Très simple, même chose que l’im...
@jpbempel#LockFree @jpbempel#LockFree
Meilleur exemple dans JDK: CopyOnWriteArrayList
Parfait pour les listes de listeners...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Lock striping
@jpbempel#LockFree @jpbempel#LockFree
Réduire la contention en la distribuant
N’enlève pas de locks, mais en ajoute !
Effi...
@jpbempel#LockFree @jpbempel#LockFree
Meilleur exemple dans JDK: ConcurrentHashMap [JDK7]
Lock striping
@jpbempel#LockFree @jpbempel#LockFree
Relativement simple à implémenter
Peut être très efficace si bon partitionnement
Peu...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Compare-And-Swap
@jpbempel#LockFree @jpbempel#LockFree
Primitive pour n’importe quel algorithme Lock-Free
Utilisé pour implémenter locks et...
@jpbempel#LockFree @jpbempel#LockFree
Met à jour de façon atomique un emplacement mémoire par
une valeur si la précédente ...
@jpbempel#LockFree @jpbempel#LockFree
Compare-And-Swap
@jpbempel#LockFree @jpbempel#LockFree
En Java pour les classes AtomicXXX :
L’adresse mémoire est le champ value de la clas...
@jpbempel#LockFree @jpbempel#LockFree
Incrément atomique avec CAS
[JDK7] getAndIncrement():
[JDK8] getAndIncrement():
“int...
@jpbempel#LockFree @jpbempel#LockFree
Echange atomique avec CAS
[JDK7] long getAndSet(long newValue):
[JDK8] long getAndSe...
@jpbempel#LockFree @jpbempel#LockFree
ReentrantLock est implémenté avec CAS
Si CAS échoue => Lock déjà acquis
Compare-And-...
@jpbempel#LockFree @jpbempel#LockFree
L’algorithme lock-free le plus simple
Utilise CAS pour mettre à jour le pointeur sui...
@jpbempel#LockFree @jpbempel#LockFree
Compare-And-Swap: ConcurrentLinkedQ
@jpbempel#LockFree @jpbempel#LockFree
Compare-And-Swap: ConcurrentLinkedQ
@jpbempel#LockFree @jpbempel#LockFree
Compare-And-Swap: ConcurrentLinkedQ
@jpbempel#LockFree @jpbempel#LockFree
Compare-And-Swap: ConcurrentLinkedQ
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Modèle Mémoire Java
(Introduction)
@jpbempel#LockFree @jpbempel#LockFree
Premier langage à avoir un modèle mémoire bien défini:
Java JDK5 (2004) avec le JSR ...
@jpbempel#LockFree @jpbempel#LockFree
Ordonnancement mémoire
int a;
int b;
boolean enabled;
{ {
a = 21; enabled = true;
b ...
@jpbempel#LockFree @jpbempel#LockFree
Ordonnancement mémoire
int a;
int b;
boolean enabled;
Thread 1 Thread 2
{ {
a = 21; ...
@jpbempel#LockFree @jpbempel#LockFree
Ordonnancement mémoire
int a;
int b;
volatile boolean enabled;
Thread 1 Thread 2
{ {...
@jpbempel#LockFree @jpbempel#LockFree
Peut être à 2 niveaux: Compilateur & Hardware
En fonction de l’architecture du CPU, ...
@jpbempel#LockFree @jpbempel#LockFree
Barrière mémoire
@jpbempel#LockFree @jpbempel#LockFree
Champ volatile implique des barrières mémoires
Barrière compilateur : empêche réordo...
@jpbempel#LockFree @jpbempel#LockFree
CAS est aussi une barrière mémoire
Compilateur : Reconnu par le JIT (Unsafe)
Matérie...
@jpbempel#LockFree @jpbempel#LockFree
blocs synchronized ont aussi des barrières mémoires
Entrée du bloc: Barrière mémoire...
@jpbempel#LockFree @jpbempel#LockFree
Méthode des classes AtomicXXX
Barrière mémoire seulement pour le compilateur
Pas de ...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Ce qu’il faut retenir
@jpbempel#LockFree @jpbempel#LockFree
Mesurer
Copier
Distribuer
Mettre à jour atomiquement
Ordonner
Ce qu’il faut retenir
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
A suivre...
@jpbempel#LockFree @jpbempel#LockFree
Disruptor & Ring Buffer
wait/notify – await/signal
Attente active (Spinning)
Queues ...
@jpbempel#LockFree
Références
•jucProfiler: http://www.infoq.com/articles/jucprofiler
•Java Memory Model Pragmatics: http:...
@jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree
Q & A
Ullink
Architecte Performance
@jpbempel
ht...
Prochain SlideShare
Chargement dans…5
×

Programmation lock free - les techniques des pros (1ere partie)

1 043 vues

Publié le

La scalabilité des applications est une préoccupation importante. Beaucoup de pertes en scalabilité proviennent de code contenant des locks qui produisent une importante contention en cas de forte charge.

Dans cette présentation nous allons aborder différentes techniques (striping, copy-on-write, ring buffer, spinning, ...) qui vont nous permettre de réduire cette contention ou d'obtenir un code sans lock. Nous expliquerons aussi les concepts de Compare-And-Swap et de barrières mémoires.

0 commentaire
3 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
1 043
Sur SlideShare
0
Issues des intégrations
0
Intégrations
13
Actions
Partages
0
Téléchargements
30
Commentaires
0
J’aime
3
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Programmation lock free - les techniques des pros (1ere partie)

  1. 1. @jpbempel#LockFree @jpbempel#LockFree Programmation Lock-Free : les techniques des pros Ullink Architecte Performance @jpbempel http://jpbempel.blogspot.com jpbempel@ullink.com
  2. 2. @jpbempel#LockFree Objectif Réduction de la contention pour une meilleure scalabilité
  3. 3. @jpbempel#LockFree Agenda 1ère partie Mesurer la contention Copy On Write Lock striping Compare-And-Swap Introduction au Modèle Mémoire Java
  4. 4. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Immutabilité
  5. 5. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Contention
  6. 6. @jpbempel#LockFree @jpbempel#LockFree Contention 2 threads ou plus essayant d'acquérir un lock Threads en attente de la libération du lock Raison numéro 1 pour éviter les locks Photo de Filip Bogdan
  7. 7. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Measure, don’t guess! Kirk Pepperdine & Jack Shirazi
  8. 8. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Measure, don’t premature!
  9. 9. @jpbempel#LockFree @jpbempel#LockFree Bloc Synchronized •Profilers (YourKit, JProfiler, ZVision) •JVMTI native agent •Résultats peuvent être difficiles à exploiter Mesurer la contention
  10. 10. @jpbempel#LockFree @jpbempel#LockFree Mesurer la contention
  11. 11. @jpbempel#LockFree @jpbempel#LockFree Mesurer la contention
  12. 12. @jpbempel#LockFree @jpbempel#LockFree Mesurer la contention java.util.concurrent.Lock •JVM ne peut aider ici •classes du JDK, code classique •JProfiler peut les profiler •Modification classes j.u.c + bootclasspath (jucProfiler)
  13. 13. @jpbempel#LockFree @jpbempel#LockFree Mesurer la contention
  14. 14. @jpbempel#LockFree @jpbempel#LockFree Mesurer la contention Insertion de compteur de contention •Identifier les endroits où l’acquisition des locks échouent •Incrémenter le compteur Identifier les locks •Callstack à l’instanciation •logger le statut des compteurs Comment mesurer les locks existants dans votre code •Modifier les classes du JDK •Réintroduire ces classes dans les bootclasspath
  15. 15. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Copy On Write
  16. 16. @jpbempel#LockFree @jpbempel#LockFree Copier toutes les données quand il y a modification Très simple, même chose que l’immutabilité Même problèmes que l’immutabilité (surcoût copie, GC) Fonctionne bien pour structures à faible modification Copy On Write
  17. 17. @jpbempel#LockFree @jpbempel#LockFree Meilleur exemple dans JDK: CopyOnWriteArrayList Parfait pour les listes de listeners Autre usage interne: CopyOnWriteHashMap Maps de référence Copy On Write
  18. 18. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Lock striping
  19. 19. @jpbempel#LockFree @jpbempel#LockFree Réduire la contention en la distribuant N’enlève pas de locks, mais en ajoute ! Efficacité dépend d’un bon partitionnement (cf HashMap) Lock striping
  20. 20. @jpbempel#LockFree @jpbempel#LockFree Meilleur exemple dans JDK: ConcurrentHashMap [JDK7] Lock striping
  21. 21. @jpbempel#LockFree @jpbempel#LockFree Relativement simple à implémenter Peut être très efficace si bon partitionnement Peut être affiné (nombre de partitions) en fonction de la contention/niveau de concurrence Lock striping
  22. 22. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Compare-And-Swap
  23. 23. @jpbempel#LockFree @jpbempel#LockFree Primitive pour n’importe quel algorithme Lock-Free Utilisé pour implémenter locks et primitives de synchronisations Géré directement par le CPU (instruction dédiée) Compare-And-Swap
  24. 24. @jpbempel#LockFree @jpbempel#LockFree Met à jour de façon atomique un emplacement mémoire par une valeur si la précédente est celle attendue instruction à 3 arguments: •adresse mémoire (rbx) •valeur attendue (rax) •nouvelle valeur (rcx) Compare-And-Swap movabs rax,0x2a movabs rcx,0x2b lock cmpxchg QWORD PTR [rbx],rcx
  25. 25. @jpbempel#LockFree @jpbempel#LockFree Compare-And-Swap
  26. 26. @jpbempel#LockFree @jpbempel#LockFree En Java pour les classes AtomicXXX : L’adresse mémoire est le champ value de la classe Compare-And-Swap boolean compareAndSet(expect, update)
  27. 27. @jpbempel#LockFree @jpbempel#LockFree Incrément atomique avec CAS [JDK7] getAndIncrement(): [JDK8] getAndIncrement(): “intrinsèquifier”: Compare-And-Swap: AtomicLong while (true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } return unsafe.getAndAddLong(this, valueOffset, 1L); movabs rsi,0x1 lock xadd QWORD PTR [rdx+0x10],rsi
  28. 28. @jpbempel#LockFree @jpbempel#LockFree Echange atomique avec CAS [JDK7] long getAndSet(long newValue): [JDK8] long getAndSet(long newValue): “intrinsèquifier”: Compare-And-Swap: AtomicLong while (true) { long current = get(); if (compareAndSet(current, newValue)) return current; } return unsafe.getAndSetLong(this, valueOffset, newValue); xchg QWORD PTR [rsi+0x10],rdi
  29. 29. @jpbempel#LockFree @jpbempel#LockFree ReentrantLock est implémenté avec CAS Si CAS échoue => Lock déjà acquis Compare-And-Swap: lock volatile int state; lock() compareAndSet(0, 1); unlock(): setState(0);
  30. 30. @jpbempel#LockFree @jpbempel#LockFree L’algorithme lock-free le plus simple Utilise CAS pour mettre à jour le pointeur suivant dans la liste chainée Si CAS échoue, une mise à jour concurrente a eu lieu Lire la nouvelle valeur, aller à l’élément suivant et renouveler le CAS Compare-And-Swap: ConcurrentLinkedQ
  31. 31. @jpbempel#LockFree @jpbempel#LockFree Compare-And-Swap: ConcurrentLinkedQ
  32. 32. @jpbempel#LockFree @jpbempel#LockFree Compare-And-Swap: ConcurrentLinkedQ
  33. 33. @jpbempel#LockFree @jpbempel#LockFree Compare-And-Swap: ConcurrentLinkedQ
  34. 34. @jpbempel#LockFree @jpbempel#LockFree Compare-And-Swap: ConcurrentLinkedQ
  35. 35. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Modèle Mémoire Java (Introduction)
  36. 36. @jpbempel#LockFree @jpbempel#LockFree Premier langage à avoir un modèle mémoire bien défini: Java JDK5 (2004) avec le JSR 133 C++ obtient le sien en 2011 (C++11) Avant cela, certaines constructions sont non définies ou différentes en fonction de la plateforme/compilateur (ex : Double Check Locking) Modèle Mémoire Java
  37. 37. @jpbempel#LockFree @jpbempel#LockFree Ordonnancement mémoire int a; int b; boolean enabled; { { a = 21; enabled = true; b = a * 2; a = 21; enabled = true; b = a * 2; } } JIT Compiler
  38. 38. @jpbempel#LockFree @jpbempel#LockFree Ordonnancement mémoire int a; int b; boolean enabled; Thread 1 Thread 2 { { a = 21; if (enabled) { b = a * 2; int answer = b; enabled = true; process(answer); } } }
  39. 39. @jpbempel#LockFree @jpbempel#LockFree Ordonnancement mémoire int a; int b; volatile boolean enabled; Thread 1 Thread 2 { { a = 21; if (enabled) { b = a * 2; int answer = b; enabled = true; process(answer); } } }
  40. 40. @jpbempel#LockFree @jpbempel#LockFree Peut être à 2 niveaux: Compilateur & Hardware En fonction de l’architecture du CPU, la barrière n’est pas forcément requise x86: Modèle fort, réordonnancement limité Barrière Mémoire
  41. 41. @jpbempel#LockFree @jpbempel#LockFree Barrière mémoire
  42. 42. @jpbempel#LockFree @jpbempel#LockFree Champ volatile implique des barrières mémoires Barrière compilateur : empêche réordonnancement Barrière matérielle : S’assure que les buffers sont vidés Sur x86, seule la barrière d’écriture est nécessaire Barrière mémoire: volatile lock add DWORD PTR [rsp],0x0
  43. 43. @jpbempel#LockFree @jpbempel#LockFree CAS est aussi une barrière mémoire Compilateur : Reconnu par le JIT (Unsafe) Matérielle : toutes les instructions lock agissent comme une barrière mémoire Barrière mémoire: CAS
  44. 44. @jpbempel#LockFree @jpbempel#LockFree blocs synchronized ont aussi des barrières mémoires Entrée du bloc: Barrière mémoire de lecture Sortie du bloc: Barrière mémoire d’écriture Barrière mémoire: synchronized synchronized (this) { enabled = true; a = 21; b = a * 2; }
  45. 45. @jpbempel#LockFree @jpbempel#LockFree Méthode des classes AtomicXXX Barrière mémoire seulement pour le compilateur Pas de barrière mémoire matérielle pour l’écriture Garantit toujours l’ordonnancement, mais l’effet ne sera pas immédiat pour les autres threads Barrière mémoire: lazySet
  46. 46. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Ce qu’il faut retenir
  47. 47. @jpbempel#LockFree @jpbempel#LockFree Mesurer Copier Distribuer Mettre à jour atomiquement Ordonner Ce qu’il faut retenir
  48. 48. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree A suivre...
  49. 49. @jpbempel#LockFree @jpbempel#LockFree Disruptor & Ring Buffer wait/notify – await/signal Attente active (Spinning) Queues lock-free (JCTools) Ticketage : OrderedScheduler A suivre dans la 2ème partie
  50. 50. @jpbempel#LockFree Références •jucProfiler: http://www.infoq.com/articles/jucprofiler •Java Memory Model Pragmatics: http://shipilev.net/blog/2014/jmm- pragmatics/ •Memory Barriers and JVM Concurrency: http://www.infoq.com/articles/memory_barriers_jvm_concurrency •JSR 133 (FAQ): http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html •CPU cache flushing fallacy: http://mechanical- sympathy.blogspot.fr/2013/02/cpu-cache-flushing-fallacy.html •atomic<> Weapons: http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond- 2012-Herb-Sutter-atomic-Weapons-1-of-2
  51. 51. @jpbempel#LockFree @YourTwitterHandle@YourTwitterHandle@jpbempel#LockFree Q & A Ullink Architecte Performance @jpbempel http://jpbempel.blogspot.com jpbempel@ullink.com

×