Conseils sur l'écriture de micro-benchmarks par les créateurs de Java HotSpot :
Règle 0: Lisez un article réputé sur les JVM et le micro-benchmarking. Un bon exemple est Brian Goetz, 2005 . N'attendez pas trop des micro-benchmarks; ils ne mesurent qu'une gamme limitée de caractéristiques de performances JVM.
Règle 1: incluez toujours une phase de préchauffage qui exécute votre noyau de test tout au long, suffisamment pour déclencher toutes les initialisations et compilations avant de chronométrer les phases. (Moins d'itérations est OK sur la phase d'échauffement. La règle de base est de plusieurs dizaines de milliers d'itérations de boucle interne.)
Règle 2: Toujours exécuter avec -XX:+PrintCompilation
, -verbose:gc
etc., de sorte que vous pouvez vérifier que le compilateur et d' autres parties de la machine virtuelle Java ne font pas le travail inattendu pendant votre phase de synchronisation.
Règle 2.1: Imprimez des messages au début et à la fin des phases de chronométrage et d'échauffement, afin de pouvoir vérifier qu'il n'y a pas de sortie de la règle 2 pendant la phase de chronométrage.
Règle 3: Soyez conscient de la différence entre -client
et -server
, et OSR et des compilations régulières. Le -XX:+PrintCompilation
drapeau des rapports compilations OSR avec un arobase pour indiquer le point d'entrée non initial, par exemple: Trouble$1::run @ 2 (41 bytes)
. Préférez le serveur au client et régulier à l'OSR, si vous recherchez les meilleures performances.
Règle 4: Soyez conscient des effets d'initialisation. N'imprimez pas pour la première fois pendant votre phase de synchronisation, car l'impression charge et initialise les classes. Ne chargez pas de nouvelles classes en dehors de la phase de préchauffage (ou de la phase de rapport final), sauf si vous testez le chargement de classe spécifiquement (et dans ce cas, ne chargez que les classes de test). La règle 2 est votre première ligne de défense contre de tels effets.
Règle 5: Soyez conscient des effets de désoptimisation et de recompilation. Ne prenez pas de chemin de code pour la première fois dans la phase de synchronisation, car le compilateur peut ordonner et recompiler le code, sur la base d'une hypothèse optimiste antérieure selon laquelle le chemin n'allait pas du tout être utilisé. La règle 2 est votre première ligne de défense contre de tels effets.
Règle 6: Utilisez les outils appropriés pour lire l'esprit du compilateur et attendez-vous à être surpris par le code qu'il produit. Inspectez le code vous-même avant de former des théories sur ce qui rend quelque chose plus rapide ou plus lent.
Règle 7: Réduisez le bruit dans vos mesures. Exécutez votre référence sur une machine silencieuse et exécutez-la plusieurs fois, en éliminant les valeurs aberrantes. Utilisez -Xbatch
pour sérialiser le compilateur avec l'application et envisagez de définir -XX:CICompilerCount=1
pour empêcher le compilateur de s'exécuter en parallèle avec lui-même. Faites de votre mieux pour réduire les frais généraux du GC, définissez Xmx
(assez grand) égal Xms
et utilisez-le UseEpsilonGC
s'il est disponible.
Règle 8: Utilisez une bibliothèque pour votre référence car elle est probablement plus efficace et a déjà été déboguée à cette seule fin. Tels que JMH , Caliper ou Bill and Paul's Excellent UCSD Benchmarks for Java .