JIT derleyicisinin sıradan bir derleyiciden farkı nedir?


22

Java, Ruby ve Python gibi diller için JIT derleyicileri hakkında çok fazla yutturmaca vardı. JIT derleyicileri C / C ++ derleyicilerinden nasıl farklıdır ve C / C ++ derleyicileri yalnızca derleyiciler olarak adlandırılırken, neden JIT derleyicileri Java, Ruby veya Python için yazılmış derleyicilerdir?

Yanıtlar:


17

JIT derleyicileri kodu anında, yürütmeden hemen önce veya yürütürken bile derler. Bu şekilde, kodun çalıştığı VM, yalnızca çalışma zamanı bilgileriyle mümkün olabilecek optimizasyonlara izin vermek için kod yürütmedeki kalıpları kontrol edebilir. Ayrıca, eğer VM derlenmiş versiyonun hangi nedenle olursa olsun yeterince iyi olmadığına karar verirse (örneğin, çok fazla önbellek eksikse veya belirli bir istisna attığında kod sık sık), daha akıllı bir şekilde yeniden derlemeye karar verebilir derleme.

Diğer taraftan, C ve C ++ derleyicileri geleneksel olarak JIT değildir. Geliştiricinin makinesinde yalnızca bir kez çekim yaparlar ve daha sonra bir çalıştırılabilir üretilirler.


Önbellek özlemlerini takip eden ve derleme stratejilerini buna göre uyarlayan JIT derleyicileri var mı? @Victor
Martin Berger

@MartinBerger Herhangi bir JIT derleyicisinin bunu yapıp yapmadığını bilmiyorum ama neden olmasın? Bilgisayarlar daha güçlü ve bilgisayar bilimleri geliştikçe, insanlar programa daha fazla optimizasyon uygulayabilirler. Örneğin, Java doğduğunda, çok yavaş, derlenmiş olanlara göre 20 kere olabilir, ancak şimdi performans çok fazla kalmıyor ve bazı derleyicilerle karşılaştırılabilir durumda
olabiliyor

Bunu uzun zaman önce bir blog yazısında duydum. Derleyici mevcut CPU'ya bağlı olarak farklı şekilde derlenebilir. Örneğin, CPU'nun SSE / AVX'i desteklediğini tespit etmesi durumunda, bazı kodları otomatik olarak vektörleştirebilir. Yeni SIMD uzantıları mevcut olduğunda, yeni olanları derleyebilir, böylece programcının herhangi bir şeyi değiştirmesine gerek kalmaz. Ya da daha büyük önbellekten yararlanmak için işlemleri / verileri düzenleyebilirse veya önbellek eksikliğini azaltabilirse
phuclv 11.03

@ LưuVĩnhPhúc Chào! Buna inanmaktan mutluyum, ancak fark şu ki, örneğin CPU tipi veya önbellek boyutu, hesaplama boyunca değişmeyen statik bir şeydir, bu yüzden kolayca bir statik derleyici tarafından da yapılabilir. Önbellek özlüyor OTOH çok dinamik.
Martin Berger

12

JIT tam zamanında derleyici için kısa ve isim yanlış: çalışma zamanı sırasında kodun optimizasyonuna değer belirler ve bunları uygular. Normal derleyicilerin yerini almaz, ancak tercümanların bir parçasıdır. Ara kod kullanan Java gibi dillerin her ikisine de sahip olduğunu unutmayın : kaynak kodundan orta kod çevirisine normal bir derleyici ve performans artırıcı tercümana dahil edilen bir JIT.

Kod optimizasyonları kesinlikle "klasik" derleyiciler tarafından gerçekleştirilebilir, ancak asıl farkı not edin: JIT derleyicileri çalışma zamanında verilere erişebilir . Bu büyük bir avantaj; Açıkça kullanmak, açıkça zor olabilir.

Örneğin, şöyle bir kod düşünün:

m(a : String, b : String, k : Int) {
  val c : Int;
  switch (k) {
    case 0 : { c = 7; break; }
    ...
    case 17 : { c = complicatedMethod(k, a+b); break; }
  }

  return a.length + b.length - c + 2*k;
}

Normal bir derleyici bu konuda çok fazla şey yapamaz. Bununla birlikte, bir JIT derleyicisi mbunun yalnızca k==0bir nedenden dolayı çağrıldığını tespit edebilir (zamanla kod değiştiğinde böyle şeyler olabilir); daha sonra kodun daha küçük bir versiyonunu oluşturabilir (ve bunu kavramsal olarak küçük bir nokta olarak düşünmeme rağmen, onu yerel koda derleyin):

m(a : String, b : String) {
  return a.length + b.length - 7;
}

Bu noktada, şu anda önemsiz olduğu için yöntem çağrısının satır içi bile büyük olasılıkla olacaktır.

Anlaşılan, Güneş javac, Java 6’da yapılan çoğu optimizasyonu reddetti ; Bu optimizasyonların JIT’in yapmasını zorlaştırdığı ve sonunda derlenen kodların daha hızlı çalıştığı söylendi. Git figürü.


Bu arada, tür silme varlığında (örneğin, Java'daki jenerikler) JIT aslında bir dezavantajlı wrt tipindedir.
Raphael

Bu nedenle, çalışma zamanı, derlenmiş bir dilden daha karmaşıktır çünkü çalışma ortamı optimize etmek için veri toplamalıdır.
saadtaame,

2
Birçok durumda, bir JIT yerine mümkün olmaz mkontrol etmediği bir sürümü ile ko kanıtlamak mümkün olacağını beri molurdu asla olmayan bir sıfır ile çağrılabilir k, ancak bu bile o yerini alabilir kanıtlamak mümkün olmadan onunla static miss_count; if (k==0) return a.length+b.length-7; else if (miss_count++ < 16) { ... unoptimized code for m ...} else { ... consider other optimizations...}.
supercat,

1
@Supercat ile aynı fikirdeyim ve örneğinizin aslında oldukça yanıltıcı olduğunu düşünüyorum. Sadece k=0 her zaman ise , bunun girdi veya ortamın bir işlevi olmadığı anlamına gelir, testi bırakmak güvenlidir - ancak bunun belirlenmesi çok pahalı ve dolayısıyla derleme zamanında uygun maliyetli olan statik analiz gerektirir. Bir JIT, bir kod bloğundan geçen bir yol diğerlerinden çok daha sık alındığında kazanabilir ve bu yol için uzmanlaşmış bir kodun sürümü daha hızlı olacaktır. Ancak JIT, hızlı yolun uygulanıp uygulanmadığını kontrol etmek için bir test yayacak ve eğer değilse "yavaş yolu" izleyecektir.
j_random_hacker

Örnek: Bir işlev bir Base* pparametre alır ve bunun üzerinden sanal işlevleri çağırır; çalışma zamanı analizi, her zaman (veya hemen hemen her zaman) işaret edilen gerçek nesnenin Derived1türünde olduğunu gösterir. JIT, işlevin yeni bir sürümünü, Derived1yöntemlere statik olarak çözümlenmiş (hatta satır içi) çağrılarla üretebilir . Bu kodun önünde, seçilebilir pişaretçinin beklenen Derived1tabloya işaret edip etmediğini kontrol eden bir şartlı kural gelir ; eğer değilse, bunun yerine yavaş yavaş dinamik olarak çözülmüş yöntem çağrıları ile fonksiyonun orijinal versiyonuna atlar.
j_random_hacker 4:18
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.