Java VisualVM geben bizarre Ergebnisse für die CPU-profiling - Hat sonst noch jemand dieses?
Ich geschrieben habe, diese kleine (und Brutal ineffizient) Klasse und wollte das Profil mit Hilfe der Java VisualVM.
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
br.readLine();
int n = Integer.parseInt(args[0]);
int fib = fib(n);
System.out.println(fib);
}
private static int fib(int n) {
if (n < 2) {
return n;
}
return fib(n-1)+fib(n-2);
}
}
Die Ergebnisse sind Bizarr. Die Ergebnisse sind völlig dominiert durch Aufrufe ConnectionHandler.run().
(98.2%) Sonne.rmi.transport.tcp.TCPTransport$ConnectionHandler.run()
(1.7%) java.lang.Thread.join(long)
(0%) java.lang.String.equals(Object)
etc...
Gibt es wahrscheinlich rund hundert Methoden profiliert und nicht einer von Ihnen ist fib(int)!
Es ist unvorstellbar, dass mein Programm ist tatsächlich verbringen alle seine Zeit in diese Methoden. Sie zu sein scheinen die profiler-Verbindung zu meinem jvm und Ihr Ding macht.
Was mache ich falsch?
Bearbeitet für Klarheit: Wenn Sie übergeben, 45 für die n-diese Anwendung läuft für die 20 gut profilierten Sekunden. Das Programm, das ich war-profiling-ursprünglich (nicht ein fibonacci-Rechner) Heringe alle vier Kerne meiner cpu bei 100% und ich war dabei profiling läuft dauert bis zu 5 Minuten. Diese hatte die gleichen Ergebnisse und Methoden aus meiner Anwendung nicht erscheinen, hoch oben auf der hot spot Methode-Liste.
Variiert von run zu run, aber ConnectionHandler.run() ist immer an der Spitze und in der Regel Konten für ~99% des Profils Zeit.
Zweiter Edit: ich habe versucht mit dem sampler und ich bin jetzt immer Ergebnisse, die im Einklang stehen mit dem, was JProfiler produziert. Der Nachteil dabei ist, dass ich nicht bekommen, die stack-trace-Informationen, mit profiling. Aber für meine unmittelbaren Bedürfnisse dieser ist ausgezeichnet.
Etwas, das ich entdeckt, während rund um das Spiel ist, dass VisualVM zählt Wand-Uhr Zeit für Methodenaufrufe während der Profilerstellung werden.
In meinem speziellen Fall meine Anwendung hat einen main-thread startet die worker-threads und sofort blockiert warten auf eine Nachricht auf einer queue.
Dies bedeutet, dass die blockierende Methode erscheinen wird, nehmen fast die ganze Zeit auf dem profiler-trotz der Tatsache, dass es nicht die Methode, die frisst meine CPU.
Ich würde erwarten, dass das gleiche gilt von der Sonne.rmi.transport.tcp.TCPTransport$ConnectionHandler.die run () - Methode, die macht seinen job gut - aber wenn es endet, es wird eines der längsten Verfahren in meinem Antrag - wiederholt.
- Verwenden Sie CPU-sampler oder das instrumentierte profiler? Was sind die Einstellungen? Es scheint, dass Sie entweder mit dem CPU-sampler (könnte Verzerrungen der Ergebnisse durch die Probenahme Granularität etc.) oder Ihre profiling-Einstellungen sind nicht richtig eingestellt.
- Das ist die Art von nussig, was Sie bekommen können, mit einigen Profiler. Während Sie versuchen, das herauszufinden, versuchen Sie einfach diese Methode.
- Sieht aus, wie Sie lief in das gleiche problem wie Glunk: stackoverflow.com/questions/3243100/... es scheint wie ein jvisualvm Methode instrumentation Mangel, wo, wenn Sie anrufen wenn Sie von der main es kann nicht neu definiert werden.
- Danke für den Hinweis aus dem sampling-Modus.
- können Sie mir sagen, welche Einstellungen gut funktioniert für Sie?
- Ich kam nie richtig funktionieren, fürchte ich. Ich benutze jprofiler, wenn ich eine bekommen kann. Aus der Erinnerung ich habe nie zufriedenstellende Ergebnisse aus visualjvm auf den code, den ich war mit ihm auf. Kann es sich verbessert haben, da dann, das war vor langer Zeit.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass das undenkbar überhaupt. Sie haben eine Anwendung, bei der "Zuladung" ist ziemlich winzig (aber das hängt natürlich von dem Wert der
n
), und Sie haben zu akzeptieren, dass der zusätzliche Aufwand (für die Verbindung der profiler und verschieben Sie alle Informationen über dazu) Sumpf, der Nutzlast.Dies ist nicht die Art von Anwendung ich wäre profiling in den ersten Platz, da es ziemlich offensichtlich, dass die große Menge an Zeit ausgegeben würde, in
fib
sowieso (für nicht-triviale Werten
), die Markierung, die als ein offensichtliches Ziel für die Optimierung.Ich würde eher dazu neigen, verwenden Sie die profiler-weitere wesentliche Anwendungen, bei denen:
Wenn Sie wirklich wollen, zu testen , dass - code, werden Sie wahrscheinlich benötigen, um bump up Ihre Wirkung, indem Sie (zum Beispiel) zu ersetzen:
mit:
Werde ich Ihnen sagen eine Sache zu beachten, obwohl. Ich kenne nicht die Interna einer bestimmten JVM, aber mit einer rekursiven Methode, bei der die Reduktion des Arguments ist langsam, ist in der Regel eine schlechte Idee, das führt zu stack-Speicher erschöpft ziemlich schnell.
Damit meine ich eine binäre Suche ist ein guter Kandidat, da es entfernt die Hälfte der verbleibenden Suchraum mit jeder rekursionsebene (so dass ein Suchraum mit einer Milliarde Artikel ist nur 30 Ebenen).
Auf der anderen Seite, mit Rekursion für Fibonacci-Sequenz auf die Anzahl 1,000,000,000 würde etwa eine Milliarde Ebenen und die meisten stacks würde haben eine harte Zeit mit diesem.
Tail end-Rekursion-Optimierung vermeiden kann, dass problem aber Sie müssen vorsichtig sein, im Falle, dass die Optimierung nicht getan.
jvisualvm profiling wahrscheinlich webt-bytecode in Klassen, wie Sie geladen werden. Da das Programm nur eine Klasse, und es ist bereits durch die Zeit initialisiert jvisualvm kommt auf die Szene, ich nehme an es nicht instrumentiert.
Bewegen Sie Ihre fib-Methode in eine andere Klasse und versuchen, die Profilerstellung wieder. Man könnte hinzufügen, eine jvm-option-verbose:class" zu überprüfen, dass die Klasse nicht geladen, bevor Sie Sie aktivieren Sie cpu-profiling in der jvisualvm.
Edit: Danke JB für den Kommentar. Vergessen, meine zum laden von Klassen Quatsch. Meine intuition ist, dass die fib-Methode ist auch eng gekoppelt an die main-Methode, so ist es effektiv bytecode, der gerade ausgeführt wird.
Basierend auf Ron ' s Antwort war in der Lage, um das Ergebnis zu verbessern, durch beenden der JVM direkt nach dem start, dann aktiviert den profiler, und schließlich nach, dass weiterhin die excetion (durch drücken der EINGABETASTE). Es ist roh.
Meine Vermutung ist, dass Sie auf der Durchreise sind ein zu kleiner Wert für fib, und das Programm einfach nicht lang genug laufen um sich zu registrieren. Um aussagekräftige Daten für fast alles, wenn profiling (oder bench-marking) Sie müssen in der Regel einer verstrichenen Zeit von mindestens ein paar Sekunden.