Java Sanal Makinesi - GC'yi Ayarlama
Son bölümde, çeşitli Generational GC'leri öğrendik. Bu bölümde, GC'nin nasıl ayarlanacağını tartışacağız.
Yığın Boyutu
Yığın boyutu, Java uygulamalarımızın performansında önemli bir faktördür. Çok küçükse, sık sık doldurulacak ve sonuç olarak, GC tarafından sık sık toplanması gerekecektir. Öte yandan, öbek boyutunu büyütürsek, daha az sıklıkta toplanması gerekmesine rağmen, duraklamaların uzunluğu artacaktır.
Ayrıca, yığın boyutunu artırmanın temel işletim sistemi üzerinde ciddi bir cezası vardır. Sayfalamayı kullanarak, işletim sistemi uygulama programlarımızın gerçekte mevcut olandan çok daha fazla bellek görmesini sağlar. İşletim sistemi bunu, diskte biraz takas alanı kullanarak, programların etkin olmayan kısımlarını diske kopyalayarak yönetir. Bu bölümlere ihtiyaç duyulduğunda, işletim sistemi bunları diskten belleğe geri kopyalar.
Bir makinenin 8G belleğe sahip olduğunu ve JVM'nin 16G sanal bellek gördüğünü varsayalım, JVM aslında sistemde yalnızca 8G'nin mevcut olduğunu bilemez. Sadece işletim sisteminden 16G isteyecek ve bu belleği aldığında kullanmaya devam edecek. İşletim sistemi birçok veriyi içeri ve dışarı takas etmek zorunda kalacak ve bu sistem için büyük bir performans cezasıdır.
Ve sonra bu tür sanal belleğin tam GC'si sırasında meydana gelebilecek duraklamalar gelir. GC, toplama ve sıkıştırma için tüm yığın üzerinde hareket edeceğinden, sanal belleğin diskten çıkarılması için çok beklemesi gerekecektir. Eşzamanlı bir toplayıcı olması durumunda, arka plan iş parçacıkları verilerin takas alanından belleğe kopyalanması için çok beklemek zorunda kalacaktır.
İşte burada optimum yığın boyutuna nasıl karar vermemiz gerektiği sorusu geliyor. İlk kural, işletim sistemine hiçbir zaman gerçekte mevcut olandan daha fazla bellek talep etmemektir. Bu, sık sık değiştirme problemini tamamen önleyecektir. Makinede kurulu ve çalışan birden çok JVM varsa, hepsinin bir araya getirdiği toplam bellek talebi, sistemde bulunan gerçek RAM'den daha azdır.
İki bayrak kullanarak JVM tarafından yapılan bellek talebinin boyutunu kontrol edebilirsiniz -
-XmsN - İstenen ilk belleği kontrol eder.
-XmxN - Talep edilebilecek maksimum belleği kontrol eder.
Her iki işaretin de varsayılan değerleri, temeldeki işletim sistemine bağlıdır. Örneğin, MacOS'ta çalışan 64b JVM'ler için, -XmsN = 64M ve -XmxN = minimum toplam fiziksel belleğin 1G'si veya 1 / 4'ü.
JVM'nin iki değer arasında otomatik olarak ayarlanabileceğini unutmayın. Örneğin, çok fazla GC olduğunu fark ederse, -XmxN'nin altında olduğu ve istenen performans hedeflerine ulaşıldığı sürece bellek boyutunu artırmaya devam edecektir.
Uygulamanızın tam olarak ne kadar belleğe ihtiyacı olduğunu biliyorsanız, -XmsN = -XmxN ayarlayabilirsiniz. Bu durumda, JVM'nin yığının "en uygun" değerini bulmasına gerek yoktur ve bu nedenle, GC süreci biraz daha verimli hale gelir.
Nesil Boyutları
YG'ye yığının ne kadarını ayırmak istediğinize ve bunun ne kadarını OG'ye ayırmak istediğinize karar verebilirsiniz. Bu değerlerin her ikisi de uygulamalarımızın performansını aşağıdaki şekilde etkiler.
YG'nin boyutu çok büyükse, o zaman daha az sıklıkta toplanacaktır. Bu, OG'ye yükseltilen daha az sayıda nesne ile sonuçlanacaktır. Öte yandan, OG'nin boyutunu çok fazla artırırsanız, toplamak ve sıkıştırmak çok fazla zaman alır ve bu da uzun STW duraklamalarına neden olur. Dolayısıyla kullanıcının bu iki değer arasında bir denge bulması gerekir.
Bu değerleri ayarlamak için kullanabileceğiniz bayraklar aşağıdadır -
-XX:NewRatio=N: YG'nin OG'ye oranı (varsayılan değer = 2)
-XX:NewSize=N: YG'nin başlangıç boyutu
-XX:MaxNewSize=N: YG'nin maksimum boyutu
-XmnN: Bu bayrağı kullanarak NewSize ve MaxNewSize'ı aynı değere ayarlayın
YG'nin başlangıç boyutu, verilen formülle NewRatio değerine göre belirlenir -
(total heap size) / (newRatio + 1)
NewRatio'nun başlangıç değeri 2 olduğundan, yukarıdaki formül YG'nin başlangıç değerini toplam yığın boyutunun 1 / 3'ü olarak verir. NewSize bayrağını kullanarak YG'nin boyutunu açıkça belirterek bu değeri her zaman geçersiz kılabilirsiniz. Bu bayrağın herhangi bir varsayılan değeri yoktur ve açıkça belirtilmezse, YG'nin boyutu yukarıdaki formül kullanılarak hesaplanmaya devam edecektir.
Permagen ve Metaspace
Permagen ve meta alan, JVM'nin sınıfların meta verilerini tuttuğu yığın alanlarıdır. Boşluğa Java 7'de 'permagen', Java 8'de ise 'metaspace' olarak adlandırılır. Bu bilgiler derleyici ve çalışma zamanı tarafından kullanılır.
Aşağıdaki bayrakları kullanarak permajenin boyutunu kontrol edebilirsiniz: -XX: PermSize=N ve -XX:MaxPermSize=N. Metaspace'in boyutu aşağıdakiler kullanılarak kontrol edilebilir:-XX:Metaspace- Size=N ve -XX:MaxMetaspaceSize=N.
Bayrak değerleri ayarlanmadığında, permagen ve metaspace'in nasıl yönetildiği konusunda bazı farklılıklar vardır. Varsayılan olarak, her ikisinin de varsayılan bir başlangıç boyutu vardır. Ancak metaspace, ihtiyaç duyulduğu kadar yığının çoğunu işgal edebilirken, permagen varsayılan başlangıç değerlerinden fazlasını işgal edemez. Örneğin 64b JVM, maksimum permajen boyutu olarak 82M yığın alanına sahiptir.
Metaspace, belirtilmediği sürece sınırsız miktarda bellek işgal edebileceğinden, yetersiz bellek hatası olabileceğini unutmayın. Bu bölgeler yeniden boyutlandırıldığında tam bir GC gerçekleşir. Bu nedenle, başlatma sırasında, yüklenen çok sayıda sınıf varsa, metaspace her seferinde tam bir GC ile sonuçlanacak şekilde yeniden boyutlandırmaya devam edebilir. Bu nedenle, ilk metaspace boyutunun çok düşük olması durumunda büyük uygulamaların başlaması çok zaman alır. Başlatma süresini kısalttığı için başlangıç boyutunu artırmak iyi bir fikirdir.
Permaajen ve meta alan sınıf meta verilerini tutsa da kalıcı değildir ve alan, nesnelerde olduğu gibi GC tarafından geri kazanılır. Bu tipik olarak sunucu uygulamaları söz konusudur. Sunucuya yeni bir dağıtım yaptığınızda, yeni sınıf yükleyiciler artık alana ihtiyaç duyacağından eski meta verilerin temizlenmesi gerekir. Bu alan, GC tarafından serbest bırakılır.