71 votes

Le benchmarking par chronomètre est-il acceptable ?

Est-ce que quelqu'un utilise parfois le benchmarking par chronomètre, ou faut-il toujours utiliser un outil de performance ? Existe-t-il de bons outils gratuits pour Java ? Quels outils utilisez-vous ?

Pour clarifier mes préoccupations, l'évaluation comparative des chronomètres est sujette à des erreurs dues à la programmation du système d'exploitation. Lors d'une exécution donnée de votre programme, le système d'exploitation peut programmer un autre processus (ou plusieurs) au milieu de la fonction que vous chronométrez. En Java, les choses sont encore un peu pires si vous essayez de chronométrer une application threadée, car le planificateur de la JVM ajoute encore un peu plus d'aléatoire dans le mélange.

Comment abordez-vous l'ordonnancement du système d'exploitation lors de l'analyse comparative ?

48voto

Lawrence Dol Points 27976

L'évaluation comparative des chronomètres est bien, à condition de mesurer assez de itérations pour être significatif. En général, je demande un temps total écoulé d'un certain nombre de secondes à un chiffre. Sinon, vos résultats seront facilement faussés par la programmation et d'autres interruptions du processus par le système d'exploitation.

Pour cela, j'utilise un petit ensemble de méthodes statiques que j'ai construit il y a longtemps, et qui sont basées sur System.currentTimeMillis() .

Pour le travail de profilage, j'ai utilisé jProfiler depuis un certain nombre d'années et je le trouve très bon. J'ai récemment examiné YourKit qui semble génial d'après le site Web, mais je ne l'ai pas du tout utilisé, personnellement.

Pour répondre à la question sur l'ordonnancement des interruptions, je trouve que la répétition des exécutions jusqu'à ce que la cohérence soit atteinte/observée fonctionne en pratique pour éliminer les résultats anormaux de l'ordonnancement des processus. Je trouve également que l'ordonnancement des threads n'a pas d'impact pratique pour les exécutions entre 5 et 30 secondes. Enfin, après avoir dépassé le seuil de quelques secondes, l'ordonnancement a, d'après mon expérience, un impact négligeable sur les résultats - je trouve qu'une exécution de 5 secondes donne systématiquement la même moyenne qu'une exécution de 5 minutes en termes de temps/itération.

Vous pouvez également envisager de pré-exécuter le code testé environ 10 000 fois pour "chauffer" le JIT, en fonction du nombre de fois que vous pensez que le code testé sera exécuté au fil du temps dans la vie réelle.

6voto

cliff.meyers Points 10394

C'est tout à fait valable tant que vous mesurez des intervalles de temps suffisamment grands. J'exécuterais 20 à 30 passages de ce que vous avez l'intention de tester de façon à ce que le temps total écoulé soit supérieur à 1 seconde. J'ai remarqué que les calculs de temps basés sur System.currentTimeMillis() ont tendance à être soit 0ms soit ~30ms ; je ne pense pas que vous puissiez obtenir quelque chose de plus précis que cela. Vous pouvez essayer System.nanoTime() si vous avez vraiment besoin de mesurer un petit intervalle de temps :

5voto

Scott Wisniewski Points 14420

Un profileur vous donne des informations plus détaillées, qui peuvent vous aider à diagnostiquer et à résoudre les problèmes de performance.

En termes de mesure réelle, le temps du chronomètre est ce que les utilisateurs remarquent, donc si vous voulez valider que les choses sont dans des limites acceptables, le temps du chronomètre est parfait.

Cependant, lorsque vous voulez vraiment résoudre des problèmes, un profileur peut être très utile.

4voto

Peter Lawrey Points 229686

Vous devez tester un nombre réaliste d'itérations car vous obtiendrez des réponses différentes selon la façon dont vous testez le timing. Si vous n'effectuez une opération qu'une seule fois, il peut être trompeur de prendre la moyenne de nombreuses itérations. Si vous voulez savoir le temps qu'il faut après que la JVM se soit réchauffée, vous pouvez exécuter de nombreuses itérations (par exemple 10 000) qui ne sont pas incluses dans le chronométrage.

Je vous suggère également d'utiliser System.nanoTime() car c'est beaucoup plus précis. Si le temps de votre test est d'environ 10 micro-secondes ou moins, vous ne voulez pas l'appeler trop souvent ou cela peut changer votre résultat. (Par exemple, si je teste pendant 5 secondes et que je veux savoir quand c'est terminé, je n'obtiendrai le nanoTime que toutes les 1000 itérations, si je sais qu'une itération est très rapide).

2voto

Daniel Paull Points 4225

Les profileurs peuvent gêner les chronométrages. J'utiliserais donc une combinaison de chronométrage pour identifier les problèmes de performances globales, puis j'utiliserais le profileur pour déterminer où le temps est passé. Répétez le processus si nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X