JVM neden JIT kodu derlemiyor?


107

Sun'ın kanonik JVM uygulaması, kod birkaç kez çalıştırıldıktan sonra neredeyse yerel yürütme hızları elde etmek için bayt koduna oldukça karmaşık bir optimizasyon uygular.

Soru şudur, bu derlenmiş kod neden aynı işlevin / sınıfın sonraki kullanımları sırasında kullanılmak üzere diske önbelleğe alınmıyor?

Mevcut haliyle, bir program her çalıştırıldığında, JIT derleyicisi, kodun önceden derlenmiş bir sürümünü kullanmak yerine yeniden başlar. Bayt kodu esasen yorumlanırken, bu özelliğin eklenmesi programın ilk çalışma süresine önemli bir artış sağlamaz mı?


4
Bu sorunu tartışan bir konu: javalobby.org/forums/thread.jspa?threadID=15812
miku

2
Ancak kesin bir yanıt alması beklenmeyen bir soru.
bmargulies

1
"Önemli" bir artıştan emin değilim, çünkü o zaman JITted öğelerini bellekte JITlemek yerine diskten yüklemeniz gerekir. İşleri hızlandırabilir, ancak durum bazında.
R. Martinho Fernandes

1
Herkese harika cevaplar için teşekkürler! Tüm cevaplar eşit derecede geçerliydi, bu yüzden bu konuda toplulukla gittim ...
Chinmay Kanchi

Bana sorarsan bu iyi bir soru :)
Alfred

Yanıtlar:


25

@ MYYN'nin gönderdiği bağlantıyı kesip yapıştırmaya başvurmadan, bunun JVM'nin gerçekleştirdiği optimizasyonların statik değil, daha çok veri kalıplarına ve kod kalıplarına dayalı olarak dinamik olduğundan şüpheleniyorum. Bu veri modellerinin uygulamanın ömrü boyunca değişmesi ve önbelleğe alınan optimizasyonları optimumdan daha az hale getirmesi muhtemeldir.

Dolayısıyla, kaydedilen optimizasyonların hala optimal olup olmadığını belirlemek için bir mekanizmaya ihtiyacınız olacak, bu noktada sadece anında yeniden optimize edebilirsiniz.


6
... ya da sadece bir olarak sebat sunabilir seçeneği güçlendirmek - Oracle'ın JVM yaptığı gibi, ileri düzey programcılar kendi uygulamanın performansını ve onlar sadece optimize etmek bilmek desenler vardır değil onların sorumluluğu altında, değişen. Neden olmasın?!
Alex Martelli

2
Çünkü muhtemelen buna değmez. Ne SUN, IBM ne de BEA, performans JVM'leri için bunu değerli görmediyse, bunun için iyi bir neden olacaktır. Belki RT optimizasyonu Oracle'ınkinden daha hızlıdır, bu yüzden Oracle onu önbelleğe alır.
skaffman

9
Önceki çalışmalarda öğrenilenleri kullanmak için neden depolanmış optimizasyonları başlangıç ​​noktası olarak almıyorsunuz? Oradan, JIT her zamanki gibi yeniden optimize ederek çalışabilir. Kapatma sırasında, bu kod tekrar kalıcı hale getirilebilir ve sonraki çalıştırmada yeni bir başlangıç ​​noktası olarak kullanılabilir.
Puce

1
@Puce Düşünebilmemin tek nedeni, AFAIK'in optimize edilmiş kod çalıştırarak profilleme istatistikleri elde etmemenizdir. Yani iyileştirmenin bir yolu yok ...
maaartinus

1
Kişisel olarak, "yalnızca aynı JVM, aynı veriler vb. İçin geçerli olacak ve aksi takdirde göz ardı edilecek" şeklinde tüm uyarıları içeren "yalnızca JIT profilleme bilgilerini çalıştırmalar arasında devam ettirin" seçeneğiyle iyi olurum. Bunun neden uygulanmadığına gelince, JIT tohum verilerini sürdürmenin ve doğrulamanın ek karmaşıklığının diğer projelerden kaynak almak için çok fazla olmasını bekliyorum. Bu ve Java 8 lambda + akışları arasındaki seçim göz önüne alındığında, ikincisini tercih ederim.
Thorbjørn Ravn Andersen

25

Oracle'ın JVM'sinin gerçekten bunu yaptığı belgelenmiştir - Oracle'dan alıntı yaparak,

derleyici, isteğe bağlı olarak veritabanı çağrıları, oturumları veya örneklerinde derlenmiş Java yöntemlerini sürdürmek için Oracle JVM'nin sınıf çözümleme modelinden yararlanabilir. Bu tür bir kalıcılık, anlamsal olarak Java kodunun değişmediği bilindiğinde, oturumlar veya örnekler arasında gereksiz yeniden derlemelerin ek yükünü önler.

Tüm karmaşık sanal makine uygulamalarının neden benzer seçenekler sunmadığını bilmiyorum.


8
Çünkü diğer gelişmiş JVM'lerde eşyaları saklamak için kullanışlı, harika bir kurumsal RDBMS yok :)
skaffman

Vaov! bu, Derlemelerin zaman zaman önbelleğe alındığı anlamına gelir. Bu iyi haber!
Sandeep Jindal

IBM'in J9'unun da bunu yaptığı belgelenmiştir.
user314104

9
Bu Oracle JVM'nin, Oracle'ın Sun'ı satın alırken indirdiği değil, Oracle Veritabanının içinde olduğunu unutmayın.
Thorbjørn Ravn Andersen

14

Mevcut yanıtlara güncellendi - Java 8, bunu çözmeye adanmış bir JEP'e sahiptir:

=> JEP 145: Önbellek Derlenmiş Kod . Yeni bağlantı .

Çok yüksek bir düzeyde, belirtilen amacı şudur :

Büyük Java uygulamalarının başlatma süresini iyileştirmek için önceki çalıştırmalardan derlenmiş yerel kodu kaydedin ve yeniden kullanın.

Bu yardımcı olur umarım.


3
Özellik, son sürüme ulaşmadı .
assylias

5

Excelsior JET , 2001'de piyasaya sürülen 2.0 sürümünden beri bir önbelleğe alma JIT derleyicisine sahiptir. Ayrıca, AOT derleyicisi tüm optimizasyonları kullanarak önbelleği tek bir DLL / paylaşılan nesne olarak yeniden derleyebilir.


3
Evet, ama soru kanonik JVM ile ilgiliydi, yani Sun'ın JVM'si. Java için birkaç AOT derleyicisinin yanı sıra diğer JVM'leri önbelleğe aldığının farkındayım.
Chinmay Kanchi

0

JVM uygulamasına hiçbir şekilde dahil olmadığım için gerçek nedenleri bilmiyorum, ancak bazı makul nedenler düşünebilirim:

  • Java fikri, her yere bir kez yazılabilen bir dil olmaktır ve sınıf dosyasına önceden derlenmiş şeyler koymak bunu bir nevi ihlal eder (sadece "tür" çünkü tabii ki gerçek bayt kodu hala orada olacaktır)
  • Bu, sınıf dosya boyutlarını artırır, çünkü orada aynı koda birden çok kez sahip olursunuz, özellikle aynı programı birden fazla farklı JVM altında çalıştırırsanız (bu, farklı sürümlerin farklı JVM'ler olduğunu düşündüğünüzde çok da nadir değildir. gerçekten yapmak zorunda)
  • Sınıf dosyalarının kendileri yazılabilir olmayabilir (bunu kontrol etmek oldukça kolay olsa da)
  • JVM optimizasyonları kısmen çalışma zamanı bilgilerine dayalıdır ve diğer çalıştırmalarda uygulanabilir olmayabilir (yine de bazı faydalar sağlamaları gerekir)

Ama gerçekten tahmin ediyorum ve gördüğünüz gibi, nedenlerimin gerçek şovları durdurduğunu düşünmüyorum. Sun'un bu desteği bir öncelik olarak görmediğini düşünüyorum ve belki de ilk nedenim gerçeğe yakın, çünkü bunu alışkanlıkla yapmak insanları Java sınıf dosyalarının gerçekten olmak yerine her VM için ayrı bir sürüme ihtiyaç duyduğunu düşünmeye sevk edebilir. çapraz platform.

Tercih ettiğim yöntem, aslında önceden açıkça böyle bir şey yapmak için kullanabileceğiniz ayrı bir bayt kodu-yerel çevirmene sahip olmak, belirli bir sanal makine için açıkça oluşturulmuş sınıf dosyaları oluşturmak ve muhtemelen orijinal bayt kodu ile içlerinde olmaktır. farklı VM'lerle de çalışabilir. Ama bu muhtemelen benim deneyimimden kaynaklanıyor: Çoğunlukla Java ME yapıyorum, Java derleyicisinin derleme konusunda daha akıllı olmaması gerçekten canımı yakıyor.


1
sınıf dosyasında böyle şeyler için bir nokta vardır, aslında bu orijinal amaçtı (JIT'lenmiş kodu sınıf dosyasında bir öznitelik olarak saklayın).
TofuBeer

@TofuBeer: Onay için teşekkürler. Durumun bu olabileceğinden şüphelendim (ben de öyle yapardım), ama emin değildim. Bunu olası bir neden olarak kaldırmak için düzenlendi.
JaakkoK

Sanırım son kurşun noktanızla kafasına çiviyi vurdunuz. Diğerleri üzerinde çalışılabilir, ancak bu son kısım, sanırım JITed kodunun kalıcı olmamasının ana nedeni.
Sasha Chedygov

1
Açık bayt kodundan yerel derleyiciye ilişkin son paragraf, şu anda NGEN ile .NET'te sahip olduğunuz şeydir ( msdn.microsoft.com/en-us/library/6t9t5wcf(VS.71).aspx ).
R. Martinho Fernandes
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.