17 novembre 2010

Performance Anxiety

Joshua Bloch fait salle ultra-comble, comme Brian Goetz il y a une heure que je n'ai pas pu suivre. Les allées et les escaliers sont pris d'assaut, le couloir reste encombré, n'imaginez même pas accéder à  la salle (je ne suis pas complètement sur que ce soit conforme aux règles de sécurité pour la salle d'ailleurs). Dur pour les speakers qui sont programmés au même moment dans l'une des 5 autres salles. Sujet du jour - les performances :D

En attendant que la conf démarre (parce qu'il ne suffit pas d'arriver 10 minutes à l'avance, je suis assis sur les marches et je ne suis pas le moins bien lotti) un détail sur Devoxx pour ceux qui voudraient venir l'an prochain : Devoxx c'est 3000 personnes et beaucoup de français. On peut donc y rencontrer plein de gens biens, en plus d'assister à des confs passionnantes, à condition de bien gérer son emploi du temps. L'effet de bord c'est qu'on se retrouve convié à des BOF le soir et/ou à des repas de JUG-leaders, Opensource-man, Truc-community. Ce soir je vais devoir me cloner ;)

Joshua est sur les starting blocs et commence avant l'enregistrement, ils faut donc l'arrêter déjà lancé dans son discours - comme quoi les problèmes de performance ne sont pas limités à l'informatique :P Bon, ça suffit pour les crétineries, soyons sérieux deux minutes.

Parlons donc performances et optimisation, avec un disclaimer "Premature Optimization is Evil" ...

Avec l'augmentation de l'abstraction et la programmation devenue une discipline empirique, on ne peut plus que mesurer les performance et plus les estimer. librairies, langage, VM ou processeurs sont de plus en plus complexes et abstrait, et introduisent une dimension d'imprévisibilité dans nos estimations de performance. Que ceux qui peuvent dire qui d'un AND conditionnel (&&) et d'un AND logique (&) est le plus rapide lèvent la main ;) La prédiction de branchement dans nos processeurs fausse notre interprétation naïve du problème. La réponse est ... ça dépend !

La performance de lecture d'un attribut dans un objet ? ça dépend ! Est-il volatile ? Sur quel processeur ? Est-il un attribut d'une classe imbriquée - dans ce cas, c'est un appel de méthode, sauf si le compilo l'à inliné. Ca dépend, il faut mesurer !

Un bench simpliste montre déjà l'effet du premier lancement par rapport à la répétition : le warm-up de la JVM et la stabilisation de ses optimisations. Pas de grosse surprise jusqu'ici. Cependant, après plusieurs tirs (même si Joshua n'arrive pas de le montrer sur sa démo) les résultats peuvent être très différents sur un autre tir. Il est donc très difficile de comparer des résultats, et donc de voir les effets de changements dans le code.

La complexité de notre stack matérielle et logicielle nous oblige à renoncer à la prédictibilité. Rien qu'en analysant les possibilités d'inlining que la VM peut appliquer à un fragment de code simpliste, la combinatoire donne des résultats très variables. Or le "Compilation Planing" de la JVM Just-In-Time est un processus en tâche de fond, non-déterministe lors de notre mesure :'( Les mêmes dérives sont constatées sur du code C/C++ (la VM n'explique donc pas tout) ni même sur du code assembleur. L'outillage (comme un profiler) peut d'ailleurs fausser la mesure au point d'invalider toute l'analyse : 6 profilers testés sur un même code on détecté des "hot-spots" différents :'(

Notre seule solution : une approche statistique ! En multipliant les runs, en groupant les données et en effectuant une analyse statistique on obtient une meilleure vision de nos performances, et la moyenne n'est pas le seul résultat à retenir : l'étalement des mesures peut être impressionnant.

En tant que développeur d'application nous ne pouvons donc que reposer sur des constructions validées et stables en conservant un niveau d'abstraction maximal. En tant que développeur de librairie, nous devons étudier soigneusement les recommandations des spécialistes pour éviter les constructions hasardeuses (classes imbriquées de visibilité private par exemple) qui ajoutent du flou dans le traitement du compilateur, et donc dégradent d'autant la prédictibilité. Comment les connaître ? Demandez à Doug Lea - ou achetez son livre ;)

L'art du benchmark est très délicat, largement détaillé par Cliff Click (JavaOne 2009). Caliper est un framework qui peut aider à en construire avec un bon niveau de fiabilité. Quoi qu'il en soit, Joshua conclut que nous vivons une époque passionnante dans laquelle le prédictif se perd et où nous devons apprendre à mesurer notre travail avec de nombreuses précautions.

1 commentaires:

François OSTYN a dit…

Très bon article !
Note: N'abuse pas trop des bonnes choses (la bière)...