2013-03-11 4 views
8

Ich habe die folgenden jHiccup Ergebnis.jHiccup Analyse addiert sich nicht

jHiccup analysis graph

Offensichtlich gibt es große Spitzen von wenigen Sekunden in der Grafik. Meine App gibt alle 100 ms Protokolle aus. Wenn ich meine Protokolle lese, sehe ich nie so große Pausen. Ich kann auch die Gesamtzeit, in der GC von der JVM-Diagnose ausgegeben überprüfen und es sagt die folgend:

Time:  
2013-03-12 01:09:04 
Used:  
 1,465,483 kbytes 
Committed:  
 2,080,128 kbytes 
Max:  
 2,080,128 kbytes 
GC time:  
     2 minutes on ParNew (4,329 collections) 

8.212 seconds on ConcurrentMarkSweep (72 collections) 

Die Gesamt big-GC Zeit beträgt etwa 8 Sekunden verteilt über 72 getrennte Sammlungen. Alle von ihnen sind unter 200ms pro JVM-Hinweis, um die Pausen zu begrenzen.

Auf der anderen Seite beobachtete ich genau eine Instanz der Netzwerkantwortzeit von 5 Sekunden in meinen unabhängigen Netzwerkprotokollen (wireshark). Das impliziert, dass die Pausen existieren, aber sie sind nicht GC und sie sind keine blockierten Threads oder etwas, das in Profiler- oder Thread-Dumps beobachtet werden kann.

Meine Frage ist, was wäre der beste Weg, dieses Verhalten zu debuggen oder abzustimmen?

Außerdem würde ich gerne verstehen, wie jHiccup die Messung macht. Offensichtlich ist es keine GC-Pausenzeit.

Antwort

24

Freut mich zu sehen, dass Sie jHiccup verwenden, und dass es Realitäts-basierte Schluckauf zu zeigen scheint.

jHiccup beobachtet "Schluckauf", die auch von Anwendungsthreads auf der JVM erkannt werden. Es ist nicht der Grund dafür - nur meldet die Tatsache. Gründe können alles sein, was dazu führt, dass ein Prozess nicht fehlerfrei ausgeführt wird: GC-Pausen sind eine häufige Ursache, aber ein temporäres^Z an der Tastatur oder eines dieser "Live-Migration" -Dinge über virtualisierte Hosts hinweg genau so gut beobachtet. Es gibt eine Vielzahl von möglichen Gründen, einschließlich der Planung von Druck auf der Betriebssystem- oder Hypervisor-Ebene (falls vorhanden), Power-Management-Verrücktheit, Swapping und viele andere. Ich habe gesehen, Linux-Dateisystem Druck und Transparent Huge Page "Hintergrund" Defragmentierung verursachen mehrere Sekunden Schluckauf sowie ...

Ein guter erster Schritt bei der Isolierung der Ursache der Pause ist die Verwendung der Option "-c" in jHiccup: Es wird ein separater Kontrollprozess gestartet (mit ansonsten ungenutzter Arbeitslast). Wenn sowohl Ihre Anwendung als auch der Steuerungsprozess Schluckauf zeigen, die grob in Größe und Zeit korrelieren, wissen Sie, dass Sie nach einem (im Gegensatz zu einem prozesstechnischen) Grund auf Systemebene suchen. Wenn sie nicht korrelieren, werden Sie das Innere Ihrer JVM vermuten - was höchstwahrscheinlich darauf hindeutet, dass Ihre JVM für etwas Großes pausiert hat; entweder GC oder etwas anderes, wie ein Lock-Debiasing oder eine Class-Loading-Derived-Deoptimization, die bei manchen JVMs eine sehr lange (und oft nicht gemeldete) Zeit in Anspruch nehmen kann, wenn Time-to-Safepoint aus irgendeinem Grund lang ist (und weiter Bei den meisten JVM gibt es viele mögliche Ursachen für eine lange Zeit bis zum sicheren Punkt.

Die Messung von jHiccup ist so einfach, dass es schwer ist, sich zu irren. Die ganze Sache ist weniger als 650 Zeilen Java-Code, so dass Sie die Logik für sich selbst betrachten können. Der HiccupRecorder-Thread von jHiccup geht wiederholt für 1 ms in den Ruhezustand, und wenn er aufwacht, zeichnet er jeden Zeitunterschied auf (vor dem Schlaf), der größer ist als 1 ms als Schluckauf. Die einfache Annahme ist, dass wenn ein vorbereiteter Thread (der HiccupRecorder) 5 Sekunden lang nicht ausgeführt wurde, andere Threads in demselben Prozess auch einen ähnlich großen Schluckauf sahen. Wie Sie oben bemerkt haben, scheinen jHiccups Beobachtungen in Ihren unabhängigen Netzwerkprotokollen bestätigt zu sein, wo Sie eine Antwortzeit von 5 Sekunden sahen. Beachten Sie, dass nicht alle Schluckaufe von den Netzwerkprotokollen beobachtet wurden, wie nur Anfragen während der Schluckauf wäre von einem Netzwerk-Logger beobachtet worden.Im Gegensatz dazu kann sich kein Hiccup, der größer als ~ 1 ms ist, vor jHiccup verbergen, da er selbst bei keiner anderen Aktivität 1000 Mal pro Sekunde aufwacht.

Dieser kann nicht GC sein, aber bevor Sie GC ausschließen, würde ich vorschlagen, dass Sie in die GC-Protokollierung ein wenig mehr suchen. Zu Beginn ist ein JVM-Hinweis zur Begrenzung von Pausen auf 200 ms für alle bekannten JVMs nutzlos. Ein Pausenhinweis ist gleichbedeutend mit "Bitte". Außerdem glauben Sie Ihren GC-Protokollen nicht, wenn Sie -XX: + PrintGCApplicationStoppedTime nicht in Optionen einschließen (und sie auch dann noch verdächtigen). Es gibt Pausen und Teile von Pausen, die sehr lang sein können und nicht gemeldet werden, es sei denn, Sie fügen dieses Flag hinzu. Z.B. Ich habe Pausen gesehen, die durch die gelegentliche lange gezählte Schleife verursacht wurden, die 15 Sekunden dauerte, um einen sicheren Punkt zu erreichen, wo GC nur den .08 Sekunden-Teil der Pause berichtete, wo es tatsächlich etwas Arbeit geleistet hat. Es gibt auch viele Pausen, deren Ursachen nicht als Teil von "GC" betrachtet werden und daher durch GC-Logging-Flags nicht gemeldet werden können.

- Gil. [jHiccups Autor]