"Enter"a basıp içeriğe geçin

Java Sanal Makinesinde Katmanlı Derleme

BIr Java kodu yazdigimizda bunu calistirmak icin oncelikle derlememiz gerekir. Bu derlemenin sonucunda ise JVM’in calistirabilecegi baytkod olarak adlandirilan bir kod uretilir. Bytekod olarak derlenen Java sınıfları Java sanal makinesi (Java Virtual Machine – JVM) bünyesinde yorumlanır. Tek derleme işlemi Java sınıflarının bytekoda dönüştürülmesi esnasında yapılmaz. JVM bünyesinde de bytekodun makine koduna dönüştürüldüğü bir derleme gerçekleştirilir. Bu işleme Just in time (JIT) derleme adi verilir.

Iki tur Just-In-Time Java derleyicisi vardir: Bunlar sırasıyla C1 ve C2 olarak adlandirilan istemci ve sunucu turu derleyicilerdir. Bu ikisi arasındaki temel fark ise, kod derleme biçimindeki farkliliktir. İstemci derleyicisi, bir uygulamanın daha hızlı başlatılmasını sağlamak için optimize edilirken, Sunucu derleyicisi uzun vadede daha iyi performans sağlar. Tahmin edebileceğiniz gibi, İstemci derleyicisi herhangi bir tür istemci uygulamasına (genellikle GUI tabanlı) tahsis edilirken, Sunucu derleyicisi uzun süreli sunucu tarafı uygulamaları için tasarlanmıştır.

Sunucu derleyicisi neden daha hızlıdır diye soracak olursak, bunun nedeni sunucu derleyicisinin kodu daha uzun bir süre boyunca gözlemlemesi ve analiz etmesidir. Daha sonra bu bilgi, Sunucu derleyicisinin derlenmiş kodda daha iyi optimizasyonlar yapmasına olanak tanır. Bunun aksine, İstemci derleyicisi kodu mümkün olan en kısa sürede optimize etmeye ve derlemeye çalışır, bu da başlatma süresini azaltır.

Sorabileceğimiz bir diger soru, hem hızlı başlatma hem de uzun vadede mümkün olduğunca iyi performans elde etmek için hem istemci hem de sunucu derleyicilerinin bir karışımını yapmanın mümkün olup olmadığıdır. Cevap Evettir. Aslinda bu ozelligi Java 7’den beri kullanıyoruz ve buna Katmanlı derleme deniyor.

Katmanlı Derleme

Normalde, bir sunucu sanal makinesi, derleyiciye verilmiş olan metotlarla ilgili profil bilgilerini toplamak için yorumlayıcıyı kullanır. Katmanlı derleme yapısında, yorumlayıcıya ek olarak, istemci derleyicisi de kullanılır. İstemci derleyicisi kendileri hakkında profil bilgileri toplayan metotların derlenmiş sürümlerini oluşturmak için kullanılır. Derlenen kod, yorumlayıcının çalıştırdığı koddan önemli ölçüde daha hızlı olduğundan, program, profil oluşturma aşamasında daha yüksek performansla yürütülür. Çoğu durumda, sunucu derleyicisi tarafından üretilen nihai kod, uygulama başlangıcının ilk aşamalarında zaten mevcut olabileceğinden, istemci VM’inden bile daha hızlı bir başlangıç süresi elde edilebilir. Daha hızlı profil oluşturma aşaması, daha iyi optimizasyon sağlayabilecek daha uzun bir profil oluşturma süresine izin verdiği için, katmanlı yapı ayrıca normal bir sunucu VM’inden daha iyi bir performans sağlayabilir.

Hem 32 hem de 64 bit modların yanı sıra sıkıştırılmış oop desteklenir. Katmanlı derlemeyi etkinleştirmek için Java komutuyla -XX:+TieredCompilation bayrağını kullanın.

Java’da yalnızca iki temel derleyici (+ yorumlayıcı) olmasına rağmen, beş yürütme düzeyi vardır. Çünkü İstemci derleyicisi (C1) üç farklı derleme düzeyine ve Sunucu derleyicisi (C2) de yalnızca bir derleme düzeyine sahiptir.

  • Seviye 0 – yorumlanmış kod
  • Seviye 1 – basit C1 derlenmiş kod (profil oluşturma olmadan)
  • Seviye 2 – sınırlı C1 derlenmiş kod (hafif profil oluşturma ile)
  • Seviye 3 – tam C1 derlenmiş kod (tam profil oluşturma ile)
  • Seviye 4 – C2 derlenmiş kod (önceki adımlardan alınan profil verilerini kullanır)

Normal yol 0 -> 3 -> 4’tür, yani kod önce yorumlanır, ardından yeterince çalıştıktan sonra, tam profil oluşturma etkinken C1 tarafından derlenir ve son olarak C2, C1 tarafından toplanan profil verilerini kullanarak kodu derler.

Ancak bunun üç istisnası vardır.

Derlenecek Metod Basittir

Derlenecek yöntem basitse, sunucu derleyicisi daha hızlı yapmayacağından yalnızca Seviye 1’de derlenir – eğer onsuz hızlı bir şekilde yapılabiliyorsa, kodun nasıl kullanıldığını öğrenmek için kapsamlı profil oluşturmanın bir anlamı yoktur.

C2 Meşguldür

Bir noktada Sunucu derleyici kuyruğu dolarsa, yöntem Sunucu kuyruğundan alınır ve 2. Seviyede derlenir (yöntemi daha önce derleyen hafif profil oluşturma ile). Bir süre sonra, kod 3. seviyede (tam profil oluşturma ile) derlenecek ve son olarak, Sunucu kuyruğu daha az meşgul olduğunda, Sunucu derleyicisi tarafından derlenecektir (yine seviye 3’te toplanan profil verileri kullanılarak).

C1 Meşguldür, fakat C2 Müsaittir

C1 kuyruğu dolu, ancak C2 kuyruğu müsaitse, yöntem yorumlayıcı tarafından (Seviye 0) profillenebilir ve ardından doğrudan C2’ye gidebilir (böylece istemci derleyicisi derlemeye hiç dahil olmaz).

Derleyici kuyruklarının standart FIFO değil, öncelikli olduğunu belirtmekte fayda var. Java 8’de, Katmanlı derleme varsayılan olarak etkindir.

Sıkıştırılmış Sıradan Nesne İşaretçileri (OOPs)

Java Hotspot dilinde bir “oop” veya sıradan nesne işaretçisi, bir nesneye yönelik yönetilen bir işaretçidir. Bir oop normalde yerel makine işaretçisiyle aynı boyuttadır, bu da bir LP64 sisteminde 64 bit anlamına gelir. Bir ILP32 sisteminde, maksimum yığın boyutu, birçok uygulama için yetersiz olan 4 gigabayttan biraz daha azdır. Bir LP64 sisteminde, belirli bir program tarafından kullanılan yığının, bir ILP32 sisteminde çalıştırıldığından yaklaşık 1,5 kat daha büyük olması gerekebilir. Bu gereksinim, yönetilen işaretçilerin genişletilmiş boyutundan kaynaklanmaktadır. Bellek ucuzdur, ancak bu günlerde bant genişliği ve önbellek yetersizdir, bu nedenle yığın boyutunu önemli ölçüde artırmak ve yalnızca 4 gigabayt sınırının biraz üzerine çıkmak istenmez.

Java yığınındaki yönetilen işaretçiler, 8 baytlık adres sınırlarında hizalanmış nesnelere işaret eder. Sıkıştırılmış Sıradan Nesne İşaretçileri , yönetilen işaretçileri (JVM yazılımındaki çoğu yerde olmasa da) 64-bit Java yığın temel adresinden 32-bit nesne ofsetleri olarak temsil eder. Bayt ofsetleri yerine nesne ofsetleri olduklarından, dört milyara kadar nesneyi (bayt değil) veya yaklaşık 32 gigabayta kadar bir yığın boyutunu adreslemek için kullanılabilirler. Bunları kullanmak için, 8 çarpanı ile ölçeklenmeleri ve başvurdukları nesneyi bulmak için Java yığın temel adresine eklenmeleri gerekir. Sıkıştırılmış Sıradan Nesne İşaretçileri kullanan nesne boyutları, ILP32 modundakilerle karşılaştırılabilir.

Kod çözme terimi, 32 bit sıkıştırılmış bir oop’un yönetilen yığına 64 bit yerel adrese dönüştürüldüğü işlemi ifade etmek için kullanılır. Ters işlem kodlama olarak adlandırılır.

Sıkıştırılmış Sıradan Nesne İşaretçileri, Java SE 6u23 ve sonraki sürümlerde varsayılan olarak desteklenir ve etkinleştirilir. Java SE 7’de, -Xmx belirtilmediğinde ve -Xmx değerleri 32 gigabayttan küçük olduğunda 64-bit JVM işlemleri için Sıkıştırılmış Sıradan Nesne İşaretçileri kullanımı varsayılandır. 6u23 sürümünden önceki JDK 6 için, özelliği etkinleştirmek için Java komutuyla birlikte -XX:+UseCompressedOops bayrağını kullanın.

Sıfır Tabanlı Sıkıştırılmış Sıradan Nesne İşaretçileri (OOPs)

64-bit Java Sanal Makinesi prosesinde sıkıştırılmış oops kullanırken, JVM yazılımı işletim sisteminden sıfır sanal adresinden başlayarak Java yığını için bellek ayırmasını ister. İşletim sistemi böyle bir isteği destekliyorsa ve sıfır sanal adresinde Java yığını için bellek ayırabiliyorsa, sıfır tabanlı sıkıştırılmış oops kullanılır.

Sıfır tabanlı sıkıştırılmış oops kullanımı, Java yığın temel adresini eklemeden 32 bitlik bir nesne ofsetinden 64 bitlik bir işaretçinin kodunun çözülebileceği anlamına gelir. 4 gigabayttan küçük yığın boyutları için, JVM yazılımı bir nesne ofseti yerine bir bayt ofseti kullanabilir ve böylece ofseti 8 ile ölçeklemekten kaçınabilir. 64-bitlik bir adresi 32-bitlik bir ofset olarak kodlamak da buna uygun olarak verimlidir.

26 gigabayt civarındaki Java yığın boyutları için, Solaris, Linux ve Windows işletim sistemlerinden herhangi biri tipik olarak Java yığınını sanal adres sıfırına tahsis edebilecektir.

Kaynaklar

  1. Java ™ HotSpot Virtual Machine Performance Enhancements – https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html
  2. Compilation Optimization – https://docs.oracle.com/javacomponents/jrockit-hotspot/migration-guide/comp-opt.htm#JRHMG117
  3. Client, Server, and Tiered Compilation – DZone Java – https://dzone.com/articles/client-server-and-tiered-compilation
  4. Deep Dive Into the New Java JIT Compiler – Graal | Baeldung – https://www.baeldung.com/graal-java-jit-compiler
  5. JVM Nasıl Çalışır Yazı Serisi – Java Just In Time Compiler (JIT) Nasıl Çalışır? – http://www.kurumsaljava.com/2016/05/14/java-just-in-time-compiler-jit-nasil-calisir/

İlk Yorumu Siz Yapın

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir