Ders 13 / 16
Derleyici, Yorumlayıcı ve Sanal Makine
Kaynak kodun yürütülmesine giden üç model, aralarındaki ödünleşimler ve dil ile gerçekleştirim ayrımı.
İçindekiler
Önceki konu, işlemcinin bellekteki bit örüntülerini komut olarak yürüttüğünü kurdu. Programcı ise bit örüntüsü yazmaz; okunabilir bir metin yazar. Aradaki mesafeyi bir program kapatır.
Bu konunun sorusu şudur: sonuc = a + b satırı, işlemcinin yürütebileceği komutlara
nasıl dönüşür? Bu ders, dönüşümün ne zaman yapıldığına göre ayrışan üç modeli
tanımlar; sonraki dersler dönüşümün kendisini adım adım ele alacaktır.
Kaynak Kod Bir Metindir
Kaynak dosya, karakter kodlamaları dersinde tanımlanan kurallara göre yazılmış bir bayt
dizisidir. İçindeki if, + veya değişken adları, bilgisayar için henüz anlam taşımaz;
yalnızca karakterlerdir.
Bu metni yürütülebilir bir davranışa çevirmenin üç yolu vardır. Üçü de aynı işi yapar, farkları çevirinin ne zaman yapıldığındadır.
Derleme
Derleyici (compiler), kaynak metnin tamamını çalıştırmadan önce hedef makinenin komutlarına çevirir. Çıktı, doğrudan yürütülebilen bir dosyadır.
Sonuçları:
- Çalışma anında çeviri maliyeti yoktur; program doğrudan işlemci hızında yürür.
- Derleyici tüm programı gördüğü için kapsamlı eniyileme yapabilir.
- Hataların bir bölümü çalıştırmadan önce, derleme sırasında yakalanır.
- Çıktı belirli bir komut kümesine ve işletim sistemine bağlıdır; başka bir platform için yeniden derleme gerekir.
- Kaynaktaki her değişiklik, çalıştırmadan önce bir derleme adımı gerektirir.
Yorumlama
Yorumlayıcı (interpreter), kaynağı önceden çevirmez; yapıları sırayla okur ve karşılık gelen işlemleri kendisi yürütür. Program çalışırken çeviri de sürer.
Sonuçları:
- Aynı kaynak, yorumlayıcısı bulunan her platformda çalışır; ayrı derleme gerekmez.
- Yazma ve çalıştırma arasındaki döngü kısadır.
- Her yapı, yürütüldüğü her seferde yeniden çözümlenir; bu, komut başına sabit bir maliyet ekler.
- Hataların çoğu, ilgili satır çalışana kadar görünmez.
Önbellek dersindeki hesabın neden zamanlama ölçümüyle gösterilmediği burada açıklanır: yorumlama maliyeti eleman başına sabit bir yük eklediğinde, bellek davranışından gelen fark bu yükün altında kalır.
Sanal Makine ve Bayt Kodu
Üçüncü model ikisini birleştirir. Kaynak, gerçek bir işlemcinin komut kümesine değil, sanal makine (virtual machine) adı verilen tasarlanmış bir makinenin komut kümesine çevrilir. Bu ara gösterime bayt kodu (bytecode) denir.
Bayt kodu, kaynak metinden kompakt ve çözümlenmesi ucuz; makine kodundan ise platformdan bağımsızdır. Sanal makine, bayt kodunu yürüten programdır; her platform için bir sanal makine yazmak, her platform için ayrı derleyici yazmaktan azdır.
Ara katmanın bedeli hızdır: bayt kodunu yürütmek, yerel komutları yürütmekten yavaştır. Anında derleme (just-in-time compilation) bu bedeli azaltır. Sanal makine, çalışırken sık yürütülen bölümleri saptar ve onları yerel makine koduna çevirir. Çeviri maliyeti bir kez ödenir, kazanç her tekrarda alınır.
Anında derlemenin iki gözlenebilir sonucu vardır. Birincisi ısınma: programın ilk turları sonrakilerden yavaştır, bu yüzden başarım ölçümleri ilk turlar atlanarak yapılır. İkincisi, çalışma anındaki bilginin kullanılabilmesidir; derleyici, hangi dalın gerçekte sık alındığını bilmeden tahmin ederken, anında derleyici gözlemleyerek karar verebilir.
Dil ile Gerçekleştirimi Ayırmak
Yaygın bir karışıklık, bu modellerin dilin kendisine ait olduğunu sanmaktır. “Derlenen dil” ve “yorumlanan dil” ifadeleri yanıltıcıdır.
Bir dil, sözdizimi ve anlamıyla tanımlanır; nasıl yürütüleceği gerçekleştirimin kararıdır. Aynı dilin hem derleyicisi hem yorumlayıcısı yazılabilir ve pratikte yazılmıştır. Yorumlanmakla bilinen dillerin derleyicileri, derlenmekle bilinen dillerin yorumlayıcıları vardır.
Doğru cümle şudur: bu dilin bu gerçekleştirimi, kaynağı bayt koda çevirip sanal makinede yürütür. Bu ayrım, bir dilin başarımı hakkındaki iddiaların hangi düzeye ait olduğunu görmeyi sağlar.
Çeviriciyi Kim Çevirir
Derleyici de bir programdır ve o da bir dilde yazılmıştır. Bu, ilk bakışta döngüsel görünen bir soru doğurur: bir dilin ilk derleyicisi hangi dille yazılır?
Yanıt basittir: başka bir dille. Yeni dilin ilk derleyicisi, var olan bir dilde yazılır ve dilin küçük bir alt kümesini çevirebilir. Bu derleyici çalışır hâle geldiğinde, dilin derleyicisi kendi diliyle yeniden yazılabilir ve ilk derleyiciyle derlenir. Bundan sonra derleyici kendi kendini derler; buna kendi kendini barındıran (self-hosting) derleyici denir.
Aynı akıl yürütme yorumlayıcılar ve sanal makineler için de geçerlidir. Zincirin en altında her zaman, o platformda hâlihazırda çalışan bir program bulunur.
Bunun pratik sonucu, bir dilin yürütme modelinin dilin tanımına değil, ekosistemin tarihine bağlı olmasıdır. Aynı dil için sonradan yazılan bir gerçekleştirim, bambaşka bir model seçebilir.
Üç Modelin Karşılaştırması
| Ölçüt | Derleme | Yorumlama | Sanal makine |
|---|---|---|---|
| Çeviri zamanı | Çalıştırmadan önce | Çalışırken sürekli | Önce bayt koda, sonra çalışırken |
| Taşınabilirlik | Hedef platforma bağlı | Yorumlayıcı olan her yerde | Sanal makine olan her yerde |
| Yürütme hızı | En yüksek | En düşük | Arada; anında derleme ile artar |
| Geri bildirim döngüsü | Derleme adımı gerektirir | En kısa | Kısa |
| Hata yakalama | Derleme sırasında bir bölümü | Çalışma anında | İkisi arası |
Sınırlar keskin değildir. Derlenen bir dilin çalışma zamanı kütüphanesi olabilir; yorumlanan bir dil, kaynağı önce ara gösterime çevirebilir. Modeller, gerçek gerçekleştirimlerin üzerine oturduğu eksenlerdir.
İki Aşamayı Görmek
Python, bu üç modelin ikincisi ve üçüncüsü arasında durur: kaynak önce bayt koda çevrilir, sonra sanal makinede yürütülür. İki aşama ayrı ayrı çağrılabilir:
kaynak = "sonuc = a + b" kod = compile(kaynak, "<ornek>", "exec") # birinci aşama: metin -> kod nesnesi print(type(kod)) # <class 'code'> print(kod.co_names) # ('a', 'b', 'sonuc') ortam = {"a": 10, "b": 4} exec(kod, ortam) # ikinci aşama: yürütme print(ortam["sonuc"]) # 14 import dis dis.dis(kod) # üretilen bayt kodun listesi
compile çağrısı hiçbir şey yürütmez; yalnızca metni çözümleyip bir kod nesnesi
üretir. Yürütme, exec çağrısıyla ayrıca başlatılır. İki adımın ayrılabilmesi,
çevirinin yürütmeden farklı bir iş olduğunun doğrudan kanıtıdır.
dis çıktısındaki komut adları ve sayısı, gerçekleştirimin sürümüne göre değişir; bayt
kodu bir standart değil, sanal makinenin iç ayrıntısıdır. Kararlı olan, listenin
varlığıdır: kaynak metin, yürütülmeden önce bir komut dizisine dönüşmüştür.
Özet
- Kaynak kod bir metindir; yürütülebilmesi için makine komutlarına çevrilmesi gerekir.
- Derleyici çeviriyi çalıştırmadan önce yapar: hız ve derleme zamanı hata yakalama sağlar, çıktı platforma bağlıdır.
- Yorumlayıcı çeviriyi çalışırken yapar: taşınabilirlik ve kısa geri bildirim döngüsü sağlar, komut başına maliyet ekler.
- Sanal makine modeli, kaynağı platformdan bağımsız bayt koda çevirir; anında derleme sık yürütülen bölümleri yerel koda çevirerek aradaki farkı kapatır.
- Derlenme veya yorumlanma dilin değil, gerçekleştirimin özelliğidir.
- Bir dilin ilk çeviricisi başka bir dille yazılır; sonrasında kendi kendini derleyen bir çeviriciye geçilebilir.
Sonraki Adım
Bu ders çevirinin ne zaman yapıldığını ele aldı; nasıl yapıldığını değil. Sonraki ders, kaynak metnin karakterlerden komutlara giden yolunu aşama aşama açacak: sözcüklere ayırma, yapıyı çıkarma, anlam denetimi ve kod üretimi.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.