Erhan Ballıeker

WebAssembly ve Microsoft Asp.Net Core Blazor

Selamlar,

Bu yazımda sizlere Mono, Docker vb çılgınlık seviyesinde bir yenilikten bahsetmek istiyorum;

WebAssembly

Tarihi çok da eskilere gitmemekle beraber öncesinde bir grubun poc olarak başlattığı fakat sonradan çarşının karışabileceği belli olduğundan birçok dünya devininde geliştirilmesine yatırımlar yaptığı bir teknoloji haline geldi webassembly.

Geçmişi tam olarak şöyle;

wasmhistory.PNG

2017 yılında işe Apple, Google, Mozilla, Facebook ve benzeri devlerin de devreye girmesiyle hayalin gerçeğe dönüşmesi işi başladı.

Ne olduğunu tek bir cümlede anlatmak zor, ama özetle şu;

  • Modern browserlar üzerinde hiçbir plugin e gerek kalmadan (Flash, Silverlight vb.) çalışacak olan, client side (– server side desteği ile de,  ki .NetCore 3.0 içerisinde bu şekilde gelecek malesef, signalr destekli olarak. -) web yazılımına yeni özellikler ve performans katmayı amaçlayan yeni bir binary kod tipi.

Kendi sitelerinde söyledikleri de tam olarak şu aslında;

  • Binary formata sahip, stack-based bir virtual machine. High-Level dillerin (C#, Java vb.) kendisine compile edilebilmesi ve client ve server uygulamaları için web üzerinden deploy edilmesi ile asıl farkı yaratıyor.

Bu tek cümle yetersiz kaldığı kadar güçsüz de kalıyor. Az daha örneklersek şöyle oluyor;

  • High-Level bir dilde yadığınız kodu, .wasm a compile edip (bu kısma aşağıda web assembly yi nasıl yazarız kısmında değineceğim) web e deploy ederek, client side kodu gibi kullanabiliyorsunuz.

Aslında nasıl node.js ile front-end yazan arkadaşlarımız bir anda backendci ve fullstack oluverdilerse, bu sayede backend ci arkadaşlar da artık javascript yazmadan frontend ci olabilecekler (html + css hariç :)).

Peki o zaman ilk soru şu; Hangi browserlarda çalışır?

Bunun için şu adresten herhangi bir t anında hangi browserlarda çalışabilir olduğunu kontrol edebilirsiniz.

WebAssembly i anlamak için aslında önce javascript in nasıl çalıştığını anlamak gerekiyor. Modern browserlarda server-client arası işleyiş aşağıdakine benzer şekilde oluyor.

jvinanutshell

Html ve css ile browserların design tooları web sitenizi gösteriyor. Kullanıcı ile bu sayfalar arasında etkileşim oluşturabilmek için javascript kodları yazıyoruz. Browser http üzerinden server e istek gönderdiğinde, browser ın websitemizi göstermesi için gerekli olan tüm dosyalar server dan browser a iletiliyor yukarıda ki resimde de görebileceğiniz üzere.

Javascript bildiğiniz üzere tüm client-side tarafta(node.js ile beraber server tarafında da) işlemlerimizi yapmak için kullandığımız bir dil. Interpreted (yorumlanan) bir dil javascript, bir derlenme sürecinden geçip hedef makina nın doğrudan anlayıp çalıştırabileceği bir kod a dönüşmüyor önceden, yani ilgili cihaz da ilgili runtime da bir intertpreter(yorumlayıcı) ile yorumlanıp sonrasında runtime ın anlayıp execute edebileceği bir hale geliyor.

Tüm browserlarda (desktop, mobil vs) javascript çalıştırmak için aşağıdaki gibi bir Javascript Runtime a sahip. Bu sandbox olarak browser için de bulunan runtime da javascript kodları çalışırken bir yandan da browser tarafında bazı api lara ulaşma hakkı oluyor. Herşeye ulaşma imkanı yok, aksi halde bu ciddi güvenlik sorunları doğururdu. Aşağıdaki resimde özetle Javascript in bir browser üzerinde javascript runtime ile çalışıp browser üzerinde ulaşabildiği api ları görüyoruz.

jvruntime

Buraya kadar bu günlere geldik, yazılan tüm web projeleri client-side gereksinimlerini javascript ve yukarıdaki model ile çözebildi. Halen de çözebilir, gelecek zaman için javascript adına kötü haberler yok tabii ki.

Ama bu resme artık şöyle bir arkadaş eklendi;

jvwwa

Javascript ile aynı güvenlik prensiplerine sahip, aynı javascript runtime ı içerisinde çalışan ama interpreted olmayan, doğrudan runtime ın anlayıp çalıştırabileceği yeni bir binary kod tipi olan ve üstelik başka high-level dillerden kendisine compile edilebilir olan WASM (WebAssembly)” oyuna resmi olarak dahil oldu.

WebAssembly kodunun tipi aşağıdaki gibi birşey;

jsvsawasm

Sol tarafta bildiğiniz javascript, high-level yani insanların okuyup anlayabileceği kolayca yazabileceği bir dil, sağ tarafta ise bir wasm (web assembly) kodu görüyoruz. Ve önceden söylediğim gibi ikisi de aynı runtime içerisinde çalışarak, aynı güvenlik sistemleri içerisinde hem browser tarafında hemde node.js gibi teknolojilerle server tarafında çalışabilir halde.

 

WebAssembly nin gelecek planları içerisinde kendi runtime ın da çalıştırabilmek javascript runtime ına bağlı kalmamak gibi bir hedefi de var. Browser larda yine javascript runtime kullanılacak fakat, örneğin bir android cihaz da browser a gerek kalmadan doğrudan kendi runtime içerisinde çalıştırılabilmesi gibi bir hedef de söz konusu.

Wasm’ı tahmin edebilebileceğiniz gibi doğrudan yazmak biraz zor gibi duruyor 🙂 ama isteyen yazabilir, diğer farklı yazım olanaklarına bakmadan önce hızlıca “neden wasm kullanmalıyım?” sorusunu bir düşünelim.

Cevabını aşağıdaki gibi listeyelebiliriz.

  • Interpreted bir dil olmayıp, doğrudan runtime tarafından execute edilebilecek olmasından dolayı neredeyse native hız da çalışabilecek bir kod tipi olması.
  • Diğer High-Level kodların(C#, Java, Python, C/C++ ..) WebAssembly(wasm) a derlenebilir olması.
  • Browserlar tarafından doğrudan desteklenir olması, kullanmak için hiçbir plugin e gerek olmaması.
  • Javascript Runtime Sandbox ı içerisinde çalıştığı için, javascript yazarken ki güvenliğin birebir aynısına sahip olması.
  • Javascript kodu ile beraber çalışabilir olması. Javascript tarafından webassembly modüllerini çağırıp parametreler geçebiliriz, aynı şekilde wasm modülleri tarafından da javascript fonksiyonları çağırabiliriz.

İki büyük yanlış anlaşılmayı da gidermek adına burada da söylemem de fayda var.

  • WebAssembly javascript yerine gelmedi. Aksine onu tamamlayıcı, onunla beraber çalışabilir bir dil. Javascript hayatına olduğu gibi devam edecek tabii ki.
  • WebAssembly ile yazmak demek artık server side ihtiyacı yok demek değil asla.Bunun yerine şunu söylersek doğru olur, önceleri javascript ile client side tarafında yapamayacağımız yoğun hesaplama işlemleri içeren bir sistemi artık server side a ihtiyaç duymadan client-side tarafta yapabiliriz. Örneklersek;
    • Video/Audio Editing, Streaming, Calling
    • Game
    • Virtual/Augmented Reality
    • AI (Image Recognition vs..)

WebAssembly nin performansı sayesinde yukarıdaki örneklerden oyun a örnek olarak aşağıdaki oyuna bir göz atabilirsiniz.

https://www.funkykarts.rocks/demo.html 

Bu oyun yerçekimini simülasyonu hesaplamalarını tamamen client-side tarafında webassembly ile yapan bir oyun.

Diğer yapılanlar için buraya bakabilirsiniz.

WebAssembly Yazmanın Yolları

WebAssembly ile kod geliştirmek için farklı yöntemler mevcut. Bunların neler olduğuna bakalım.

WAT Formatında Kod

Doğrudan wasm formatında kod yazmak çok gerçekçi ve mümkün olmadığından, bununla eş düzeyde wat formatında, insanın okuyup yazmasına çok daha müsait formatta wat kodumuzu yazıp wasm a derleyebiliriz.

İşleyiş şu şekilde oluyor.

writewat

Sol tarafta gördüğünüz gibi WAT formatında kodunuzu yazıp The WebAssembly Binary Toolkit ile runtime ın anlayabileceği WASM formatına dönüştürebilirsiniz.Bu dönüşüm işlemleri için hali hazırda başka tool larda yazılmakta fakat şu an en popülerlerinden birisi bu.

Peki bunu gerçekten deneyelim.

https://webassembly.studio/ sitesine giderek, yeni bir proje oluşurup bunu web ortamında build edip javascript içerisinde çağırıp sonuçları gözlemleyebilirsiniz.

webassembly.studio sitesine gittiğinizde karşınıza bir popup da istediğiniz proje tipini soran bir popup çıkacak.Burada bir çok highlevel dilin yanında Empty Wat Project seçerek, wat formatında kodunuzu yazabilirsiniz.

emptywat

Empty Wat Project seçtiğinizde karşınıza aşağıdaki gibi bir solution yapısı çıkıyor. src altında main.html, main.js ve main.wat dosyaları olduğunu görüyoruz. Burada .wat dosyasında wat formatında kodumuzu yazıp, Build&Run diyerek sonuçları aynı ekran üzerinde gözlemlememiz mümkün.

Aşağıdaki $add fonksiyonu basitce iki adet sayıyı ekleyip geri dönen bir function. Burada kod yazmak istediğiniz de inetllisense bile mevcut. sytnax a alışmak biraz vakit alıcak olsa da, doğrudan wasm yazmayla zorluk derecesi kıyaslanamaz bile 🙂

mainwat

Aşağıda ise, javascript doyasından bir wasm modülünün nasıl çağırıldığını görüyoruz. Bu da aslında WebAssembly yazmanın bir başka yolu diyebiliriz. Modülü instantiate ettikten sonra ilgili fonksiyonu export ederek kullanabiliriz.

mainjs

main.html tarafında ise bildiğimizi dışında hiçbirşey yok. aşağıdaki gibi basit bir html koduna sadece main.js eklenmiş.

mainhtml

Build&Run diyerek bu kodları çalıştırdığımızda çıktı aşağıdaki gibi ekranın sağ alt köşesinde gözüküyor.

Capture.PNG

Ek olarak bir de solution tarafında bir output folder ı görüyoruz.Burada wat kodumuzun dönüşmüş olduğu wasm kodunun nasıl olduğuna bakmak için, main.wasm doyasına sağ tıklayarak alttaki seçeneklerden View as Binary yi seçersek, ekran da bize yazdığımız wat kodumuzun wasm a çevrilmiş halini gösterecektir.

wasmbinary

Microsoft Blazor Tool Chain

Higl-level bir kodun wasm a derlenerek js runtime da çalışabildiğini söylemiştim, ki zaten bu javascripte göre en büyük artılarından bir tanesi webassembly nin.

Bir çok dil için farklı Tool lar mevcut. Biz bir C# / Razor kodumuzun nasıl webassembly e dönüştüğü kısmına bakacağız.

Aşağıdaki resimde ana fikri görüyoruz. Detaylarına değineceğim.

compiletowasm

Burada anlatılan aslında şu;

  • Yazdığımız C# kodu normal hayatta olduğu gibi bir .dll dosyasına dönüştürülür.
  • Bu .dll dosyası, wasm formatına dönüştürülerek mono.wasm runtime u üzerinde çalışır.
  • mono da, aslında js runtime u üzerinde çalışır.

Yani aslında yazdığımız kod .dll e dönüştükten sonra, mono sayesinde, ilgili formata dönüştürülüp mono runtime üzerinde çalışır. yani kodumuz direk js runtime üzerinde değil, mono runtime ında çalışır, mono runtime ı da js runtime üzerinde çalışabildiğinden, en nihayetinde yazdığımız C# kodu, mono sayesinde javascript runtime üzerinde wasm tipinde çalışan bir kod haline gelir.

Sadece bu bile Mono yu yani Xamarin i(mono project i başlatan ekip sonuçta, hatta başlatan kişi 🙂 ) çok fazla sevmek için bile tek başına yetebilecek bir sebep.

Blazor ın Client-side ve server side tarafında çalışma şekilleri farklı. Bunların detaylarına bir sonraki yazımda gireceğim. Asp.Net Core 3.0 ile beraber ne şekilde kullanabiliyor olacağız, bunları inceleyeceğiz.

WebAssembly tarafına ufak bir girişten ve Blazor için C#/Razor kodunun browser da çalışır hale gelmesi akışını sadece akış olarak inceledikten sonra, bir sonraki yazımda sizlere Visual Studio üzerinde Blazor ile neler yapabiliyoruz bunları da göstermek istiyorum.

Bir sonraki yazımda görüşmek üzere.