genel bakış
Bir yorumlayıcı dil için X herhangi bir program yürüten bir program (veya bir makine ya da genel olarak mekanizmanın sadece bir tür) bir p dili ile yazılmış X bu etkiler yapar ve tarifname tarafından öngörülen sonuçları değerlendirir bu şekilde X . Modern yüksek performanslı iş istasyonu CPU'ları aslında ondan daha karmaşık olmasına rağmen, CPU'lar genellikle kendi talimat kümeleri için tercümanlardır; aslında altında yatan özel bir özel talimat setine sahip olabilirler ve dışarıdan görülebilen kamu talimat setini çevirir (derler) veya yorumlarlar.
Bir derleyici gelen X ile Y herhangi bir program çeviren bir program (veya bir makine ya da genel olarak mekanizmanın sadece bir tür) bir p bir dil gelen X bir anlama sahip programı içine p ' bir dil içinde Y bir şekilde bu semantik Programın korunması, yani p'nin Y için bir tercümanla yorumlanmasının aynı sonuçları vereceği ve p'nin X için bir tercüman ile aynı etkilere sahip olacağı kaydedilmiştir . ( X ve Y'nin aynı dil olabileceğini unutmayın .)
Terimleri Öncesi-of-Time (AOT) ve Just-in-Time (JIT) atıfta zaman derleme gerçekleşir: o açıdan anılacaktır "zaman" "çalışma zamanı" dir, yani bir JIT derleyicisi programı derleyen olduğu gibi çalışırken , bir AOT derleyicisi programı çalıştırmadan önce derler . Bunun, X dilinden Y diline kadar bir JIT derleyicisinin bir şekilde Y dili için bir tercümanla birlikte çalışması gerektiğini unutmayın.Aksi takdirde, programı çalıştırmanın bir yolu olmazdı. (Örneğin, JavaScript'i x86 koduna göre derleyen bir JIT derleyicisi, bir x86 CPU'su olmadan bir anlam ifade etmiyor; programı çalışırken derliyor, ancak x86 CPU'su olmadan program çalışmıyor.)
Bu ayrımın tercümanlar için bir anlamı olmadığını unutmayın: Bir tercüman programı çalıştırır. Bir programı çalıştırmadan önce çalıştıran bir AOT yorumlayıcısı veya çalışırken bir programı çalıştıran bir JIT yorumlayıcısı fikri saçmadır.
Böylece sahibiz:
- AOT derleyici: çalıştırmadan önce derler
- JIT derleyicisi: çalışırken derlenir
- tercüman: çalışır
JIT Derleyicileri
JIT derleyicileri ailesinde, tam olarak ne zaman derlendikleri, ne sıklıkta ve hangi ayrıntı derecelerinde olduğu konusunda hala birçok fark vardır .
Örneğin, Microsoft’un CLR’sindeki JIT derleyicisi yalnızca bir kez (yüklendiğinde) kodu derler ve bir seferde bütün bir derlemeyi derler. Diğer derleyiciler, program çalışırken bilgi toplayabilir ve kodu daha iyi optimize etmelerine olanak sağlayan yeni bilgiler mevcut olduğunda birkaç kez yeniden derleyebilir. Bazı JIT derleyicileri kodu bile en iyi duruma getirme yeteneğine sahiptir . Şimdi, neden birisinin bunu yapmak istediğini kendinize sorabilirsiniz. De-optimizing, gerçekten güvensiz olabilecek çok agresif optimizasyonlar yapmanıza olanak tanır: çok agresif olursanız, sadece tekrar geri çekilebilirsiniz, oysa, optimizasyon yapamayan bir JIT derleyicisini tekrar çalıştırabilirsiniz. ilk etapta agresif optimizasyonlar.
JIT derleyicileri ya bir hareket halindeyken bazı statik kod birimlerini derleyebilir (örneğin bir modül, bir sınıf, bir işlev, bir yöntem,…; bunlar genellikle bir kerede yöntem JIT olarak adlandırılır ) veya dinamiği izleyebilirler . kodunun çalışması dinamik bulmak izleri daha sonra (bu denir derlenir (tipik olarak döngüler) izleme JITs).
Tercüman ve Derleyicileri Birleştirme
Tercümanlar ve derleyiciler tek bir dil yürütme motorunda birleştirilebilir. Bunun yapıldığı iki tipik senaryo var.
Bir AOT derleyici birleştiren X için Y için bir tercüman Y . Burada, genellikle X'in insanlar tarafından okunabilmesi için optimize bazı üst düzey dil oysa olduğu YMakinelerin yorumlanabilirliği için optimize edilmiş kompakt bir dildir (genellikle bir tür bytecode). Örneğin, CPython Python yürütme altyapısı, Python kaynak kodunu CPython bayt koduyla derleyen bir AOT derleyicisine ve CPython bayt kodunu yorumlayan bir tercümana sahiptir. Aynı şekilde, YARV Ruby yürütme motorunda Ruby kaynak kodunu YARV bayt koduna derleyen bir AOT derleyicisi ve YARV bayt kodunu yorumlayan bir tercüman bulunur. Bunu neden yapmak istiyorsun? Ruby ve Python hem çok üst düzeyde hem de biraz karmaşık dillerdir, bu yüzden önce bunları ayrıştırması ve yorumlanması daha kolay bir dilde derliyoruz, sonra da o dili yorumluyoruz .
Bir tercümanı ve bir derleyiciyi birleştirmenin diğer bir yolu karma modlu bir yürütme motorudur. Burada, uygulamak için iki "mod" "mix" aynı yani birlikte bir tercüman dilini X ve bir JIT derleyicisi X için Y . (Yani, buradaki fark, yukarıdaki durumda, programı derleyen derleyiciyle birden fazla "aşamaya" sahip olduğumuz ve daha sonra sonucu tercümana beslediğimiz, burada aynı dilde iki yan yana çalıştığımız . ) Bir derleyici tarafından derlenen kod, tercüman tarafından yürütülen koddan daha hızlı çalışma eğilimindedir, ancak gerçekte kodun derlenmesi zaman alır (ve özellikle kodu çalıştırmak için yoğun bir şekilde optimize etmek istiyorsanız)çok hızlı, çok zaman alıyor). Bu nedenle, JIT derleyicisinin kodu derlemeye meşgul olduğu bu köprüde bulunmak için tercüman kodu çalıştırmaya başlayabilir ve JIT derlemesi bittiğinde, yürütmeyi derlenmiş koda geçirebiliriz. Bu, derlenmiş kodun mümkün olan en iyi performansını elde ettiğimiz anlamına gelir, ancak derlemenin bitmesini beklememiz gerekmez ve uygulamamız derhal çalışmaya başlar (olabildiğince hızlı olmasa da).
Bu aslında karma modlu bir yürütme motorunun mümkün olan en basit uygulamasıdır. Örneğin, derhal derlemeye başlamayacak, ancak tercümanın bir süreliğine çalışmasına izin verecek ve istatistik, profil bilgileri, tip bilgileri, hangi koşullu branşların alınma olasılığı ile ilgili bilgiler, hangi yöntemlerin çağrıldığı en çok vb. ve daha sonra daha dinamik bir kod üretebilmesi için bu dinamik bilgileri derleyiciye besleyin. Bu aynı zamanda yukarıda bahsettiğim de-optimizasyonu uygulamanın bir yoludur: optimizasyonda çok agresif olduğunuz ortaya çıkarsa, kodu atıp (bir kısmına) tekrar yorumlamaya geri dönebilirsiniz. Örneğin HotSpot JVM bunu yapar. Hem JVM bytecode için bir tercüman hem de JVM bytecode için bir derleyici içerir. (Aslında,iki derleyici!)
İlk derler bir AOT derleyici olmak üzere iki faz: Aynı zamanda, mümkün olan ve bu iki yaklaşım birleştirme için ortak aslında X için Y ve ikinci faz, her ikisi de yorumlayan bir karışık modlu motoru olan Y ve derler Y için Z . Rubinius Ruby yürütme motoru bu şekilde çalışır, örneğin: Ruby kaynak kodunu Rubinius bytecode'a derleyen bir AOT derleyicisine ve ilk olarak Rubinius bytecode'unu yorumlayan karışık modlu bir motora sahiptir. makine kodu.
Tercümanın karışık modlu bir yürütme motoru durumunda oynadığı, yani hızlı çalıştırmanın sağlanması ve ayrıca potansiyel olarak bilgi toplama ve geri dönüş yeteneği sağlama rolünün alternatif olarak ikinci bir JIT derleyicisi tarafından da oynanabileceğini unutmayın. Örneğin V8 böyle çalışır. V8 asla yorum yapmaz, daima derlenir. İlk derleyici çok hızlı başlayan çok hızlı, çok ince bir derleyicidir. Ürettiği kod çok hızlı değil. Bu derleyici aynı zamanda oluşturduğu koda profil kodunu da enjekte eder. Diğer derleyici yavaştır ve daha fazla bellek kullanır, ancak çok daha hızlı kod üretir ve ilk derleyici tarafından derlenen kodu çalıştırarak toplanan profilleme bilgilerini kullanabilir.