İki tür programlama dili vardır: çöp toplayıcı programlama dilleri ve manuel bellek yönetimi gerektiren programlama dilleri. Bunların yanı sıra Kotlin, PHP veya Java da buna örnek gösterilebilir. C, C++ veya Rust, bu tür programlama dillerine örnek olarak verilebilir. Genel bir kural olarak, üst düzey programlama dillerinde standart bir özellik olarak çöp toplama işlevinin bulunması daha olasıdır. Bu blog yayınında, bu tür çöp toplayıcı programlama dilleri ve bunların WebAssembly'e (Wasm) nasıl derlenebileceği ele alınmaktadır. Peki, öncelikle, çöp toplama (genellikle GC olarak adlandırılır) nedir?
Tarayıcı Desteği
Atık toplama
Basitleştirilmiş bir ifadeyle, program tarafından ayrılmış ancak artık referans verilmeyen belleği geri alma girişimi, çöp toplama fikridir. Bu tür hafızalara "çöp" denir. Çöp toplama işlemini uygulamak için birçok strateji vardır. Bunlardan biri, amaç bellekteki nesnelere yapılan referansların sayısını saymak olan referans sayımı. Bir nesneye artık referans verilmediğinde, artık kullanılmadığı ve çöp toplama işlemine hazır olduğu işaretlenebilir. PHP'nin çöp toplayıcısı referans sayımı kullanır. Xdebug uzantısının xdebug_debug_zval()
işlevini kullanarak çöp toplayıcının işleyişine göz atabilirsiniz. Aşağıdaki PHP programını düşünün.
<?php
$a= (string) rand();
$c = $b = $a;
$b = 42;
unset($c);
$a = null;
?>
Program, bir dizeye atanmış rastgele bir sayıyı a
adlı yeni bir değişkene atar. Daha sonra, b
ve c
adlı iki yeni değişken oluşturup bunlara a
değerini atar. Bunun ardından b
, 42
numarasına yeniden atanır ve c
ayarı kaldırılır. Son olarak a
değerini null
olarak ayarlar. Programın her adımını xdebug_debug_zval()
ile notlandırarak çöp toplayıcının referans sayacını çalışırken görebilirsiniz.
<?php
$a= (string) rand();
$c = $b = $a;
xdebug_debug_zval('a');
$b = 42;
xdebug_debug_zval('a');
unset($c);
xdebug_debug_zval('a');
$a = null;
xdebug_debug_zval('a');
?>
Yukarıdaki örnekte aşağıdaki günlükler oluşturulur. Bu günlüklerde, a
değişkeninin değerine yapılan referansların her adımdan sonra nasıl azaldığını görürsünüz. Bu durum, kod sırası göz önüne alındığında mantıklı bir durumdur. (Rastgele sayınız elbette farklı olacaktır.)
a:
(refcount=3, is_ref=0)string '419796578' (length=9)
a:
(refcount=2, is_ref=0)string '419796578' (length=9)
a:
(refcount=1, is_ref=0)string '419796578' (length=9)
a:
(refcount=0, is_ref=0)null
Çöp toplamayla ilgili döngüleri algılama gibi başka zorluklar da vardır ancak bu makale için referans sayımını temel düzeyde anlamak yeterlidir.
Programlama dilleri diğer programlama dillerinde uygulanır
Bu, başlangıç gibi görünebilir ancak programlama dilleri diğer programlama dillerinde uygulanır. Örneğin, PHP çalışma zamanı öncelikle C dilinde uygulanır. GitHub'da PHP kaynak koduna göz atabilirsiniz. PHP'nin atık toplama kodu çoğunlukla zend_gc.c
dosyasında bulunur. Çoğu geliştirici, PHP'yi işletim sisteminin paket yöneticisi aracılığıyla yükler. Ancak geliştiriciler PHP'yi kaynak kodundan da derleyebilirler. Örneğin, bir Linux ortamında ./buildconf && ./configure && make
adımlarıyla, Linux çalışma zamanı için PHP oluşturulur. Ancak bu, PHP çalışma zamanının Wasm gibi diğer çalışma zamanları için derlenebileceği anlamına da gelir.
Dilleri Wasm çalışma zamanına taşımanın geleneksel yöntemleri
PHP'nin çalıştığı platformdan bağımsız olarak PHP komut dosyaları aynı bayt koduna derlenir ve Zend Engine tarafından çalıştırılır. Zend Engine, PHP komut dosyası dili için bir derleyici ve çalışma zamanı ortamıdır. Zend Derleyici ve Zend Yürütücüsü, Zend Sanal Makinesi'nden (VM) oluşur. C gibi diğer yüksek düzey dillerde uygulanan PHP gibi diller genellikle Intel veya ARM gibi belirli mimarileri hedefleyen optimizasyonlara sahiptir ve her mimari için farklı bir arka uç gerektirir. Bu bağlamda Wasm yeni bir mimariyi temsil eder. Sanal makinede "tam zamanında" (JIT) veya önceden (AOT) derleme gibi mimariye özgü bir kod varsa geliştirici, yeni mimari için bir JIT/AOT arka ucu da uygular. Bu yaklaşım çok mantıklıdır çünkü kod tabanının ana kısmı çoğu zaman her yeni mimari için yeniden derlenebilir.
Wasm'in düşük seviyeli olması nedeniyle burada da aynı yaklaşımı denemek doğaldır: Ana sanal makine kodunu, ayrıştırıcısı, kütüphane desteği, çöp toplama ve optimize edicisiyle birlikte Wasm olarak yeniden derleyin ve gerekirse Wasm için JIT veya AOT arka ucu uygulayın. Bu, Wasm MVP'den beri mümkün olmuştur ve birçok durumda pratikte iyi sonuç verir. WordPress Playground'u destekleyen şey aslında Wasm için derlenmiş PHP'dir. WordPress Playground ve WebAssembly ile tarayıcı içi WordPress deneyimleri oluşturma makalesinde proje hakkında daha fazla bilgi edinebilirsiniz.
Ancak PHP Wasm, tarayıcısında ana dil JavaScript bağlamında çalışır. Chrome'da JavaScript ve Wasm, Google'ın ECMAScript'i ECMA-262'da belirtildiği şekilde uygulayan açık kaynak JavaScript motoru V8'de çalıştırılır. V8'in zaten bir çöp toplayıcısı vardır. Bu, örneğin Wasm'e derlenmiş PHP kullanan geliştiricilerin, aktarılan dilin (PHP) bir çöp toplayıcı uygulamasını, zaten çöp toplayıcısı olan tarayıcıya gönderdiği anlamına gelir. Bu da kulağa geldiği kadar israftır. İşte bu noktada WasmGC devreye girer.
Wasm modüllerinin Wasm'in doğrusal belleği üzerine kendi GC'lerini oluşturmasına izin verme şeklindeki eski yaklaşımın diğer sorunu, Wasm'in kendi çöp toplayıcısı ile Wasm'e derlenmiş dilin üzerine inşa edilmiş çöp toplayıcısı arasında hiçbir etkileşim olmamasıdır. Bu durum, bellek sızıntıları ve verimsiz toplama girişimleri gibi sorunlara neden olur. Wasm modüllerinin mevcut yerleşik GC'yi yeniden kullanmasına izin vermek bu sorunları önler.
WasmGC ile programlama dillerini yeni çalışma zamanlarına taşıma
WasmGC, WebAssembly Topluluk Grubu'nun bir önerisidir. Mevcut Wasm MVP uygulaması, doğrusal bellekte yalnızca sayılarla (yani tam sayılar ve kayan noktalı sayılar) işlem yapabilir. Referans türleri önerisi kullanıma sunulduğunda Wasm, harici referansları da tutabilir. WasmGC artık yapı ve dizi yığın türleri ekliyor. Bu da doğrusal olmayan bellek ayırma desteği anlamına geliyor. Her WasmGC nesnesi sabit bir türe ve yapıya sahiptir. Bu, VM'lerin JavaScript gibi dinamik dillerin sahip olduğu optimizasyondan çıkarma riski olmadan alanlarına erişmek için verimli kod oluşturmasını kolaylaştırır. Böylece bu teklif, Wasm'i hedefleyen dil derleyicilerin ana makine sanal makinesindeki bir çöp toplayıcı ile entegre olmasını sağlayan struct ve dizi yığın türleri aracılığıyla WebAssembly'ye üst düzey yönetilen diller için etkili destek sağlar. Basit bir şekilde ifade etmek gerekirse bu, WasmGC ile bir programlama dilinin Wasm'a taşınması, artık programlama dilinin çöp toplayıcısının artık bağlantı noktasının parçası olması gerekmediği anlamına gelir. Bunun yerine mevcut çöp toplayıcı kullanılabilir.
Bu iyileştirmenin gerçek dünyadaki etkisini doğrulamak için Chrome'un Wasm ekibi C, Rust ve Java'dan Fannkuch karşılaştırması (çalışırken veri yapılarını ayırır) sürümlerini derledi. C ve Rust ikili programları, çeşitli derleyici işaretlerine bağlı olarak 6.1 K ile 9,6 K arasında olabilirken Java sürümü sadece 2.3 K ile çok daha küçüktür! C ve Rust'ta çöp toplayıcı bulunmasa da belleği yönetmek için malloc/free
paketlenir. Java'nın burada daha küçük olmasının nedeni, bellek yönetimi kodunu paketlemesi gerekmemesidir. Bu, tek bir spesifik örnek olsa da WasmGC ikili programlarının çok küçük olma potansiyeline sahip olduğunu gösteriyor. Hatta boyut optimizasyonuyla ilgili önemli bir çalışmadan önce bile bu durum söz konusu.
WasmGC tarafından desteklenen bir programlama dilini iş başında görme
Kotlin Wasm
WasmGC sayesinde Wasm'e taşınan ilk programlama dillerinden biri, Kotlin/Wasm biçiminde Kotlin'dir. Kotlin ekibi tarafından sağlanan kaynak kodu içeren demo aşağıdaki girişte gösterilmektedir.
import kotlinx.browser.document
import kotlinx.dom.appendText
import org.w3c.dom.HTMLDivElement
fun main() {
(document.getElementById("warning") as HTMLDivElement).style.display = "none"
document.body?.appendText("Hello, ${greet()}!")
}
fun greet() = "world"
Yukarıdaki Kotlin kodu temel olarak Kotlin'e dönüştürülmüş JavaScript OM API'lerinden oluştuğu için bunun ne anlama geldiğini merak ediyor olabilirsiniz. Geliştiricilerin Android Kotlin uygulamaları için önceden oluşturmuş olabilecekleri kullanıcı arayüzünü geliştirmelerine olanak tanıyan Compose Multiplatform ile birlikte kullanıldığında daha anlamlı bir hale geliyor. Kotlin ekibinin sunduğu Kotlin/Wasm görüntü görüntüleyici demosunu inceleyerek bu özelliğin erken dönem keşfine göz atabilir ve kaynak kodunu keşfedebilirsiniz.
Dart ve Flutter
Google'daki Dart ve Flutter ekipleri de WasmGC desteğini hazırlıyor. Dart'tan Wasm'e derleme çalışması neredeyse tamamlandı. Ekip, WebAssembly'e derlenmiş Flutter web uygulamalarını yayınlamak için araç desteği üzerinde çalışıyor. Çalışmanın mevcut durumu hakkında bilgi edinmek için Flutter dokümanlarını inceleyebilirsiniz. Aşağıdaki demo, Flutter WasmGC Önizlemesi'dir.
WasmGC hakkında daha fazla bilgi
Bu blog yayını henüz yüzeye henüz çıkmamış ve WasmGC hakkında çoğunlukla üst düzey bir genel bakışa sahipti. Özellik hakkında daha fazla bilgi edinmek için şu bağlantılara göz atın:
- Çöp toplayıcı programlama dillerini WebAssembly'e verimli bir şekilde getirmenin yeni yolu
- WasmGC'ye Genel Bakış
- WasmGC MVP
- WasmGC MVP sonrası
Teşekkür ederiz
Bu makale Matthias Liedtke, Adam Klein, Joshua Bell, Alon Zakai, Jakob Kummerow, Clemens Backes, Emanuel Ziegler ve Rachel Andrew tarafından incelenmiştir.