2017-01-05 2 views
2

Je testais récemment une application de présentation avec une charge concurrente relativement élevée. L'application est une application Java et s'exécute sur Hotspot JVM (1.8.0_111).Hotspot JVM - G1GC Problème de redimensionnement de tas

Je pourrais obtenir un débit maximum d'environ 400 TPS avec un tas 4G et un collecteur de débit parallèle. Le tableau de débit (en fonction de la charge) est indiqué ci-dessous.

enter image description here

Comme Oracle suggère d'utiliser pour G1GC tas de tailles plus grandes que 4G, je voulais essayer G1 et voir si cela profite à mon débit d'application de quelque façon. À ma grande surprise, avec G1GC, j'ai vu la tendance du débit ci-dessous.

enter image description here

J'ai été vraiment surpris et a décidé de creuser dans pour voir ce qui est arrivé ici. C'est ce que j'ai trouvé.

enter image description here

Je vois que d'abord, sur le tas 4G, 1.5G est alloué aux anciennes régions gen et 2.5G aux régions eden. Mais au fur et à mesure que le temps avance et que l'ancienne génération ne peut plus tenir dans 1.5G, le tas est redimensionné. Cela semble anodin. Mais le problème semble être dans la façon dont le redimensionnement se produit.

La totalité de la 4G est maintenant allouée aux régions de génération ancienne et aucune, presque, aux régions d'eden. Maintenant, quand quelque chose doit être alloué à eden, le tas est redimensionné. Et ceci devient la nouvelle normale, où le tas est redimensionné à plusieurs reprises, ce qui entraîne un énorme coût de performance pour l'application.

Quelqu'un a-t-il déjà remarqué cela avec G1GC? Y a-t-il des recommandations pour négocier ce problème?

Voici la ligne de commande de démarrage avec les options JVM.

java -server -Xms4096m -Xmx4096m -XX:MetaspaceSize=100m -XX:MaxMetaspaceSize=100m -XX:MaxDirectMemorySize=512m -XX:MinMetaspaceFreeRatio=0 -XX:MaxMetaspaceFreeRatio=100 -XX:CompressedClassSpaceSize=20m -XX:InitialCodeCacheSize=50m -XX:ReservedCodeCacheSize=50m -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/tmp -Xloggc:/servers/logs/gc.log.2017-01-05-085234 -Djava.awt.headless=true -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -Dio.netty.leakDetectionLevel=simple -XX:MaxDirectMemorySize=512m -Dadmin.connectors.http.port=9000 -Dproxy.connectors.http.port=8080 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8654 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -server -cp ... 

options JVM:

-server 
-Xms4096m 
-Xmx4096m 
-XX:MetaspaceSize=100m 
-XX:MaxMetaspaceSize=100m 
-XX:MaxDirectMemorySize=512m 
-XX:MinMetaspaceFreeRatio=0 
-XX:MaxMetaspaceFreeRatio=100 
-XX:CompressedClassSpaceSize=20m 
-XX:InitialCodeCacheSize=50m 
-XX:ReservedCodeCacheSize=50m 
-XX:+AlwaysPreTouch 
-XX:+DisableExplicitGC 
-XX:+PrintGCDetails 
-XX:+PrintGCDateStamps 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/var/tmp 
-Xloggc:/servers/logs/gc.log.2017-01-05-085234 
-Djava.awt.headless=true 
-XX:+UnlockCommercialFeatures 
-XX:+FlightRecorder 
-Dio.netty.leakDetectionLevel=simple 
-XX:MaxDirectMemorySize=512m 
-Dadmin.connectors.http.port=9000 
-Dproxy.connectors.http.port=8080 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=8654 
-Dcom.sun.management.jmxremote.local.only=false 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-server 
-cp ... 

S'il vous plaît trouver les journaux gc here

+1

Pouvez-vous partager tous les paramètres que vous avez définis lors du démarrage de l'application? https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/g1_gc_tuning.html#recommendations –

+0

@SauliusNext J'ai maintenant ajouté la liste des paramètres à la question. Pour G1GC, la seule différence est l'ajout de -XX: + UseG1GC –

+1

puisque vous avez déjà activé la journalisation GC, vous devez joindre un journal GC suffisamment long de la période d'intérêt. – the8472

Répondre

1

Il semble y avoir beaucoup des éléments suivants deux causes GC:

  • [pause GC (G1 Humongous Allocation) (jeune) (marque initiale)
  • [GC Pause (G1 Evacuation Pause) (jeune) (épuisé)

Les allocations humonges ont besoin d'espace dans l'ancienne génération, l'épuisement vers l'espace augmente la taille de la jeune génération. Ils sont en concurrence les uns avec les autres.

Il semble que vous allouiez beaucoup d'objets gigantesques (taille de région 1/2> G1) plus rapidement que les cycles simultanés initiés par l'IHOP peuvent les collecter.

Vous pouvez essayer d'augmenter la taille de la région. Si ce sont de grandes grappes primitives (c'est-à-dire qui ne sont pas de référence), le test expérimental eager reclaim feature pourrait également aider.

+0

Oui. Mon application alloue beaucoup d'objets humongous en fait. Malheureusement, la fonctionnalité de récupération désirée que vous pointez semble être disponible uniquement pour OpenJDK (j'utilise Hotspot JVM). Mais, après avoir lu les commentaires mentionnés par vous et @sauliusNext, je pense que je vais jouer avec les options suivantes pour voir comment cela aide. -XX: MaxGCPauseMillis -XX: G1MixedGCLiveThresholdPercent = <> -XX: G1MixedGCCountTarget = <> -XX: G1OldCSetRegionThresholdPercent = <> –

+0

A la fin de l'exercice entier, j'ai réalisé que votre suggestion d'augmenter la taille de la région résolue mon problème. Je vous remercie :-) –