Comment puis-je écrire un bon micro-benchmark en Java?
Comment écrivez-vous (et exécuter) un bon micro-benchmark en Java?
Je suis à la recherche pour certains des exemples de code et des commentaires qui illustrent les différentes choses à penser.
Exemple: si l'indice de référence de mesurer le temps/l'itération ou d'itérations/temps, et pourquoi?
Connexes: Est-chronomètre d'analyse comparative acceptable?
Voir [cette question][1] à partir d'un il ya quelques minutes pour quelques infos. edit: désolé, ce n'est pas censé être une réponse. Je devrais avoir posté un commentaire. [1]: stackoverflow.com/questions/503877/...
Il était une fois la planification pour consulter l'affiche de cette question à une question comme ça que j'ai noté que cette question n'existe pas. Si elle est ici, j'espère qu'il va assembler quelques bons conseils au fil du temps.
Java 9 pourrait fournir certaines fonctionnalités de micro-analyse comparative: openjdk.java.net/jeps/230
Je pense que c'JEP, vise à ajouter de certains micro de référence pour le JDK code, mais je ne pense pas que jmh seront inclus dans le JDK...
Probablement double: Comment puis-je le temps d'une méthode d'exécution en Java?
Il était une fois la planification pour consulter l'affiche de cette question à une question comme ça que j'ai noté que cette question n'existe pas. Si elle est ici, j'espère qu'il va assembler quelques bons conseils au fil du temps.
Java 9 pourrait fournir certaines fonctionnalités de micro-analyse comparative: openjdk.java.net/jeps/230
Je pense que c'JEP, vise à ajouter de certains micro de référence pour le JDK code, mais je ne pense pas que jmh seront inclus dans le JDK...
Probablement double: Comment puis-je le temps d'une méthode d'exécution en Java?
OriginalL'auteur John Nilsson | 2009-02-02
Vous devez vous connecter pour publier un commentaire.
Conseils sur l'écriture de micro-benchmarks par les créateurs de Java HotSpot:
Règle 0: Lire un papier de bonne réputation sur les machines virtuelles et les micro-analyse comparative. Une bonne Brian Goetz, 2005. Ne vous attendez pas trop à partir de micro-benchmarks; ils mesurent seulement une gamme limitée de la JVM des caractéristiques de performance.
Règle 1: Toujours inclure une phase d'échauffement qui se déroule votre test noyau tout le chemin à travers, assez pour déclencher toutes les initialisations et les compilations avant de synchronisation de phase(s). (Moins d'itérations est OK sur la phase d'échauffement. La règle de base est de plusieurs dizaines de milliers d'intérieur itérations de boucle.)
Règle 2: Toujours fonctionner avec
-XX:+PrintCompilation
,-verbose:gc
, etc., de sorte que vous pouvez vérifier que le compilateur et d'autres parties de la machine ne sont pas fait inattendu de travail au cours de votre calendrier de phase.La règle 2.1: Imprimer des messages au début et à la fin de la synchronisation et de chauffe phases, de sorte que vous pouvez vérifier qu'il n'y a pas de sortie de la Règle 2 lors de la synchronisation de phase.
Règle 3: Être conscient de la différence entre
-client
et-server
, et OSR et régulièrement des compilations. Le-XX:+PrintCompilation
drapeau rapports OSR compilations avec un signe pour désigner le non-point de départ, par exemple:Trouble$1::run @ 2 (41 bytes)
. Préférez le serveur vers le client, et régulière pour OSR, si vous êtes après de meilleures performances.Règle 4: Être conscient de l'initialisation des effets. Ne pas imprimer pour la première fois au cours de votre synchronisation de phase, car l'impression des charges et initialise les classes. Ne chargez pas de nouvelles classes en dehors de la phase d'échauffement (ou rapport final de phase), à moins que vous sont à l'essai de chargement de classe, en particulier (et dans ce cas de ne charger que les classes de test). Règle 2 est votre première ligne de défense contre de tels effets.
Règle 5: Être conscient de deoptimization et recompilation effets. Ne pas prendre tout chemin de code pour la première fois dans le calendrier de la phase, parce que le compilateur peut indésirable et de recompiler le code, en se basant sur une hypothèse optimiste que le chemin n'était pas destiné à être utilisé à tous. Règle 2 est votre première ligne de défense contre de tels effets.
Règle 6: Utiliser des outils appropriés pour lire le compilateur de l'esprit, et s'attendre à être surpris par le code qu'il produit. Inspecter le code vous-même avant de former des théories sur ce qui rend quelque chose de plus rapide ou plus lent.
Règle 7: Réduire le bruit dans vos mesures. Exécutez votre référence dans un quartier calme de la machine, et l'exécuter plusieurs fois, en rejetant les valeurs aberrantes. Utilisation
-Xbatch
de sérialiser le compilateur avec l'application, et d'étudier la création-XX:CICompilerCount=1
pour empêcher le compilateur de s'exécuter en parallèle avec lui-même. Essayez de votre mieux pour réduire GC frais généraux, ensembleXmx
(assez grand) est égal àXms
et l'utilisationUseEpsilonGC
si elle est disponible.Règle 8: Utiliser une bibliothèque de référence, comme il est probablement plus efficace et a déjà été débuggé pour ce seul but. Comme JMH, Étrier ou Le projet de loi et de Paul Excellente UCSD points de référence pour Java.
Aussi, ne jamais utiliser de Système.currentTimeMillis (), sauf si vous êtes OK avec + ou - 15 ms précision, ce qui est typique sur la plupart des OS + JVM combinaisons. L'Utilisation Du Système.nanoTime() à la place.
Un peu de papier de javaOne: azulsystems.com/events/javaone_2009/session/...
Il convient de noter que
System.nanoTime()
n'est pas garantie pour être plus précis queSystem.currentTimeMillis()
. Il n'est assuré d'être au moins aussi précis. Il est généralement beaucoup plus précis, cependant.La principale raison pour laquelle on doit utiliser
System.nanoTime()
au lieu deSystem.currentTimeMillis()
est que le premier est garanti d'être de plus en plus monotone. En soustrayant les valeurs retournées deuxcurrentTimeMillis
invocations peut effectivement donner des résultats négatifs, peut-être parce que l'heure du système a été ajusté par quelque démon NTP.OriginalL'auteur
Je sais que cette question a été marqué comme réponse mais je voulais mentionner les deux bibliothèques que nous aider à écrire des micro-benchmarks
Étrier de Google
Prise en main des tutoriels
JMH de OpenJDK
Prise en main des tutoriels
jmh est sans doute supérieure à l'Étrier de nos jours, Voir aussi: groups.google.com/forum/#!msg/mécanique-de la sympathie/m4opvy4xq3U/...
OriginalL'auteur Aravind R. Yarram
Choses importantes pour Java de référence sont:
System.gc()
entre les itérations, c'est une bonne idée pour l'exécuter entre les essais, de sorte que chaque test espérons obtenir un "nettoyage" de la mémoire de l'espace pour travailler avec. (Oui,gc()
est plus d'une indication que comme une garantie, mais c'est très probablement qu'il aura vraiment des ordures recueillir dans mon expérience.)Je suis juste dans le processus de création de blogs à propos de la conception d'un référentiel .NET. J'ai un couple de les anciens messages qui peut être en mesure de vous donner quelques idées - tout ne sera le cas, bien sûr, mais certaines d'entre elles peuvent être.
gc
toujours libère de la mémoire inutilisée.Eh bien, le intention, c'est qu'il n'. Tout cela n'est pas strictement garanti, c'est effectivement un très fort soupçon. Va modifier pour être plus clair.
Je ne suis pas d'accord avec l'appel Système.gc(). C'est un indice, c'est tout. Pas encore "ce sera, j'espère, faire quelque chose". Vous ne devriez jamais jamais l'appeler. C'est de la programmation, et non de l'art.
Oui, c'est une allusion - mais c'est celui que j'ai observé à généralement être prises. Donc, si vous n'aimez pas utiliser
System.gc()
, comment vous proposez-vous pour réduire la collecte des ordures dans un test en raison des objets créés dans les tests précédents? Je suis pragmatique et non dogmatique.Je ne sais pas ce que vous entendez par "grand secours". Pouvez-vous expliquer, et de nouveau - avez-vous une proposition pour donner de meilleurs résultats? J'ai fait explicitement dire que ce n'est pas une garantie...
OriginalL'auteur Jon Skeet
jmh est un ajout récent à OpenJDK et a été écrit par certains de rendement des ingénieurs de l'Oracle. Certainement en valeur un regard.
Très intéressant morceaux de l'information enfouie dans l'exemple de tests de commentaires.
Voir aussi:
Pour info, JEP 230: Microbenchmark Suite est une OpenJDK proposition Java Microbenchmark Harnais (JMH) projet. Ne pas faire la coupe pour Java 9 mais peut être ajouté plus tard.
OriginalL'auteur assylias
Il dépend ce vous êtes en train de tester.
Si vous êtes intéressé par latence, utiliser le temps/l'itération et si vous êtes intéressé par débit, l'utilisation d'itérations/heure.
OriginalL'auteur Peter Lawrey
Assurez-vous que vous en quelque sorte l'utilisation des résultats qui sont calculés en comparées code. Sinon, votre code peut être optimisé à l'écart.
OriginalL'auteur Peter Štibraný
Si vous essayez de comparer deux algorithmes, faire au moins deux points de référence pour chaque, en alternant l'ordre. c'est à dire:
J'ai trouvé quelques différences notables (de 5 à 10% parfois) dans l'exécution d'un même algorithme dans différents passe..
Aussi, assurez-vous que n est très grande, de sorte que la durée d'exécution de chaque boucle est au moins 10 secondes. Le plus d'itérations, la plus importante dans votre temps de référence et le plus fiable des données.
OriginalL'auteur Kip
Il y a beaucoup de pièges possibles pour l'écriture de micro-benchmarks en Java.
D'abord: Vous avez à calculer avec toutes sortes d'événements qui prennent du temps plus ou moins aléatoire: la collecte des Ordures, la mise en cache des effets (des OS pour les fichiers et de CPU pour mémoire), IO, etc.
Deuxième: Vous ne pouvez pas faire confiance à la précision de la mesure de temps pour des intervalles très courts.
Troisième: La JVM permet d'optimiser votre code lors de l'exécution. Si différents s'exécute dans la même JVM-instance va devenir de plus en plus vite.
Mes recommandations: Rendre votre référence exécuter quelques secondes, c'est plus fiable qu'un moteur d'exécution de plus de millisecondes. Réchauffer la JVM (signifie que l'indice de référence au moins une fois sans mesure, que la JVM peut exécuter des optimisations). Et exécuter votre référence plusieurs fois (peut-être 5 fois) et prendre la médiane de la valeur. Exécuter tous les micro-benchmark dans une nouvelle JVM-instance (appel pour chaque référence Java) sinon l'optimisation des effets de la JVM peut influencer plus tard l'exécution des tests. N'exécutent pas les choses, qui ne sont pas exécutées dans le chauffe-phase (car cela pourrait déclencher de classe de la charge et de la recompilation).
OriginalL'auteur Mnementh
Il devrait également être a noté qu'il pourrait également être important d'analyser les résultats de la micro de référence lorsque l'on compare les différentes implémentations. Donc un le test de signification doit être fait.
C'est parce que la mise en œuvre
A
pourrait être plus rapide au cours de la plupart des séries de l'indice de référence de mise en œuvreB
. MaisA
pourrait aussi avoir une marge supérieure, de sorte que les performances mesurées bénéficier deA
de ne pas être de quelque importance en comparaison avecB
.Il est donc également important d'écrire et d'exécuter un micro de référence correctement, mais aussi de l'analyser correctement.
OriginalL'auteur SpaceTrucker
http://opt.sourceforge.net/ Java Micro de Référence - tâches de contrôle nécessaires pour déterminer le rendement comparatif des caractéristiques du système informatique sur différentes plates-formes. Peut être utilisé pour guider l'optimisation des décisions et à comparer les différentes implémentations Java.
OriginalL'auteur Yuriy
À ajouter à l'autre d'excellents conseils, je voudrais aussi être conscient des éléments suivants:
Pour certains Processeurs (par exemple Intel Core i5 gamme avec TurboBoost), la température (et le nombre de cœurs utilisés actuellement, ainsi que leur utilisation pour cent) affecte la vitesse de l'horloge. Depuis les Processeurs sont dynamiquement cadencé, ce qui peut affecter vos résultats. Par exemple, si vous avez un seul thread de l'application, la vitesse d'horloge maximale (avec TurboBoost) est plus élevé que pour une application à l'aide de tous les cœurs. Cela peut donc interférer avec des comparaisons de mono et multi-thread de performance sur certains systèmes. Gardez à l'esprit que la température et volatages également affecter la durée de fréquence Turbo est maintenu.
Peut-être plus fondamentalement aspect important que vous avez un contrôle direct sur: assurez-vous que vous êtes en mesure de le droit! Par exemple, si vous utilisez
System.nanoTime()
de référence d'un bit particulier de code, de mettre les appels à l'affectation dans des endroits qui ont du sens pour éviter de mesurer des choses qui ne vous intéresse pas. Par exemple, ne pas faire:Problème est que vous êtes de ne pas obtenir immédiatement de la fin des temps lorsque le code est terminé. Au lieu de cela, essayez ce qui suit:
println
, pas une ligne d'en-tête ou quelque chose, etSystem.nanoTime()
doit être évaluée comme le premier étape dans la construction de la chaîne arg pour cet appel. Il n'y a rien d'un compilateur peut le faire avec la première qu'ils ne peuvent pas le faire avec le second, et aucun des deux n'est même encourageant à faire du travail supplémentaire avant l'enregistrement d'un arrêt du temps.OriginalL'auteur Sina Madani