C # JIT derlemesi ve .NET


87

JIT derleyicisinin nasıl çalıştığına dair ayrıntılar konusunda biraz kafam karıştı. C # 'ın IL'ye derlendiğini biliyorum. İlk çalıştırıldığında JIT'dedir. Bu, yerel koda çevrilmesini içeriyor mu? .NET çalışma zamanı (Sanal Makine olarak mı?) JIT koduyla etkileşime giriyor mu? Bunun safça olduğunu biliyorum ama gerçekten kafam karıştı. Benim izlenimim her zaman derlemelerin .NET Runtime tarafından yorumlanmadığı, ancak etkileşimin ayrıntılarını anlamadığım oldu.

Yanıtlar:


84

Evet, JIT'ing IL kodu, IL'nin yerel makine talimatlarına dönüştürülmesini içerir.

Evet, .NET çalışma zamanı JIT'lenmiş yerel makine koduyla, çalışma zamanının yerel makine kodu tarafından işgal edilen bellek bloklarına sahip olması, çalışma zamanı çağrıları yerel makine koduna vb.

.NET çalışma zamanının derlemelerinizdeki IL kodunu yorumlamadığı konusunda haklısınız.

Yürütme, henüz JIT yerel makine kodunda derlenmemiş bir işleve veya kod bloğuna (bir if bloğunun başka bir cümlesi gibi) ulaştığında olan şey, bu IL bloğunu yerel makine koduna derlemek için JIT'r çağrılır. . Bu yapıldığında, program yürütme, program mantığını yürütmek için yeni gönderilen makine kodunu girer. Bu yerel makine kodu yürütmesi yürütülürken, makine koduna henüz derlenmemiş bir işleve yönelik bir işlev çağrısına ulaşırsa, JIT'r bu işlevi "tam zamanında" derlemek için çağrılır . Ve bunun gibi.

JIT'r, bir işlev gövdesinin tüm mantığını aynı anda makine koduna derlemek zorunda değildir. Fonksiyonda if ifadeleri varsa, if veya else cümlelerinin ifade blokları, yürütme gerçekten bu bloktan geçene kadar JIT derlenemez. Yürütülmemiş kod yolları, yürütülene kadar IL formunda kalır.

Derlenen yerel makine kodu bellekte tutulur, böylece kodun bir sonraki bölümü çalıştırıldığında tekrar kullanılabilir. Bir işlevi ikinci kez çağırdığınızda, onu ilk çağırdığınızdan daha hızlı çalışacaktır çünkü ikinci seferde JIT adımına gerek yoktur.

Masaüstü .NET'te, yerel makine kodu, uygulama etki alanının ömrü boyunca bellekte tutulur. .NET CF'de, uygulamanın belleği azaldığında yerel makine kodu atılabilir. Yürütme bu koddan bir sonraki sefer geçtiğinde orijinal IL kodundan tekrar JIT derlenecektir.


14
Küçük bilgiçlik düzeltmesi - 'JIT'r, bir işlev gövdesinin tüm mantığını derlemek zorunda değildir' - Durum olabilecek teorik bir uygulamada, ancak .NET çalışma zamanının mevcut uygulamalarında, JIT derleyicisi bütün Tek seferde yöntemler.
Paul Alexander

18
Bunun neden yapıldığına gelince , bunun başlıca nedeni jit olmayan bir derleyicinin belirli optimizasyonların herhangi bir hedef platformda mevcut olduğunu varsayamamasıdır. Tek seçenek, ya en düşük ortak paydaya derlemek ya da daha yaygın olarak, her biri kendi platformunu hedefleyen birden çok sürümü derlemektir. JIT bu dezavantajı ortadan kaldırır çünkü makine koduna son çeviri, derleyicinin hangi optimizasyonların mevcut olduğunu bildiği hedef makinede yapılır.
Chris Shain

1
Chris, JIT'in hangi optimizasyonların mevcut olduğunu bildiğini düşünse bile, önemli optimizasyonları uygulamak için zamanı yoktur. Muhtemelen NGEN daha güçlüdür.
Grigory

2
@Grigory Evet, NGEN, JIT derleyicisinin sahip olmadığı bir zaman lüksüne sahiptir, ancak JIT'in derlenen kodun performansını artırmak için verebileceği ve çözmesi çok zaman almayan pek çok kod üreteci kararı vardır. Örneğin, JIT derleyicisi, JIT derleme adımına önemli bir süre eklemeden çalışma zamanında bulunan mevcut donanımla en iyi eşleşecek komut setlerini seçebilir. .NET JITter'in bunu herhangi bir önemli şekilde yaptığını sanmıyorum, ancak bu mümkündür.
dthorpe

24

Kod, derleme biçimine benzeyen Microsoft Ara Diline "derlenir".

Bir yürütülebilir dosyayı çift tıkladığınızda, Windows yüklenir mscoree.dllve ardından CLR ortamını kurar ve programınızın kodunu başlatır. JIT derleyicisi, programınızdaki MSIL kodunu okumaya başlar ve kodu dinamik olarak CPU'nun yürütebileceği x86 komutlarına derler.


2

IL kodunun yerel CPU komutlarına derlenmesini aşağıdaki örnekle açıklayacağım.

public class Example 
{
    static void Main() 
    {
        Console.WriteLine("Hey IL!!!");
    }
}

Öncelikle CLR, türle ilgili her ayrıntıyı ve bu türden hangi yöntemin meta verilerden kaynaklandığını bilir.

CLR, IL'yi yerel CPU talimatına yürütmeye başladığında, bu sefer CLR, Main'in kodu tarafından referans verilen her tür için dahili veri yapılarını tahsis eder.

Bizim durumumuzda yalnızca bir tür Konsolumuz var, bu nedenle CLR bir dahili veri yapısı tahsis edecektir. Bu iç yapı aracılığıyla, başvurulan türlere erişimi yöneteceğiz.

Bu veri yapısının içinde CLR, bu tür tarafından tanımlanan tüm yöntemlerle ilgili girişlere sahiptir. Her giriş, yöntemin uygulamasının bulunabileceği adresi tutar.

Bu yapıyı başlatırken, CLR , CLR'nin kendisinde bulunan belgelenmemiş FUNCTION'daki her girişi ayarlar . Ve tahmin edebileceğiniz gibi, bu FONKSİYON JIT Compiler dediğimiz şeydir.

Genel olarak, JIT Compiler'ı, IL'yi yerel CPU komutlarına derleyen bir CLR işlevi olarak düşünebilirsiniz. Size bu sürecin örneğimizde nasıl olacağını ayrıntılı olarak göstereyim.

1. Main, WriteLine'a ilk çağrısını yaptığında, JITCompiler işlevi çağrılır.

2. JIT Derleyici işlevi, hangi yöntemin çağrıldığını ve bu yöntemi hangi türün tanımladığını bilir.

3. Ardından Jit Compiler, bu türün tanımlandığı derlemeyi arar ve WriteLine yönteminin IL kodundaki durumumuzda bu tür tarafından tanımlanan yöntem için IL kodunu alır.

4. JIT derleyicisi DYNAMIC bellek bloğunu ayırır, bundan sonra JIT, IL kodunu doğrular ve yerel CPU koduna derler ve bu CPU kodunu bu bellek bloğuna kaydeder .

5. Daha sonra JIT derleyicisi, dahili veri yapısı girişine geri döner ve adresi (birincil olarak WriteLine'ın IL kodu uygulamasına atıfta bulunur), WriteLine'ın yerel CPU talimatlarını içeren yeni dinamik olarak oluşturulmuş bellek bloğu ile değiştirir.

6. Son olarak, JIT Compiler işlevi bellek bloğundaki koda atlar ve writeline yönteminin yerel kodunu yürütür.

7. WriteLine çalıştırıldıktan sonra kod, normal şekilde çalışmaya devam eden Ana Kod'a geri döner.


1

.NET, bazen IL olarak kısaltılan MSIL adlı bir ara dil kullanır. Derleyici kaynak kodunuzu okur ve MSIL üretir. Programı çalıştırdığınızda, .NET Tam Zamanında (JIT) derleyicisi MSIL kodunuzu okur ve bellekte yürütülebilir bir uygulama oluşturur. Bunların hiçbirini görmeyeceksiniz, ancak perde arkasında neler olduğunu bilmek iyi bir fikirdir.


0

.NET Framework, IL olarak da adlandırılan MSIL'i (Microsoft Ara Dili) üretmek için CLR Ortamını kullanır. Derleyici kaynak kodunuzu okur ve projenizi oluşturduğunuzda / derlediğinizde MSIL oluşturur. Şimdi, sonunda projenizi çalıştırdığınızda, .NET JIT ( Just-in-time Compiler ) girer. JIT, MSIL kodunuzu okur ve CPU tarafından kolayca yürütülebilen yerel kodu (x86 talimatları olan) üretir. JIT tüm MSIL komutlarını okur ve bunları Satır Satır yürütür.

Perde arkasında neler olduğunu görmekle ilgileniyorsanız, zaten cevaplanmıştır. Lütfen takip edin - İşte

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.