Yazar | Yang Xiaofeng
Kaynak | Geek Time "Java Core Technologies üzerine 36 Ders" sütunu
Dış kaynaklardan G1 girişinin çoğunun hala JDK 7 veya daha önceki sürümlerin uygulanmasında olduğunu ve birçok sonucun büyük sapmalara sahip olduğunu ve hatta bazı geçmiş GC seçeneklerinin artık önerilmediğini buldum. Bu nedenle, bugün ayrıntılı açıklama için JDK'nın yeni sürümünde varsayılan G1 GC'yi seçeceğim ve tipik senaryoları ve ayarlama fikirlerini ayarlama pratiği perspektifinden analiz edeceğim. Bu bilgiyi birlikte güncelleyelim.
Bugün size sormak istediğim soru şu: GC ayarlama fikirleriniz hakkında konuşun mu?
Ayarlama söz konusu olduğunda, bu belirli bir senaryo ve belirli bir amaç için olmalıdır.GC ayarlaması için, her şeyden önce, ayarlama hedefleri konusunda net olmanız gerekir? Performans açısından bakıldığında, genellikle üç husus söz konusudur: bellek ayak izi, gecikme ve aktarım hızı. Çoğu durumda, ayarlama hedeflerden birine veya ikisine odaklanır ve nadiren Üç farklı açının düşünülebileceği durumlar vardır. Tabii ki, yukarıdaki olağan üç özelliğe ek olarak, diğer GC ile ilgili senaryoların da dikkate alınması gerekebilir.Örneğin, OOM mantıksız GC ile ilgili parametrelerle de ilgili olabilir veya uygulama başlatma hızı gereksinimleri için GC de dikkate alınacaktır. .
Temel ayarlama fikirleri şu şekilde özetlenebilir:
Bugün incelenen GC ayarlama problemi, JVM ayarlamasının temel bir yönüdür. Birçok JVM ayarlama gereksinimi, sonunda GC ayarlamasına uygulanacak veya onunla ilgili olacaktır. Sağladığım şey ortak bir fikir.
Belirli sorunları hızlı bir şekilde bulmak ve çözmek için, JVM ve GC bilgilerinin yanı sıra gerçek ayarlama deneyiminin özetinde ve hatta bazen birikmiş deneyimin sezgisel yargısından ustalaşmak hala gereklidir. Görüşmeci, projede karşılaşılan gerçek sorunları sormaya devam edebilir.Eğer bağlamı açık ve kısaca tanıtabilir ve ardından teşhis fikirlerini ve ayarlama uygulama sürecini ifade edebilirseniz, bu iyi bir artı olacaktır.
Sütun, belirli bir proje deneyimi sağlayamasa da, ortak ayar fikirleri ve yöntemlerinde ustalaşmanıza yardımcı olabilir; bu, ister bir röportaj olsun ister gerçek bir çalışma olsun çok faydalıdır. Ek olarak, aşağıdaki farklı bakış açılarından ekleyeceğim:
Öncelikle G1 GC'nin iç yapısını ve ana mekanizmasını anlayalım.
Hafıza alanı açısından G1 de yaş kavramına sahiptir, ancak daha önce tanıttığım hafıza yapısından çok farklıdır.İç kısmı satranç tahtasına benzer bölgelerden oluşur.Lütfen aşağıdaki diyagrama bakınız.
Bölgenin boyutu aynı. Değer, 1M ile 32M bayt arasında 2'nin kuvvetidir. JVM, aynı boyuttaki yaklaşık 2048 bölgeyi bölmeye çalışacaktır. Bu, heapRegionBounds.hpp kaynak kodundan görülebilir. Elbette bu sayı manuel olarak ayarlanabilir ve G1 de yığın boyutuna göre otomatik olarak ayarlanacaktır.
G1 uygulamasında yaş, bölgenin o kısmında somutlaşan mantıksal bir kavramdır ve diğer kısmı Survivor olarak kullanılır.Beklenen Eski bölge dışında, G1 bölge boyutunun% 50'sini aşan nesnelere sahip olacaktır (uygulamalarda, genellikle bayt Veya karakter dizisi) Humongous nesneler olarak sınıflandırılır ve ilgili bölgelere yerleştirilir. Mantıksal olarak, Humongous bölgesi eski neslin bir parçasıdır, çünkü bu kadar büyük nesneleri kopyalamak çok pahalı bir işlemdir ve yeni nesil GC kopyalama algoritması için uygun değildir.
Bölge tasarımının yan etkilerini düşünebilir misiniz?
Örneğin, aynı bölge boyutunu ve büyük nesneyi garanti etmek zordur, bu da alan israfına neden olur. Diyagramımdaki bazı alanların Humongous renklerde olduğunu fark ettiniz mi bilmiyorum, ancak bunlar adlarla işaretlenmemiş. Bu, çok büyük nesnelerin birden fazla bölgeyi işgal edebileceğini belirtmek içindir. Dahası, bölge çok küçük ve uygunsuz, büyük nesneler tahsis ederken bitişik alan bulmayı zorlaştıracak Bu uzun süredir devam eden bir durum.Lütfen OpenJDK topluluğundaki tartışmaya bakın. Bu, özünde bir JVM hatası olarak da kabul edilebilir, ancak çözüm de çok basit olmasına rağmen, doğrudan daha büyük bir bölge boyutu ayarlayın, parametreler aşağıdaki gibidir:
-XX: G1HeapRegionSize = < N, örneğin 16 > MGC algoritması perspektifinden bakıldığında, G1, aşağıdaki gibi basitleştirilebilen ve anlaşılabilen bir bileşik algoritma seçer:
Geleneksel olarak, insanlar genç GC (Young GC) Minor GC'yi ve eski GC'yi genel Tam GC'den farklı olan Major GC olarak adlandırmayı severler. Ancak modern GC'de bu kavram artık doğru değil. G1 için:
G1'in dahili çalışması perspektifinden, aşağıdaki diyagram, normal çalışma sırasında G1'in durum akış değişikliklerini açıklamaktadır.Elbette, bir kaçış arızası durumunda, Tam GC tetiklenecektir.
G1'de birbiriyle ilişkili birçok kavram vardır. Bir anahtar nokta, nesnelerin bölgeler arasındaki referans ilişkisini kaydetmek ve sürdürmek için kullanılan Hatırlanan Küme'dir. Bunu neden yapmanız gerekiyor? Yeni nesil GC'nin bir kopya algoritması olduğunu, yani benzer nesnelerin Eden veya Survivor'dan alana "hareketinin" aslında "kopya" olduğunu ve aslında yeni bir nesne olduğunu hayal edin. Bu süreçte eski nesilden yeni nesile kadar bölgeler arası referansların hala geçerli olduğundan emin olmak gerekiyor. Aşağıdaki diyagram, ilgili tasarımı göstermektedir.
G1'in ek yükünün çoğu Hatırlanan Kümeden gelir.Örneğin, genellikle Yığın boyutunun yaklaşık% 20'sini veya daha fazlasını kaplar ki bu çok önemli bir orandır. Ayrıca, nesneleri kopyalarken, Kart Tablosu bilgilerini taramamız ve değiştirmemiz gerektiğinden, bu hız kopyalama hızını etkiler ve bu da duraklama süresini etkiler.
G1'in iç kısımlarını açıklayan birçok materyal var, bu yüzden onları tekrar etmeyeceğim. Dahili yapı ve algoritmalar hakkında daha fazla bilgi edinmek istiyorsanız, bazı özel girişlere bakmanızı öneririm. Kitaplar için, Charlie Hunt ve diğerleri tarafından yazılan "Java Performance Companion" ı öneririm.
Daha sonra, farkında olmayabileceğiniz G1 davranış değişikliklerini tanıtacağım.Bir dereceye kadar, kolondaki diğer derslerde bahsedilen zamansız tip kaldırma problemi gibi bazı problemleri çözecekler.
Bu tür bir ağırlık, çok fazla bellek alanı tasarrufu sağlasa da, bu eşzamanlı işlemin bazı CPU kaynaklarını kullanacağını ve ayrıca Young GC'nin biraz yavaşlamasına neden olacağını unutmayın.
G1 tipi kaldırmada herhangi bir gelişme var mı? G1'in yalnızca Full GC oluştuğunda tip boşaltma yaptığı birçok malzemede belirtilmiştir, ancak bu açıkça istediğimiz şey değildir. Kaldırma türünü görüntülemek için aşağıdaki parametreleri ekleyebilirsiniz:
-XX: + TraceClassUnloadingNeyse ki modern G1'de durum böyle değil. 8u40'tan sonra, G1 varsayılan olarak aşağıdaki seçenekleri ekledi:
-XX: + ClassUnloadingWithConcurrentMarkDiğer bir deyişle, eşzamanlı işaretleme aşaması sona erdikten sonra, JVM tip boşaltma gerçekleştirir.
JDK 9'dan sonra G1'in uygulanmasında, bu ayarlama gereksinimi çok daha az olacaktır, çünkü JVM bu parametreyi yalnızca başlangıç değeri olarak kullanacak, çalışma zamanında örnekleyecek, istatistiksel veriler elde edecek ve ardından eşzamanlı işaretleme başlangıç zamanını buna göre dinamik olarak ayarlayacaktır. Karşılık gelen JVM parametreleri aşağıdaki gibidir ve varsayılan olarak etkinleştirilmiştir:
-XX: + G1UseAdaptiveIHOPElbette, burada tanıtılmayacak daha hızlı Kart Tablosu taraması vb. Gibi birçok başka değişiklik vardır, çünkü bunlar davranışta değişiklik getirmezler ve temelde ayar seçeneklerini etkilemezler.
G1'in dahili mekanizması yukarıda tanıtıldı ve bazı ayar önerileri serpiştirildi.İşte bir bütün olarak bazı ayar önerileri. Her şeyden önce, mümkün olduğunca daha yeni bir JDK sürümüne yükseltmeniz tavsiye edilir.Yukarıda sunulan iyileştirmelerden, insanların sık sık tartıştığı birçok sorunun aslında JDK yükseltilerek çözülebileceğini görebiliriz.
İkinci olarak, GC ayarlama bilgilerini toplama yönteminde ustalaşın. Mümkün olduğunca kapsamlı, ayrıntılı ve doğru bilgilere hakim olmak, yalnızca GC ayarının değil, çeşitli ayarların temelidir. Gelin GC günlüğünü açmaya bir göz atalım.Bu çok basit bir mesele gibi görünüyor, ancak gerçekten ustalaştığınıza emin misiniz?
Yaygın olarak kullanılan iki seçeneğe ek olarak,
-XX: + PrintGCDayrıntıları -XX: + PrintGCDateStampsAyrıca çok kullanışlı bazı günlük seçenekleri vardır ve birçok özel sorunun teşhisi şu seçeneklere bağlıdır:
-XX: + PrintAdaptiveSizePolicy // G1 Ergonomi ile ilgili bilgileri yazdırınGC içindeki bazı davranışların uyarlamalı olarak tetiklendiğini biliyoruz PrintAdaptiveSizePolicy kullanarak, JVM'nin neden olmasını istemeyebileceğimiz bazı eylemler yaptığını öğrenebiliriz. Örneğin, G1 ayarı için temel bir öneri, çok sayıda Humongous nesne tahsisinden kaçınmaktır.Ergonomi bilgileri bunun gerçekleştiğini gösteriyorsa, yığın boyutunu artırmayı veya doğrudan bölge boyutunu artırmayı düşünebilirsiniz.
Alıntıların zamanında temizlenmediğinden şüpheleniyorsanız, birikimin nerede olduğunu öğrenmek için aşağıdaki seçenekleri açabilirsiniz.
-XX: + PrintReferenceGCEk olarak, paralel referans işleme seçeneklerinin altındaki seçenekleri açmanız önerilir.
-XX: + ParallelRefProcEnabledDikkat edilmesi gereken bir nokta, JDK 9'daki JVM ve GC günlüğe kaydetme mekanizmasının yeniden düzenlenmiş olmasıdır. Aslında, daha önce bahsettiğim
PrintGCDetails eski olarak işaretlendi ve PrintGCDateStamps kaldırıldı ve JVM'nin başlatılamamasına neden olacağı belirtildi. Yeni konfigürasyon parametrelerini sorgulamak için aşağıdaki komutu kullanabilirsiniz.
java -Xlog: yardımSon olarak, bazı genel uygulamalara bakın ve daha önce tanıttığım iç yapıyı ve mekanizmayı anlayın, birçok sonuç bir bakışta anlaşılır, örneğin:
Maksimum değerin düşürülmesi, Young GC gecikmesinin azaltılmasına da yardımcı olur.
-XX: G1MaxNewSizePercentDoğrudan G1 için küçük bir gecikme hedefi değeri belirlersek, yeni nesli azaltma etkisine sahip olacak, ancak verimi etkileyecektir.
Daha önce söylediğimi hatırlayın, eski bölgenin bir kısmı Karışık GC'ye dahil edilecek, bir seferde işlenen bölge sayısını azaltmak doğrudan seçimlerden biridir.
Maksimum değerini kontrol etmek için yukarıda G1OldCSetRegionThresholdPercent'i tanıttım. Karışık GC'lerin sayısını artırmak için aşağıdaki parametreleri de kullanabilirsiniz. Mevcut varsayılan değer 8'dir. Karışık GC'lerin sayısındaki artış, dahil edilen bölgenin her seferinde azaldığı anlamına gelir.
-XX: G1MixedGCCountTargetAşırı ayarlamadan kaçınmak için, G1'in büyük yığınlara karşı çok dostça olduğu ve çalışma mekanizmasının da belirli bir alan israf etmesi gerektiğine dikkat edilmelidir.Bazen yığına biraz daha fazla alan vermek, sert ayar yapmaktan daha pratiktir.
Bugün temel GC ayarlama fikirlerini sıraladım ve G1'in iç yapısını ve en son davranış değişikliklerini ayrıntılı olarak açıkladım. Genel olarak, G1'in ayarlanması nispeten basit ve sezgiseldir, çünkü duraklama süresini ve diğer hedefleri doğrudan belirleyebilir ve içerisine çeşitli akıllı uyarlanabilir mekanizmalar ekleyebilirsiniz.Umarım tüm bu çabalar, günlük uygulamaları geliştirmenize yardımcı olur. Zaman daha verimli.