Réactif, parallèle, asynchrone. Pourquoi!

563 views
488 views

Published on

My conference at USI 2014 (http://www.usievents.com/en). Explaining how we arrive to reactive programming, why we should care and what to do about it.

In French

Published in: Software
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
563
On SlideShare
0
From Embeds
0
Number of Embeds
13
Actions
Shares
0
Downloads
1
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • http://en.wikipedia.org/wiki/Time-sharing
    http://en.wikipedia.org/wiki/Unix
    http://en.wikipedia.org/wiki/CICS
    http://en.wikipedia.org/wiki/Reactor_pattern
    http://en.wikipedia.org/wiki/Computer_multitasking
    http://en.wikipedia.org/wiki/Preemption_(computing)
  • Aujourd’hui je vais vous faire parcourir l’histoire de l’informatique pour nous permettre de mieux comprendre les nouveaux paradigmes de programmation que nous voyons émerger depuis quelques années.
  • Ce qui est étonnant c’est que certains concepts proviennent du fin fond de l’aube de l’informatique, sont tombés partiellement dans l’oublie.

    Loi d’Amdahl

    Par exemple, …
  • Mais pourquoi maintenant, pourquoi rien pendant 40 ans et soudain on se découvre plein de nouveaux besoins
  • Presque tous les développements d’aujourd’hui sont sur x86

    Au début du x86, tout était simple
  • On lance un processus à la fois, il prend des données en entrées et en fait quelquechose
  • La vie était belle et simple
  • Évidemment, hors du x86, on utilisait depuis déjà 20 ans des paradigmes plus compliqués

    Ken Thompson et Dennis Ritchie

    Multiprogramming:
    Un programme tourne et on passe au suivant lors d’un IO

    Cooperative multitasking (CICS par exemple):
    Un programme tourne et laisse la main des fois pour permettre aux autres de s’exécuter. S’il ne la laisse pas, personne ne peut lui enlever
    Windows 3.1
  • Le premier OS maintenant améliorant la situation fut Windows 95 et Windows NT 3.1.

    Il faisait du preemptive multitasking.

    Évidemment, les systèmes Unix utilisaient eux aussi ce système sur une architecture SMP
  • Par exemple, cgi-bin. Un processus reçoit un appel HTTP et fork un processus correspondant à l’URL en passant des variables.

    Le problème c’est qu’il y a évidemment beaucoup d’overhead à faire des fork. Donc on a eu une autre idée
  • Pourquoi ne pas faire des threads. Le thread, c’est plein de traitements parallèles mais au sein d’un même processus et partagent la même mémoire. Il n’est plus nécessaire de créer un processus complet, uniquement une nouvelle stack d’appel.

    Le problème c’est que des OS comme Solaris n’implémentait pas de threads natifs. Donc, par exemple, lors de la sortie de Java, la JVM sur Solaris utilisait un concept de green threads. C’est la JVM qui gérait le time sharing et non l’OS. Évidemment, ça causait des problèmes. Par exemple, il fallait traiter les IO de façon asynchrone pour ne pas gelé un processus.
  • Donc sommes donc rapidement passé au native threads.

    C’est l’OS qui s’occupe du time sharing des threads. Cela ralentit la synchronisation et la création mais améliore sensiblement la gestion des IO et le context switching.
  • On a donc plusieurs processus sur lesquels l’OS distribue les threads des différents processus en tentant de maximiser l’utilisation CPU.

    Par exemple, si un thread est sur un I/O, pas de soucis, un autre thread prend le relai.

    Il suffit d’ajouter des threads pour avoir une scalabilité infinie. Pour le reste, la loi de Moore devrait nous assurer que dans le futur, l’augmentation des besoins CPUs sera couverts

    SMP = Symmetric multiprocessing
  • Le nombre de transistors double tous les 2 ans et par extension la puissance des ordinateurs
  • D’ailleurs, l’architecture de Java en général comptait beaucoup sur la loi de Moore.

    Plusieurs décisions étaient sciemment lentes pour couvrir un maximum de besoins en se disant que rapidement, cette lenteur se fondrait dans la loi de Moore
  • Et c’est là que le couperet est tombé.

    On a atteint les limites de fréquences possibles pour un ordinateur. Et dans un ordinateur, ce n’est pas vraiment le nombre de transistors qui est important, c’est la fréquence. La fréquence donne la vitesse de passage des portes. Si on ne peut pas augmenter la vitesse de passage des portes, ça ne sert à rien d’ajouter des portes.
  • Donc, les fondeurs n’ont pas trop eu le choix de changer de stratégie.

    Le nombre de transistor continue d’augmenter mais plus la fréquence. À la place, les transistors sont déplacés sur plusieurs cœurs.
  • D’où l’apparition du Dual Core d’Intel en 2007

    Le traitement parallèle n’était plus limité aux serveurs, il était maintenant pour tous
  • À noter, ce n’est pas une problème de scalabilité.

    Par exemple, pour un serveur web, chaque requête est traitée par un thread qui lui-même est assigné à un CPU.

    Donc, il suffit d’ajouter des CPUs, peu importe leurs puissance. Mais ça n’améliore pas mon temps de réponse.

    Si on zoom, un requête c’est ça
  • Évidemment, je simplifie un peu. Les fabricants trouvent des « trucs ». Ils augmentent le cache, les algorithmes de prédiction.

    Mais ce n’est que du patch. Rien de vraiment révolutionnaire
  • Une deuxième fois pour être bien sûr que c’est intégré.

    On a surfé plus de 30 ans sur la vague de la loi de Moore et c’est maintenant terminé.

    Donc, quand les développeurs s’en sont rendus compte, ils se sont mis à la recherche de solution
  • Et ça tombe bien, la passé est plein de solutions

    Mais tombé, jetons un coup d’œil sur ce qu’est vraiment une requête
  • Un requête vu à la loupe ça ressemble à ça.

    On remarque deux choses:
    1- On attend sur des IOs
    2- La fréquence étant désormais constante, il n’y a pas de raison pour que les opérations CPU d’une requête soient plus rapides dans le futur
  • Et si on zoom encore, on voit la chose suivante.

    En pratique, l’opération 1 effectue un IO, l’OS réquisitionne le CPU pour le donner à quelqu’un d’autre, l’IO termine et éventuellement, l’OS redonne la main au CPU.

    Deux autres constatations:
    1- Le context switching a un coût CPU
    2- Le temps de récupération après IO a un coût
  • Et si on zoom encore, on voit la chose suivante.

    En pratique, l’opération 1 effectue un IO, l’OS réquisitionne le CPU pour le donner à quelqu’un d’autre, l’IO termine et éventuellement, l’OS redonne la main au CPU.

    Deux autres constatations:
    1- Le context switching a un coût CPU
    2- Le temps de récupération après IO a un coût
  • Il est assez facile de réaliser que plus on a de threads, plus on a d’overhead dû au context switching.

    Il y a donc une limite
  • On voit maintenant un peu mieux comment ça marche,

    Il nous faut maintenant des solutions, des outils pour améliorer nos performances
  • Les différentes opérations d’une requête serveur sont traités en parallèles pour améliorer les temps de réponse

    Évidemment, ça ne marche que si le serveur n’est pas trop chargé. Si le CPU d’à côté est en train de traiter la requête de quelqu’un d’autre, il n’aura pas le temps de traiter la notre.
  • Non-blocking IO ou asynchronous IO

    Au lieu d’attendre bêtement les fins d’un IO, on fait d’autre chose en attendant d’être notifié de la fin de l’IO

    Évidemment, pour arriver à faire ça, on doit avoir la collaboration de la libraire effectuant l’IO et de l’OS.
  • On utilise 1 thread par CPU. Chaque thread effectue du traitement de tâches à partir des tâches disponibles dans une file de tâche
  • La gestion du multithreading et le partage de données augmente trop la complexité
  • D’autres, moins extrême n’étaient pas contre le multithreading mais contre la mutabilité des données

    Car on peut partager des données immutables sans danger

    Et les ingénieurs, quand ils ont des problèmes, ils ont des solutions
  • Et évidemment, quand il y a un problème, il y a toujours un outil disponible pour le résoudre

    PPR: Stratégie différente, intégration dans les OS, langages, frameworks, etc
  • Aussi dans les navigateurs
  • Un exemple plus raisonnable
  • Un exemple plus raisonnable

    Slide sur le fait que les langages évoluent
  • En conclusion
  • One-liner
  • On parle ici d’immutabilité des données en mémoire. Pas des données persistées
  • Si vous voulez améliorer vos performances ou diminuer vos coûts d’infrastructure, c’est la seule solution.

    Par contre, ça reste relativement compliqué, les technologies et outils ne sont pas encore tous prêts.

    Mais ça vaut quand même la peine de tester sur un petit projet avec des problématiques de performance.
  • C’est ce qui a amené le concept de programmation réactive.

    C’est une énorme buzzword qui constitue en fait un pieu vieux.

    Il consiste à appliquer toutes les nouvelles solutions provenant du passer afin d’atteindre les objectifs suivants
  • Réactive:
    1- Tout en async (orienté évènement)
    2- Pas de points de contention (immutable)
    3- Un seul thread par hard-thread (moins d’overhead)
    4- Scalabilité horizontale infinie

    C’est donc bien évidemment un gros buzzword mais derrière lequel se cachent de vraies valeurs à respecter pour obtenir de meilleures applications.

    De plus en plus de devices connectés et donc de sollicitation serveur. La granularité des requêtes diminues.

    - Petits applications bureautiques: Ne pas faire
    - Propension à augmenter en puissance: Go, avec aide et outillage
  • Réactif, parallèle, asynchrone. Pourquoi!

    1. 1. www.usievents.com #USI2014 Réactif, Parallèle, Asynchrone Pourquoi! Henri Tremblay
    2. 2. www.usievents.com #USI2014 Henri Tremblay OCTO Technology Architecte Senior Responsable R&D Spécialiste Performance EasyMock lead developer Objenesis lead developer
    3. 3. www.usievents.com #USI2014 Philippe Prados OCTO Technology Responsable Pôle Réactif François-Xavier Bonnet OCTO Technology Architecte Senior Pôle Réactif Avec l’aide de
    4. 4. www.usievents.com #USI2014
    5. 5. www.usievents.com #USI2014 Un peu d’histoire Lisp (1958) Clojure (2007) Parallel.forEach (2010) Async IO (2006) Loi d’Amdahl (1967) Real-time (1965) Reactive (2012) 43 ans 49 ans 47 ans
    6. 6. www.usievents.com #USI2014
    7. 7. www.usievents.com #USI2014 x86
    8. 8. www.usievents.com #USI2014 ProcessusIN OUT x86
    9. 9. www.usievents.com #USI2014
    10. 10. www.usievents.com #USI2014 Cooperative Multitasking UNIX Mainframe Multiprogramming Je n’ai plus besoin du CPU. Je le tend à qui veut bien Je le prend. MerciProcessus 1 Processus 2 Je fais un IO, à qui le tour? Moi! Processus 1 Processus 2
    11. 11. www.usievents.com #USI2014 Windows 95 Preemptive Multitasking Processus 1, c’est à toi Chef oui chef Processus 1 Processus 2 Temps écoulé, processus 2 Aye aye sir Un IO, je t’enlève la main
    12. 12. www.usievents.com #USI2014 cgi-bin Requête HTTPD Processus Fork
    13. 13. www.usievents.com #USI2014 Java Green threads
    14. 14. www.usievents.com #USI2014 Native threads
    15. 15. www.usievents.com #USI2014 Résumé Architecture SMP OS Processus Thread
    16. 16. www.usievents.com #USI2014 Loi de Moore
    17. 17. www.usievents.com #USI2014 Synchronisé par défaut GC généraliste IO synchrone Threads créés au besoin UTF-16 «Un jour les ordinateurs seront assez puissants »
    18. 18. www.usievents.com #USI2014 Herb Sutter (2005)
    19. 19. www.usievents.com #USI2014 Loi de Moore
    20. 20. www.usievents.com #USI2014 Dual core (2007)
    21. 21. www.usievents.com #USI2014 Requêtes
    22. 22. www.usievents.com #USI2014 Le temps de réponse ne peut plus s’améliorer uniquement par le matériel
    23. 23. www.usievents.com #USI2014 Le temps de réponse ne peut plus s’améliorer uniquement par le matériel
    24. 24. www.usievents.com #USI2014
    25. 25. www.usievents.com #USI2014 Une requête Requête Op 1 Op 2 Op n… Réponse IO IO
    26. 26. www.usievents.com #USI2014 Une requête Op 1 IO Op 2 Context switching
    27. 27. www.usievents.com #USI2014 2 threads sur 1 CPU Thread 0 Thread 1 Overhead 1 seconde
    28. 28. www.usievents.com #USI2014 10 threads sur 1 CPU T0 Overheads T1 T2 T3 T4 T5 T6 T7 T8 T9 1 seconde
    29. 29. www.usievents.com #USI2014 Attente d’entrée-sortie Attente de récupération du CPU Overhead de context switching Perte de temps
    30. 30. www.usievents.com #USI2014
    31. 31. www.usievents.com #USI2014 Solution #1: Parallel processing Op 1 Op 2 Op 3
    32. 32. www.usievents.com #USI2014 Solution #2: NIO Op 1 IO Op 2Op 3
    33. 33. www.usievents.com #USI2014 Solution #3: 1 thread par CPU Op 1 Op 2 Op 3
    34. 34. www.usievents.com #USI2014 Complexité
    35. 35. www.usievents.com #USI2014 Oh my God! (1/2)
    36. 36. www.usievents.com #USI2014 Oh my God! (2/2)
    37. 37. www.usievents.com #USI2014
    38. 38. www.usievents.com #USI2014 En JavaScript Pas de multithreading Scalabilité en instanciant plusieurs processus Approche asynchrone NodeJS
    39. 39. www.usievents.com #USI2014 Implémentation de LISP du JVM Prône la programmation fonctionnelle et l’immutabilité Facilite le partage des données en mémoire via un STM Clojure
    40. 40. www.usievents.com #USI2014 Traitements multi-threadés isolés l’un de l’autre Partage explicite des données Utilisable facilement en Groovy et Java Vert.X
    41. 41. www.usievents.com #USI2014 Netty: Gestionnaire d’IO asynchrone sur JVM Play: Fullstack reactive Rx: Framework reactive sous .Net Java 8: Évaluation paresseuse Lambda Parallélisme Haskell, Erlang, Go, … Coroutine, Continuation, Promise Pilotes de DB asynchrones Autres
    42. 42. www.usievents.com #USI2014 Conclusion
    43. 43. www.usievents.com #USI2014 NIO Avantage Améliore sensiblement la scalabilité d’un serveur d’application Désavantage Doit être supporté par les frameworks Recommandation: Allez-y Je vais faire un IO, rappelle-moi quand c’est fini. En attendant je fais d’autre chose Processus 1 D’accord
    44. 44. www.usievents.com #USI2014 Parallèle Avantage Réduit les temps de réponse d’un système peu sollicité Maximise l’utilisation CPU Désavantage Algorithmie plus complexe Recommandation: Allez-y… au besoin Yep! Les gars, voici chacun un peu de boulot. Dites-moi quand c’est fini. Je vous attend Processus 1
    45. 45. www.usievents.com #USI2014 Fonctionnel Avantage Implicitement thread-safe Diminue la quantité de code Facilement parallélisable Évaluation paresseuse Désavantage Rapidement illisible si surutilisé Lecture du code plus complexe pour les non initiés Recommandation: Allez-y. Avec retenu Bien sûr Tu pourrais effectuer cette opération sur toutes ces données et me donner le résultat? Méthode 1 Méthode 2
    46. 46. www.usievents.com #USI2014 Immutable Avantage Élimine les risques de contention Facilite les traitements parallèles Désavantage Augmente le travail du GC Les structures de données doivent être compatible Recommandation: Allez-y, sans vous forcer Tout de suite Voici des données. Tu m’en donnes une copie en appliquant cette transformation? Méthode 1 Méthode 2
    47. 47. www.usievents.com #USI2014 Asynchrone Avantage Réduit les temps de réponse Meilleure exploitation des CPUs Désavantage Code plus complexe si utilisé extensivement Mais ça s’améliore par l’évolution des langages Recommandation: Allez-y en opportuniste Yep! Hop, toi fais ça, et hop toi fais ça. Dites-moi quand c’est fini Processus 1
    48. 48. www.usievents.com #USI2014
    49. 49. www.usievents.com #USI2014 ReactiveScalable Resilient Event Driven Responsive React to event React to failure React to users React to load
    50. 50. www.usievents.com #USI2014 http://perfug.github.io/ +Henri Tremblay @henri_tremblay htremblay@octo.com Questions?

    ×