WebAssembly özellik algılama

Tüm tarayıcılarda kullanıcıları desteklerken en yeni WebAssembly özelliklerini nasıl kullanacağınızı öğrenin.

Ingvar Stepanyan
Ingvar Stepanyan

WebAssembly 1.0 dört yıl önce kullanıma sunuldu ancak geliştirme çalışmaları burada sona ermedi. Yeni özellikler teklif standartlaştırma süreci aracılığıyla eklenir. Web'deki yeni özelliklerde genellikle olduğu gibi, bu özelliklerin uygulama sırası ve zaman çizelgeleri farklı motorlar arasında önemli ölçüde farklılık gösterebilir. Bu yeni özellikleri kullanmak istiyorsanız kullanıcılarınızdan hiçbirinin kapsam dışında kalmadığından emin olmanız gerekir. Bu makalede, bu hedefe ulaşmak için kullanabileceğiniz bir yaklaşımı öğreneceksiniz.

Bazı yeni özellikler, yaygın işlemler için yeni talimatlar ekleyerek kod boyutunu iyileştirir, bazıları güçlü performans temel öğeleri ekler, bazıları ise geliştirici deneyimini ve web'in geri kalanıyla entegrasyonu iyileştirir.

Önerilerin tam listesini ve ilgili aşamalarını resmi depoda bulabilir veya resmi özellik yol haritası sayfasında motorlardaki uygulama durumlarını takip edebilirsiniz.

Tüm tarayıcıların kullanıcılarının uygulamanızı kullanabilmesi için hangi özellikleri kullanmak istediğinizi belirlemeniz gerekir. Ardından, tarayıcı desteğine göre gruplara ayırın. Ardından, kod tabanınızı bu grupların her biri için ayrı ayrı derleyin. Son olarak, tarayıcı tarafında desteklenen özellikleri algılamanız ve ilgili JavaScript ve Wasm paketini yüklemeniz gerekir.

Özellikleri seçme ve gruplandırma

Örnek olarak rastgele bir özellik kümesi seçerek bu adımları uygulayalım. Boyut ve performans nedeniyle kitaplığımda SIMD, iş parçacığı ve istisna işleme kullanmak istediğimi belirlediğimi varsayalım. Tarayıcı desteği aşağıdaki gibidir:

Seçilen özelliklerin tarayıcı desteğini gösteren bir tablo.
Bu özellik tablosunu webassembly.org/roadmap adresinde bulabilirsiniz.

Her kullanıcının en optimize deneyimi elde etmesini sağlamak için tarayıcıları aşağıdaki kohortlara ayırabilirsiniz:

  • Chrome tabanlı tarayıcılar: İş parçacıkları, SIMD ve istisna işleme tümüyle desteklenir.
  • Firefox: İş parçacığı ve SIMD desteklenir, istisna işleme desteklenmez.
  • Safari: İş parçacıkları desteklenir, SIMD ve istisna işleme desteklenmez.
  • Diğer tarayıcılar: Yalnızca temel WebAssembly desteği varsayılır.

Bu döküm, her tarayıcının en son sürümündeki özellik desteğine göre ayrılır. Modern tarayıcılar her zaman günceldir ve otomatik olarak güncellenir. Bu nedenle, çoğu durumda yalnızca en son sürümle ilgilenmeniz gerekir. Ancak, yedek kohort olarak referans WebAssembly'i eklediğiniz sürece, eski tarayıcılara sahip kullanıcılar için bile çalışan bir uygulama sunabilirsiniz.

Farklı özellik kümeleri için derleme

WebAssembly, çalışma zamanında desteklenen özellikleri algılamak için yerleşik bir yönteme sahip değildir. Bu nedenle, modüldeki tüm talimatlar hedefte desteklenmelidir. Bu nedenle, kaynak kodunu bu farklı özellik gruplarının her biri için ayrı olarak Wasm'e derlemeniz gerekir.

Her araç zinciri ve derleme sistemi farklıdır. Bu özelliklerin nasıl değiştirileceği hakkında kendi derleyicinizin dokümanlarına bakmanız gerekir. Basitlik açısından aşağıdaki örnekte tek dosyalı bir C++ kitaplığı kullanacağım ve bu kitaplığın Emscripten ile nasıl derleneceğini göstereceğim.

SSE2 emülasyonu aracılığıyla SIMD, Pthreads kitaplık desteği aracılığıyla iş parçacıkları kullanacağım ve Wasm istisna işleme ile yedek JavaScript uygulaması arasından seçim yapacağım:

# First bundle: threads + SIMD + Wasm exceptions
$ emcc main
.cpp -o main.threads-simd-exceptions.mjs -pthread -msimd128 -msse2 -fwasm-exceptions
# Second bundle: threads + SIMD + JS exceptions fallback
$ emcc main
.cpp -o main.threads-simd.mjs -pthread -msimd128 -msse2 -fexceptions
# Third bundle: threads + JS exception fallback
$ emcc main
.cpp -o main.threads.mjs -pthread -fexceptions
# Fourth bundle: basic Wasm with JS exceptions fallback
$ emcc main
.cpp -o main.basic.mjs -fexceptions

C++ kodu, derleme zamanında aynı işlevlerin paralel (iş parçacığı ve SIMD) uygulamaları ile seri uygulamaları arasında koşullu olarak seçim yapmak için #ifdef __EMSCRIPTEN_PTHREADS__ ve #ifdef __SSE2__ kullanabilir. Bu, aşağıdaki gibi görünür:

void process_data(std::vector<int>& some_input) {
#ifdef __EMSCRIPTEN_PTHREADS__
#ifdef __SSE2__
 
// …implementation using threads and SIMD for max speed
#else
 
// …implementation using threads but not SIMD
#endif
#else
 
// …fallback implementation for browsers without those features
#endif
}

İstisna işleme, derleme işaretleri aracılığıyla seçilen temel uygulamadan bağımsız olarak C++'tan aynı şekilde kullanılabildiğinden #ifdef yönergelerine ihtiyaç duymaz.

Doğru paketi yükleme

Tüm özellik kohortları için paketler oluşturduktan sonra ana JavaScript uygulamasından doğru paketi yüklemeniz gerekir. Bunu yapmak için öncelikle mevcut tarayıcıda hangi özelliklerin desteklendiğini tespit edin. Bunu wasm-feature-detect kitaplığıyla yapabilirsiniz. Bu özelliği dinamik içe aktarma ile birleştirerek en optimize paketi herhangi bir tarayıcıda yükleyebilirsiniz:

import { simd, threads, exceptions } from 'https://unpkg.com/wasm-feature-detect?module';

let initModule
;
if (await threads()) {
 
if (await simd()) {
   
if (await exceptions()) {
      initModule
= import('./main.threads-simd-exceptions.mjs');
   
} else {
      initModule
= import('./main.threads-simd.mjs');
   
}
 
} else {
    initModule
= import('./main.threads.mjs');
 
}
} else {
  initModule
= import('./main.basic.mjs');
}

const Module = await initModule();
// now you can use `Module` Emscripten object like you normally would

Son sözler

Bu yayında, farklı özellik grupları için paketleri nasıl seçeceğinizi, oluşturacağınızı ve paketler arasında nasıl geçiş yapacağınızı gösterdik.

Özellik sayısı arttıkça özellik kohortlarının sayısı sürdürülemeyecek hale gelebilir. Bu sorunu hafifletmek için gerçek kullanıcı verilerinize göre özellik kohortları seçebilir, daha az popüler tarayıcıları atlayabilir ve biraz daha az optimal kohortlara geri dönmelerine izin verebilirsiniz. Uygulamanız tüm kullanıcılar için çalışmaya devam ettiği sürece bu yaklaşım, aşamalı iyileştirme ile çalışma zamanı performansı arasında makul bir denge sağlayabilir.

Gelecekte WebAssembly, desteklenen özellikleri algılamak ve modül içinde aynı işlevin farklı uygulamaları arasında geçiş yapmak için yerleşik bir yönteme sahip olabilir. Ancak bu tür bir mekanizma, yukarıdaki yaklaşımı kullanarak koşullu olarak algılamanız ve yüklemeniz gereken bir MVP sonrası özellik olur. O zamana kadar, tüm tarayıcılarda yeni WebAssembly özelliklerini kullanarak kod oluşturmanın ve yüklemenin tek yolu bu yaklaşım olacaktır.