WebAssembly etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
WebAssembly etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

5 Ocak 2026 Pazartesi

WebAssembly ile Tarayıcıda Yüksek Performans: Rust Kullanarak Adım Adım İlk Modülünü Yayınla

Giriş: Neden WebAssembly (Wasm)?

Web uygulamalarında performans ihtiyacı arttıkça, tarayıcının “sadece JavaScript” ile sınırlı olmadığı gerçeği daha fazla önem kazanıyor. WebAssembly (Wasm), C/C++ veya Rust gibi dillerle derlenen kodu tarayıcıda güvenli bir sanal makinede çalıştırarak, özellikle CPU yoğun işlerde (şifreleme, görüntü işleme, sıkıştırma, fizik simülasyonları, veri pars etme) ciddi hız avantajı sunuyor. Bu yazıda ileri seviye ama uygulanabilir bir örnekle, Rust kullanarak Wasm modülü üretmeyi ve bunu modern bir web projesinde çalıştırmayı adım adım anlatacağım.

Hangi Senaryolarda Wasm Mantıklı?

Wasm her şeyin ilacı değil. DOM manipülasyonu, UI güncellemeleri ve tipik CRUD akışları JavaScript/TypeScript ile zaten yeterince hızlıdır. Wasm’ın güçlü olduğu taraf, hesaplama ağırlıklı fonksiyonları izole edip hızlandırmaktır. Örneğin JSON parse etmek yerine ikili format işlemek, büyük diziler üzerinde matematik, kripto, audio DSP veya WebGPU öncesi hazırlık işlemleri gibi alanlarda fark yaratır. Ayrıca Rust tarafında bellek güvenliği avantajı da cabasıdır.

Kurulum: Rust + Wasm Toolchain

Öncelikle Rust kurulu olmalı. Rust’ın resmi aracı olan rustup ile kurulum yaptıktan sonra Wasm hedefini ekleyeceğiz. Ardından JavaScript ile köprü kurmayı kolaylaştıran wasm-bindgen ekosisteminden yararlanacağız. Terminalde aşağıdaki adımları uygulayın:

1) Wasm hedefi: rustup target add wasm32-unknown-unknown

2) wasm-pack (opsiyonel ama pratik): cargo install wasm-pack

wasm-pack, derleme ve paketleme sürecini tek komutla yönetmenizi sağlar. Bu sayede npm tabanlı projelere Wasm çıktısını daha rahat entegre edebilirsiniz.

Örnek Proje: Rust ile Hızlı Fibonacci (Memoization’lı)

Klasik Fibonacci örneği basit görünse de, burada amaç “Wasm köprüsü” kurmayı göstermek. Gerçek projede benzer şekilde sık çağrılan fonksiyonlarınızı Wasm’a taşıyabilirsiniz. Yeni bir klasör açıp Rust kütüphanesini oluşturalım:

cargo new --lib wasm-fibo

Proje klasöründe Cargo.toml dosyasını Wasm uyumlu hale getirelim. Kütüphaneyi cdylib olarak derlemek gerekiyor. Ayrıca wasm-bindgen ekleyeceğiz:

Cargo.toml içinde şu alanlar olmalı:

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
wasm-bindgen = "0.2"

Şimdi src/lib.rs dosyasını düzenleyelim. Basit bir memoization yaklaşımıyla, büyük n değerlerinde gereksiz tekrar hesaplamayı azaltacağız:

Not: Rust’ta Wasm tarafında performans için panik mesajlarını kapatmak, uygun allocator seçmek gibi ek optimizasyonlar da yapılabilir; ama bu yazıda temeli sağlam kurmaya odaklanıyoruz.

src/lib.rs örneği:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn fib(n: u32) -> u64 {
    let mut a: u64 = 0;
    let mut b: u64 = 1;
    for _ in 0..n {
        let tmp = a + b;
        a = b;
        b = tmp;
    }
    a
}

Derleme: wasm-pack ile Paket Üretmek

Şimdi derleyelim. Proje kök dizininde:

wasm-pack build --target web

Bu komut, pkg adlı bir klasör oluşturur. İçinde .wasm dosyası, JavaScript bağlayıcıları ve package.json benzeri paket metadata’ları yer alır. --target web seçeneği, doğrudan tarayıcıda ES Module olarak kullanım senaryosuna uygundur.

Tarayıcıda Kullanım: Minimal HTML + JS

Wasm çıktısını bir web projesinde kullanmak için birçok yol var: Vite, Webpack, Next.js veya sadece statik dosyalar. En kolay anlaşılır yöntem için “düz” bir kullanım mantığını tarif edelim: pkg klasörünü web kökünüze kopyalayın ve modülü ES Module olarak import edin.

Örnek JavaScript (ör. main.js) akışı şu şekilde olur:

import init, { fib } from "./pkg/wasm_fibo.js";

async function run() {
    await init();
    console.log("fib(50) =", fib(50));
}

run();

Buradaki kritik nokta init() fonksiyonudur. Wasm modülünün yüklenmesi ve başlatılması bu aşamada gerçekleşir. Eğer init çağrısını atlar veya yanlış path verirseniz, tarayıcı modülü bulamaz ya da instantiate edemez.

Performans İpuçları ve Sık Yapılan Hatalar

1) Veri kopyalama maliyetine dikkat: Wasm ile JS arasında büyük diziler taşıyorsanız, asıl darboğaz “kopyalama” olabilir. Mümkün olduğunca TypedArray ve paylaşımlı bellek (uygun senaryolarda) stratejilerini araştırın.

2) Küçük fonksiyonları Wasm’a taşımayın: Çok sık ama çok küçük işler için köprü maliyeti performansı düşürebilir. Wasm’ı “toplu iş” mantığıyla kullanmak genelde daha verimlidir.

3) Release derleme kullanın: wasm-pack zaten uygun optimizasyonları hedefler; yine de üretimde “debug” benzeri çıktılarla test yapmayın. Boyut ve hız farkı barizdir.

4) Hata ayıklama yaklaşımı: Rust tarafında panik durumlarını yönetmek ve tarayıcı konsolunda anlamlı hata görmek için ek araçlar (ör. console_error_panic_hook) kullanılabilir. Proje büyüdükçe bu tür “geliştirici deneyimi” bağımlılıkları ciddi zaman kazandırır.

Sonuç: Rust + Wasm ile Modern Web’e Performans Katmanı

Bu rehberde, Rust ile basit bir fonksiyonu WebAssembly’ye derleyip tarayıcıda çalıştırmanın temel yolunu kurduk. Buradaki yapı taşları gerçek projelerde de aynıdır: Rust tarafında Wasm uyumlu kütüphane, wasm-bindgen ile arayüz, wasm-pack ile paketleme ve tarayıcıda modül yükleme. Eğer uygulamanızda CPU yoğun bir bölüm varsa, doğru tasarımla Wasm size hem performans hem de daha güvenli bir kod tabanı sağlayabilir.

3 Ocak 2026 Cumartesi

WebAssembly (Wasm) ile Node.js Performansını Artırma: Rust ile Hızlı Modül Geliştirme Rehberi

WebAssembly neden gündemde?

Node.js ekosistemi pratikliğiyle ünlü ama bazı işlerde “kolay” her zaman “hızlı” anlamına gelmiyor. Özellikle JSON işleme, sıkıştırma, görüntü/ham veri dönüştürme, kriptografi veya matematiksel hesaplar gibi CPU ağırlıklı senaryolarda JavaScript tek başına sınıra dayanabiliyor. WebAssembly (Wasm) burada devreye giriyor: Rust gibi sistem dilleriyle yazılmış kodu Wasm’a derleyip Node.js içinden çalıştırarak performansı hissedilir biçimde artırmak mümkün.

Bu yazıda ileri seviye ama uygulanabilir bir yaklaşımı ele alacağız: Rust ile Wasm modülü yazıp Node.js projesine entegre etmek. Hedefimiz “her şeyi Wasm’a taşıyalım” değil; darboğaz olan parçaları tespit edip kritik fonksiyonları hızlandırmak.

Ne zaman Wasm kullanmalı?

Wasm, her sorunun sihirli çözümü değil. Aşağıdaki durumlarda özellikle anlamlı olur: çok sayıda tekrar eden hesap (ör. hashing, parsing, diff), büyük veri üzerinde döngüler, yüksek frekanslı çağrılan saf fonksiyonlar ve GC baskısı oluşturan işlemler. Buna karşılık, ağ I/O ağırlıklı API’larda veya veritabanı bekleme süresi baskınken Wasm’a geçiş beklediğiniz kazanımı getirmeyebilir.

Bir kural: Önce ölçün. Node.js tarafında --prof, clinic.js veya yerleşik CPU profilleyicilerle darboğazı doğrulamadan Wasm’a koşmak genelde gereksiz karmaşıklık yaratır.

Kurulum: Rust ve wasm-pack

Bu rehberde Rust tarafında wasm-pack aracını kullanacağız. Node.js ile entegrasyon için en pratik yollardan biri. Gerekenler: güncel Node.js (LTS), Rust toolchain ve wasm-pack.

Rust kurulumu: Rust’ı resmi yöntemle kurduktan sonra wasm-pack yükleyin. Komut satırında: cargo install wasm-pack. Ardından projenizi oluşturacağız.

Adım adım: Rust ile Wasm modülü yazma

Örnek olarak CPU’yu yoran ama anlaşılır bir iş seçelim: büyük bir dizide basit istatistik (toplam ve ortalama) hesaplamak. Elbette gerçek hayatta daha karmaşık algoritmalar daha iyi kazanç sağlar; amaç süreçleri göstermek.

Yeni bir Rust-Wasm paketi oluşturun: wasm-pack new faststats. Klasör içine girip src/lib.rs dosyasını düzenleyin. Rust tarafında JavaScript’ten veri alırken kopyalama maliyetlerine dikkat etmek gerekir; mümkünse TypedArray yaklaşımı tercih edilir. wasm-bindgen ile gelen veri türlerini kontrollü kullanacağız.

Temel bir örnek mantık: JavaScript’ten Float64Array gönderip Rust’ta döngüyle toplamı hesaplayacağız. Dönüşte toplam ve ortalamayı tek bir yapı olarak dönmek yerine, sade kalması için JSON benzeri bir nesne döndürmek yerine iki sayıyı ayrı döndürmek veya küçük bir struct kullanmak mantıklıdır. wasm-bindgen, basit türlerde daha verimli çalışır.

Derleme: Node.js hedefi ile paketleme

Derleme için: wasm-pack build --target nodejs komutunu kullanın. Bu işlem pkg klasöründe Node.js’in içe aktarabileceği bir sarmalayıcı ve .wasm

Projeyi bir monorepo gibi kullanabilir veya üretilen paketi ana Node.js projenize kopyalayabilirsiniz. Daha temiz yöntem, Rust tarafını ayrı paket tutup ana projede dosya bağımlılığıyla kullanmaktır.

Node.js tarafında kullanım

Node.js projenizde üretilen paketi içe aktarın. Eğer aynı repo içindeyseniz, örneğin ./faststats/pkg yolundan import edebilirsiniz. Ardından Float64Array oluşturup Wasm fonksiyonunu çağırın. Bu noktada iki şeye dikkat edin: veri kopyalama ve çağrı sıklığı. Çok küçük dizilerde veya çok seyrek çağrılarda Wasm köprüsünün maliyeti kazancı gölgeleyebilir.

Pratik bir yaklaşım: veriyi parça parça göndermek yerine tek seferde daha büyük bloklar halinde işlemek. Ayrıca Rust tarafında gereksiz bellek tahsisi yapmamak. Wasm modülleri hız sağlar, ama yanlış veri akışı tasarımı tüm kazanımı yiyebilir.

Performans ölçümü: Gerçekçi benchmark

Performansı değerlendirirken “tek bir çalıştırma” yerine, ısınma etkisini ve JIT davranışını göz önüne alan bir ölçüm yapın. Basitçe process.hrtime.bigint() ile süre ölçebilirsiniz. Aynı işi saf JavaScript ile ve Wasm ile yaptığınız iki senaryoyu karşılaştırın. Önemli olan sadece ortalama süre değil; p95/p99 gecikmeleri de fark yaratır.

Wasm’ın en güçlü olduğu yerlerden biri de deterministik performanstır: GC dalgalanmalarını azaltabilir. Özellikle yoğun hesap yapan servislerde daha stabil gecikme dağılımları elde edebilirsiniz.

Sık yapılan hatalar ve ipuçları

1) Her şeyi Wasm’a taşımak: Uygulamanın tamamını Wasm’a geçirmek yerine sadece sıcak noktaları hedefleyin. 2) Küçük fonksiyonları çok sık çağırmak: Köprü maliyeti artar; daha büyük iş parçaları tasarlayın. 3) Yanlış veri türü seçmek: String alışverişi maliyetlidir; mümkünse binary/TypedArray kullanın. 4) Hata ayıklamayı zorlaştırmak: Rust tarafında basit loglama ve testler ekleyin; Node tarafında da giriş doğrulaması yapın.

Ek bir öneri: Eğer amacınız Node.js’e “native hız” kazandırmaksa Wasm tek seçenek değil. N-API ile C/C++ eklentileri veya Rust tabanlı native modüller de güçlüdür. Ancak Wasm, taşınabilirlik ve dağıtım kolaylığı açısından birçok projede daha sürdürülebilir bir yol sunar.

Sonuç

WebAssembly, Node.js projelerinde performans darboğazlarını kırmak için modern ve pratik bir araç. Rust ile yazıp wasm-pack ile paketleyerek, kritik hesaplama fonksiyonlarını güvenli ve hızlı bir şekilde Node.js’e taşıyabilirsiniz. Doğru senaryoda, daha düşük CPU kullanımı ve daha stabil gecikmeler elde etmek mümkün. En iyi sonuç için profilleme yapın, veri geçişini optimize edin ve Wasm’ı “cerrahi” bir hızlandırma katmanı gibi konumlandırın.

25 Aralık 2025 Perşembe

WebAssembly ile Tarayıcıda Rust Çalıştırma: Performans Odaklı Kurulum ve Gerçekçi Kullanım Senaryoları

WebAssembly (Wasm) Nedir ve Neden Rust?

Tarayıcıda “native’e yakın” hız hedefleyen herkesin yolu bir noktada WebAssembly (Wasm) ile kesişiyor. Wasm; JavaScript’in yerine geçmekten çok, onu tamamlamak için tasarlanmış taşınabilir bir düşük seviye bytecode formatı. Performansın kritik olduğu yerlerde (görüntü işleme, kriptografi, veri sıkıştırma, oyun motoru parçaları, büyük veri dönüşümleri vb.) JavaScript tarafında zorlanan işlemleri Wasm’a taşıyabiliyorsunuz.

Bu noktada Rust pratik bir tercih: bellek güvenliği yaklaşımı, güçlü derleyici optimizasyonları ve Wasm ekosisteminin olgunlaşması sayesinde tarayıcı hedefleri için oldukça düzgün bir geliştirme deneyimi sunuyor. Bu yazıda, Blogger’da yayınlanabilir şekilde, sıfırdan Rust + Wasm projesi hazırlayıp tarayıcıda çalıştırmayı ve gerçek hayatta işinize yarayacak püf noktalarını adım adım ele alıyorum.

Ön Koşullar

Kuruluma başlamadan önce sisteminizde Rust ve Node.js bulunmalı. Rust için resmi kurulum aracı rustup yeterli. Node.js tarafında LTS sürüm tercih edin. Ayrıca yerel geliştirme için basit bir web sunucusu kullanacağız (Vite veya benzeri). Örnekleri macOS, Linux ve Windows’ta uygulayabilirsiniz; komutlar büyük ölçüde aynı.

1) Rust’ı Wasm Hedefiyle Hazırlama

İlk adım olarak Rust’ın WebAssembly hedefini ekleyin. Terminalde şu komutu çalıştırın:

rustup target add wasm32-unknown-unknown

Bu hedef, Rust kodunu Wasm bytecode’una derlemenizi sağlar. Ancak tarayıcıyla daha rahat entegrasyon için çoğu projede bir adım daha ileri gidip wasm-bindgen ve wasm-pack kullanılır. wasm-pack, proje iskeletini yönetir, derler ve JavaScript bağlayıcılarını üretir.

2) wasm-pack Kurulumu ve Proje Oluşturma

wasm-pack’i Rust’ın paket yöneticisi Cargo ile kurun:

cargo install wasm-pack

Ardından yeni bir kütüphane projesi oluşturun:

cargo new --lib hizli-wasm

Klasöre girip Cargo.toml dosyanıza wasm-bindgen bağımlılığını ekleyin. Dosyanın ilgili kısmı kabaca şöyle olmalı:

[dependencies]
wasm-bindgen = "0.2"

3) Rust Kodunu Tarayıcıya Açma (wasm-bindgen)

src/lib.rs içine basit ama ölçülebilir bir örnek koyun. Örneğin bir dizi içindeki sayıları filtreleyip toplamak gibi CPU’ya yük bindiren işleri Wasm’a taşımak yaygın bir yaklaşım. Örnek mantık: dışarıdan bir sayı listesi al, tek sayıları süz, kalanları topla. wasm-bindgen ile fonksiyonu dışa açabilirsiniz:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn ciftleri_topla(nums: Vec<u32>) -> u32 {
  nums.into_iter().filter(|n| n % 2 == 0).sum()
}

Buradaki önemli nokta: Tarayıcıya “güvenli” ve “anlaşılır” bir arayüz vermek. Karmaşık veri tipleri mümkündür ama başlangıçta sayılar ve basit diziler üzerinden ilerlemek, performans ve hata ayıklama açısından daha stabildir.

4) Derleme: Wasm Paketini Üretme

Proje klasöründe şu komutu çalıştırın:

wasm-pack build --target web

Komut tamamlandığında pkg adlı bir klasör oluşur. İçinde .wasm dosyası, JavaScript sarmalayıcısı ve package.json benzeri çıktılar yer alır. Bu klasör, web projenizde “modül” gibi kullanılabilir.

5) Vite ile Basit Bir Web Arayüzü

Wasm çıktısını hızlıca test etmek için Vite iyi bir seçenek. Ayrı bir klasörde Vite projesi oluşturun:

npm create vite@latest web-arayuz -- --template vanilla

Klasöre girip bağımlılıkları kurun:

cd web-arayuz
npm install

Ardından Rust projenizdeki pkg klasörünü web-arayuz içine kopyalayın (örneğin web-arayuz/src/pkg). Sonra src/main.js içinde Wasm modülünü içe aktarın:

import init, { ciftleri_topla } from "./pkg/hizli_wasm.js";

async function run() {
  await init();
  const nums = Array.from({ length: 100000 }, (_, i) => i);
  const sonuc = ciftleri_topla(nums);
  console.log("Sonuç:", sonuc);
}

run();

Son olarak geliştirme sunucusunu başlatın:

npm run dev

Tarayıcı konsolunda sonucu görüyorsanız temel entegrasyon tamamdır. Buradan sonra UI ekleyebilir, girdileri form üzerinden alabilir ya da daha gerçekçi veri işleme senaryolarına geçebilirsiniz.

Performans ve Gerçek Hayat İpuçları

Wasm her zaman otomatik olarak “daha hızlı” demek değildir. Kazanç, işin türüne göre değişir. Sık çağrılan küçük fonksiyonlarda JavaScript ↔ Wasm sınırı (FFI) maliyeti baskın hale gelebilir. Bu yüzden çok küçük işleri binlerce kez çağırmak yerine, mümkünse işi Wasm tarafında daha “toplu” yapacak şekilde tasarlayın.

Ayrıca tarayıcı tarafında bellek kopyaları önemli bir maliyet kalemidir. Büyük dizileri sürekli Rust’a geçirip geri almak yerine, veri akışını minimize edin. Daha ileri senaryolarda TypedArray ile bellek paylaşımı ve wasm-bindgen’in sunduğu yardımcılar gündeme gelir; fakat temel kurulum oturduktan sonra bu optimizasyonlara geçmek daha sağlıklı olur.

Hata Ayıklama ve Yaygın Sorunlar

En sık görülen problem, yanlış hedefle derleme veya modülün doğru yüklenmemesidir. Vite gibi bundler’lar ESM modüllerle iyi çalışır; bu yüzden wasm-pack build --target web seçimi önemlidir. Eğer “Failed to load module script” gibi hatalar alıyorsanız, dosya yollarını ve modül import biçimini kontrol edin.

Bir diğer konu da sürüm uyumsuzluklarıdır. wasm-bindgen sürümü yükseldiğinde, eski çıktılarla karışıklık yaşayabilirsiniz. Böyle durumlarda pkg klasörünü temizleyip yeniden derlemek genellikle sorunu çözer.

Sonuç

Rust ile WebAssembly kullanarak tarayıcıya performans odaklı bir modül eklemek, doğru kurulum yapıldığında şaşırtıcı derecede pratik. Bu rehberde Rust hedefini ekledik, wasm-pack ile derleme çıktısı ürettik ve Vite üzerinden tarayıcıda çalıştırdık. Buradan sonra gerçek bir uygulamada kriptografi, görüntü dönüştürme, sıkıştırma veya büyük veri filtreleme gibi alanlarda Wasm’ın avantajını daha net görmeye başlayacaksınız.

14 Kasım 2025 Cuma

WebGPU ile Tarayıcıda Yapay Zeka: Transformers.js Kullanarak Yerel Metin Sınıflandırıcı Kurulumu

Özet

Tarayıcıda çalışan yapay zeka uygulamaları, veriyi cihazdan çıkarmadan işlemek ve sunucu maliyetlerini azaltmak için güçlü bir çözüm haline geldi. WebGPU sayesinde artık yalnızca WebAssembly (WASM) ile sınırlı değiliz; modern ekran kartlarının gücünü doğrudan JavaScript ile kullanabiliyoruz. Bu rehberde, Transformers.js kütüphanesi ile tek sayfalık bir uygulama geliştirerek WebGPU üzerinde yerel metin sınıflandırma (pozitif/negatif duygu analizi) kuracağız. Kod, hiçbir sunucu tarafı model barındırma olmadan çalışacak ve tarayıcı, modeli indirip IndexedDB üzerinde önbellekleyecek.

Neden WebGPU?

WebGPU, grafik ve hesaplama iş yüklerinde tarayıcıya modern bir düşük seviye API sunar. WASM ile CPU üzerinde çalışan modeller, bazen yeterli performansı yakalayamazken, WebGPU destekli ONNX Runtime Web ve Transformers.js kombinasyonu, önemli ölçüde hız kazandırır. Sonuç: daha düşük gecikme, daha akıcı kullanıcı deneyimi ve ölçeklenmesi kolay bir mimari.

Önkoşullar

- Güncel bir Chromium tabanlı tarayıcı (Chrome/Edge 113+). Çoğu sistemde WebGPU varsayılan olarak açıktır. Eğer kapalıysa chrome://flags üzerinden “Enable WebGPU” etkinleştirilebilir.

- Modern bir GPU ve güncel sürücüler önerilir. GPU yoksa, uygulama otomatik olarak WASM’e düşer (daha yavaş olabilir).

- Basit bir yerel sunucu. Örnek olarak python -m http.server 8000 veya npx serve . kullanabilirsiniz.

Proje Yapısı ve Temel Sayfa

Bir klasör oluşturun: webgpu-ai-demo/. İçine index.html adında bir dosya ekleyin ve aşağıdaki iskeleti yerleştirin. COOP/COEP başlıkları, çok iş parçacıklı WASM için önerilir; yerel geliştirmede meta etiketleriyle eşdeğeri sağlanabilir. Üretimde ise HTTP yanıt başlıklarını sunucuda ayarlayın.

Aşağıdaki kodu tek bir HTML dosyasında kullanabilirsiniz:

<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>WebGPU ile Metin Sınıflandırma</title>
  <meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin">
  <meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp">
  <style>body{font-family:system-ui, Arial, sans-serif;max-width:800px;margin:40px auto;padding:0 16px}</style>
</head>
<body>
  <h1>WebGPU ile Tarayıcıda Duygu Analizi</h1>
  <textarea id="input" rows="6" style="width:100%" placeholder="Değerlendirilecek metni yazın..."></textarea>
  <br><br>
  <button id="analyze">Analiz Et</button>
  <pre id="log" style="background:#f6f8fa;padding:12px;white-space:pre-wrap">Hazırlanıyor...</pre>
  <script type="module">
    import { pipeline, env } from 'https://cdn.jsdelivr.net/npm/@xenova/transformers/dist/transformers.min.js';
    // WebGPU varsa kullan, yoksa WASM'e düş.
    const preferGPU = 'gpu' in navigator;  // navigator.gpu modern tarayıcılarda mevcuttur.
    const device = preferGPU ? 'webgpu' : 'wasm';
    // WASM fallback için iş parçacığı sayısı (COOP/COEP ile etkin çoklu iş parçacığı).
    env.backends.onnx.wasm.numThreads = Math.max(1, Math.min(4, (navigator.hardwareConcurrency||4)-1));
    const logEl = document.getElementById('log');
    const btn = document.getElementById('analyze');
    const input = document.getElementById('input');

    log('Model indiriliyor ve hazırlanıyor...');
    const classifier = await pipeline('text-classification', 'Xenova/distilbert-base-uncased-finetuned-sst-2-english', {
      device, quantized: true,
      progress_callback: x => log('İndiriliyor: ' + Math.round((x.progress||0)*100) + '%')
    });
    log('Hazır. Bir metin yazıp "Analiz Et"e basın.');

    btn.addEventListener('click', async () => {
      btn.disabled = true;
      const text = input.value.trim();
      if (!text) { log('Lütfen bir metin girin.'); btn.disabled = false; return; }
      log('Analiz ediliyor...');
      const output = await classifier(text, { topk: 2 });
      log(JSON.stringify(output, null, 2));
      btn.disabled = false;
    });

    function log(msg){ logEl.textContent = msg; }
  </script>
</body>
</html>

Çalıştırma

Proje klasörüne geçip basit bir sunucu açın. Örneğin Python kullanıyorsanız: python -m http.server 8000. Ardından tarayıcıdan http://localhost:8000 adresine gidin. İlk çalıştırmada model ağırlıkları indirileceği için bir miktar bekleme olabilir. Bu dosyalar IndexedDB üzerinde önbelleklenecek; bir sonraki açılışta çok daha hızlı başlayacaktır.

Performans İpuçları

- WebGPU: Kodda device: 'webgpu' geçiliyorsa GPU kullanılacaktır. Tarayıcınız ve ekran kartınız destekliyorsa belirgin hız kazanırsınız.

- Kuantizasyon: quantized: true seçeneğiyle 8-bit ağırlıklar kullanılır; indirme boyutu ve bellek tüketimi düşer, hız genellikle artar.

- Isınma (warm-up): Uygulama açıldığında boş bir metinle hızlı bir “ısınma” çağrısı yapmak, ilk gerçek isteğin gecikmesini azaltır.

- Çok iş parçacığı: WASM’e düşmeniz halinde COOP/COEP etkinse env.backends.onnx.wasm.numThreads ile çekirdek sayınıza göre değer belirleyin.

- Küçük modeller: Tarayıcı için küçük/orta boy modeller tercih edin. Daha büyük LLM’ler (ör. 7B) tarayıcıda pratik olmayabilir; sunucuya veya yerel native uygulamalara yönelin.

Hata Giderme

- “navigator.gpu tanımsız” uyarısı alıyorsanız tarayıcınızı güncelleyin veya WebGPU’yu flags üzerinden etkinleştirin. Bazı kurumsal politikalar WebGPU’yu devre dışı bırakabilir.

- “CORS/COEP/COOP” ile ilgili hatalarda sayfayı mutlaka bir HTTP sunucusundan servis edin. Üretimde, meta etiket yerine gerçek yanıt başlıklarını (COOP/COEP) sunucuda ayarlayın.

- Model indirme yavaşsa farklı bir ağa geçmeyi deneyin. İlk indirme bir kez yapılır; sonraki açılışlarda IndexedDB önbelleği devreye girer.

- Sonuçlar beklediğiniz gibi değilse Türkçe metinler için uygun bir modele geçebilirsiniz; Transformers.js ile Türkçe duygu analizi veya çok dilli modelleri deneyin.

Kısa Değerlendirme

Bu yaklaşım, uçtan uca gizlilik (metin cihazdan çıkmaz), anında ölçeklenebilirlik (sunucu GPU’su gerekmez) ve düşük gecikme gibi avantajlar sunuyor. Chrome ve Edge üzerinde WebGPU ile duyduğum hız artışı belirgin oldu; Safari ve Firefox tarafında ise deneysel destekler hızla olgunlaşıyor. Projenizde basit bir duygu analiziyle başlayıp, soru-cevap ya da özetleme gibi diğer görevler için hafif modellerle devam edebilirsiniz.

Sonuç

WebGPU ve Transformers.js, tarayıcıda çalışan modern yapay zeka uygulamalarını herkes için erişilebilir kılıyor. Bu yazıdaki örneği temel alarak kendi metin moderasyonu, kullanıcı geri bildirimi analizi veya içerik sınıflandırma araçlarınızı birkaç yüz satırlık kodla hayata geçirebilirsiniz. Performansı artırmak için kuantizasyon, uygun model seçimi ve önbellekleme stratejilerinden yararlanmayı unutmayın.

19 Ekim 2025 Pazar

Tarayıcıda Python Çalıştırma Rehberi: WebAssembly ve Pyodide ile Adım Adım

WebAssembly (WASM) ve Pyodide sayesinde Python kodunu doğrudan tarayıcıda, sunucuya ihtiyaç duymadan çalıştırmak artık mümkün. Bu yazıda, Pyodide nedir, nasıl entegre edilir, paket yönetimi ve performans ipuçları nelerdir gibi sorulara adım adım yanıt veriyorum. Hedefimiz, hem modern web uygulamalarına Python gömmenin pratik yolunu göstermek hem de gerçek hayatta işinize yarayacak optimizasyon önerilerini sunmak.

Pyodide Nedir?

Pyodide, CPython yorumlayıcısını ve birçok bilimsel Python paketini WebAssembly’ye derleyerek tarayıcıda çalıştırmanıza olanak tanır. NumPy, Pandas, Matplotlib gibi kütüphanelerin “pure-Python” olanlarını veya WASM’a derlenmiş varyantlarını tarayıcıya getirir. Ağ bağlantısı olmasa bile, gerekli dosyalar indirildikten sonra kodunuzu yerel olarak işletir. Bu da interaktif eğitim içerikleri, gömülü veri görselleştirme, offline notebook deneyimleri ve güvenli istemci tarafı prototipleme için güçlü bir zemin sunar.

Hızlı Başlangıç: Basit Entegrasyon

Aşağıdaki minimal örnekle tarayıcıda Python çalıştırabilirsiniz. Kodu bir HTML dosyasına koyup açmanız yeterli.

<!-- Pyodide yükleyici -->
<script src="https://cdn.jsdelivr.net/pyodide/v0.26.0/full/pyodide.js"></script>
<script>
(async () => {
const pyodide = await loadPyodide({ indexURL: "https://cdn.jsdelivr.net/pyodide/v0.26.0/full/" });
await pyodide.runPythonAsync(`import sys; print(sys.version)`);
const result = await pyodide.runPythonAsync("sum(range(10))");
console.log("Python sonucu:", result);
})();
</script>

Burada loadPyodide ile WASM tabanlı Python ortamı yükleniyor, ardından runPythonAsync ile kod yürütülüyor. Konsolda Python sürümü ve örnek bir hesaplamanın sonucu görünecektir.

Paket Yönetimi: micropip ve Yerleşik Paketler

Pyodide, birçok popüler kütüphaneyi hazır olarak getirir. Ek bir pakete ihtiyaç duyduğunuzda micropip ile pure-Python paketleri (C uzantısı gerektirmeyenler) kolayca kurulabilir.

await pyodide.runPythonAsync(`import micropip; await micropip.install("requests")`);

NumPy veya Pandas gibi ağır paketler için Pyodide’ın yerleşik kaynaklarını kullanmak daha verimlidir. Bunlar çoğunlukla pyodide.loadPackage ile önceden yüklenebilir:

await pyodide.loadPackage(["numpy", "pandas"]);

Paket yüklemelerini sayfa ilk açılışında toplu yapmak, kullanıcı etkileşimi sırasında gecikmeleri azaltır. İlk kez yüklemede CDN’den indirme yapılırken, sonraki sayfa yenilemelerinde tarayıcı önbelleğinden faydalanılır.

Tarayıcı Dosya Sistemi ve Veri Paylaşımı

Pyodide, Emscripten’in sanal dosya sistemini (MEMFS) kullanır. JavaScript tarafındaki veriyi Python tarafına aktarmak için dosya sistemine yazmak pratik bir yöntemdir:

const csv = "a,b\\n1,2\\n3,4";
pyodide.FS.writeFile("/tmp/data.csv", csv);
await pyodide.runPythonAsync(`import pandas as pd; df = pd.read_csv("/tmp/data.csv"); print(df.sum().to_dict())`);

Alternatif olarak, doğrudan JS-Python köprüsünden yararlanabilir ve pyodide.toPy / pyodide.toJs ile veri alışverişi yapabilirsiniz. Büyük verilerde kopyalamayı en aza indirmek için bu köprüleri tercih edin.

Performans İpuçları

- Lazy yükleme yapın: İlk ekranda gerekmeyen büyük paketleri, kullanıcı etkileşimiyle tetiklenen aşamada yükleyin.
- runPython yerine runPythonAsync kullanın: Uzun süren işlemler UI’ı kilitlemesin.
- Ön ısıtma (warm-up): Sayfa yüklenir yüklenmez küçük bir Python ifadesi çalıştırmak, JIT yoksa bile modül başlatmalarını önceden yaparak ilk gerçek görevde gecikmeyi azaltır.
- Önbellekleme: CDN varlıklarını (pyodide.js, .wasm, paket indeksleri) Service Worker ile cache-first stratejisiyle saklayın. Böylece offline veya zayıf ağda bile hızlı açılış sağlanır.
- Veri boyutunu sınırlayın: Tarayıcı belleği kısıtlıdır. Tek seferde işlenen veri setlerini makul boyutta tutun ve gereksiz kopyalardan kaçının.

Güvenlik ve Sandbox

Pyodide, tarayıcının güvenli çalışma alanında koşar. Varsayılan olarak yerel dosya sistemine erişemez ve ağ istekleri tarayıcı CORS kurallarına tabidir. Üçüncü taraf paketleri yüklerken yalnızca güvendiğiniz kaynakları kullanın. Kullanıcıdan gelen Python kodunu çalıştıracaksanız, suistimali azaltmak için zaman sınırı, bellek sınırı ve izinli API listesi (allowlist) gibi korumalar düşünün.

Ne Zaman Pyodide? Ne Zaman Sunucu?

- Pyodide’ı tercih edin: Hızlı prototip, eğitim içerikleri, etkileşimli dokümantasyon, gizlilik gerektiren istemci tarafı analizler, offline kullanım senaryoları.
- Sunucuyu tercih edin: Büyük veri işlemleri, yoğun CPU bellek kullanımı, kurumsal paket bağımlılıkları, kalıcı depolama ve erişim kontrolünün kritik olduğu projeler.

Örnek Kullanım: Mini Veri Görselleştirme

Aşağıdaki örnek, küçük bir veri kümesiyle Matplotlib’i kullanır. İlk etapta paketi yükleyin, ardından grafiği base64 olarak üretip bir <img> etiketine atayabilirsiniz. (Bu yazıda görsel eklemiyoruz, ancak yaklaşım bu şekildedir.)

await pyodide.loadPackage(["matplotlib", "numpy"]);
const png = await pyodide.runPythonAsync(`import matplotlib.pyplot as plt, io, base64, numpy as np
x = np.linspace(0, 2*np.pi, 200)
y = np.sin(x)
plt.figure(figsize=(3,2), dpi=150)
plt.plot(x, y)
buf = io.BytesIO()
plt.savefig(buf, format="png", bbox_inches="tight")
base64.b64encode(buf.getvalue()).decode()`);
// document.getElementById("plot").src = "data:image/png;base64," + png;

Sonuç

Pyodide ve WebAssembly, Python’u tarayıcıya taşıyarak ön uç geliştirmeye yeni kapılar açıyor. Doğru paket yönetimi, akıllı önbellekleme ve verimli veri paylaşımıyla hem akıcı bir kullanıcı deneyimi hem de sürdürülebilir performans elde edebilirsiniz. Küçük başlayın, ihtiyaç duydukça paketleri ve optimizasyonları ekleyin. Böylece ister eğitim amaçlı mini bir laboratuvar, ister ürününüze gömülü etkileşimli bir analiz modülü geliştirin; modern webin olanaklarından en iyi şekilde yararlanırsınız.

18 Ekim 2025 Cumartesi

Rust ve WebAssembly ile Tarayıcıda Yüksek Performanslı Görüntü Filtresi Geliştirme (Adım Adım)

Giriş

Tarayıcıda yüksek performanslı görüntü işleme yapmak çoğu zaman JavaScript ile zorlayıcı olabilir. Rust ve WebAssembly (WASM) ikilisi sayesinde, CPU yoğun işlemleri güvenli ve hızlı biçimde web tarafına taşıyabilirsiniz. Bu rehberde, Rust ile basit bir gri tonlama filtresi yazacak, wasm-bindgen ve wasm-pack kullanarak WebAssembly’ye derleyecek ve sonucu bir web projesinde çağıracağız. Amaç sade, pratik ve SEO uyumlu bir anlatımla sizi hızlıca üretken hale getirmek.

Neden Rust + WebAssembly?

WebAssembly, tarayıcıda neredeyse yerel hızda çalışabilen bir bayt kod formatıdır. Rust ise bellek güvenliği, sıfır maliyetli soyutlamalar ve modern dil özellikleriyle WebAssembly hedefi için biçilmiş kaftandır. Bu kombinasyon sayesinde, görüntü işleme, ses işleme, veri sıkıştırma gibi CPU yoğun iş yüklerini JavaScript’in tek iş parçacıklı darboğazından çıkarır ve kullanıcıya akıcı bir deneyim sunarsınız.

Önkoşullar ve Kurulum

Başlamadan önce sisteminizde Rust (stable), wasm-pack ve bir paket yöneticisi (npm veya pnpm) kurulu olmalı. Kurulum komutları: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ve cargo install wasm-pack. Web tarafı için basit bir Vite veya React projesi işinizi görecektir.

Rust Kütüphanesini Oluşturma

Yeni bir Rust kütüphanesi oluşturun: cargo new --lib image_filter_wasm. Ardından Cargo.toml dosyanızı aşağıdaki gibi düzenleyin:

[package]
name = "image_filter_wasm"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

Gri Tonlama Filtresi Yazımı

Temel yaklaşımımız, bir Uint8Array içindeki RGBA piksel verisini alıp, gri tonlama uygulayarak yine Uint8Array olarak geri döndürmek. src/lib.rs içeriği örneği:

use wasm_bindgen::prelude::*;
use js_sys::Uint8Array;

#[wasm_bindgen]
pub fn grayscale(input: Uint8Array) -> Uint8Array {
  let mut data = input.to_vec();
  let len = data.len();
  let mut i = 0;
  while i + 3 < len {
    let r = data[i] as u32;
    let g = data[i + 1] as u32;
    let b = data[i + 2] as u32;
    // Luma (BT.709) yaklaşımı
    let y = (0.2126 * r as f32 + 0.7152 * g as f32 + 0.0722 * b as f32) as u8;
    data[i] = y;
    data[i + 1] = y;
    data[i + 2] = y;
    i += 4;
  }
  Uint8Array::from(&data[..])
}

Yukarıdaki örnekte wasm-bindgen ile Uint8Array türünü kullanarak kopyalama maliyetini yönetilebilir düzeyde tutuyoruz. Daha ileri optimizasyonlar için tek seferlik bellek ayırma ve işaretçi tabanlı API’ler de tercih edilebilir.

WebAssembly’ye Derleme

Klasör kökünde wasm-pack build --target web çalıştırın. Bu komut pkg klasöründe tarayıcı uyumlu JS wrapper ve .wasm dosyasını üretir. Alternatif olarak --target bundler ile bundler tabanlı projelere uygun çıktı alabilirsiniz.

Web Projesine Entegrasyon (React Örneği)

Bir React projesinde, canvas üzerinden ImageData elde edip pikselleri WASM fonksiyonuna aktaracağız. Basit bir akış şu şekilde olabilir:

import init, { grayscale } from "./pkg/image_filter_wasm.js";

async function runFilter(ctx, width, height) {
  await init();
  const imageData = ctx.getImageData(0, 0, width, height);
  const input = new Uint8Array(imageData.data.buffer.slice(0));
  const output = grayscale(input);
  imageData.data.set(output);
  ctx.putImageData(imageData, 0, 0);
}

Bu kod, canvas içindeki görseli alır, pikselleri grayscale fonksiyonundan geçirir ve yeniden kanvasa yazar. Geri dönüşte yeni bir Uint8Array aldığımız için doğrudan set ile kopyalamak yeterlidir.

Performans İpuçları

- Kopyalamaları azaltın: Sürekli yeni Uint8Array oluşturmak yerine, tek bir tamponu tekrar kullanacak bir API tasarlayın (ör. işaretçi ve uzunluk üzerinden, ileri düzey wasm-bindgen teknikleriyle).
- SIMD etkinleştirin: Rust’ta wasm32-unknown-unknown hedefi için SIMD desteği stabildir. Yapılandırmada RUSTFLAGS="-C target-feature=+simd128" kullanabilir, wasm-opt -O3 ile Binaryen optimizasyonlarına başvurabilirsiniz.
- İş yükünü ayırın: Büyük resimlerde ana iş parçacığını kilitlememek için Web Worker üzerinden çağrı yapın. Çok iş parçacığı (WASM threads) kullanacaksanız SharedArrayBuffer gerekeceğinden COOP/COEP ile Cross-Origin Isolation aktif olmalı.

Karşılaşılabilecek Sorunlar

- Paketleme: Bazı bundler’lar .wasm dosyalarının kopyalanması ve yüklenmesi için özel yapılandırma ister. --target web çıktısı, modern bundler’larla genelde sorunsuzdur.
- Tür uyumsuzluğu: ImageData.data Uint8ClampedArray döndürür. Bu nedenle Uint8Array dönüşümü yaptığımızdan emin olmalıyız.
- Boyut: WASM paketinin boyutunu düşük tutmak için gereksiz bağımlılıklardan kaçının ve wasm-opt kullanın.

Test ve Ölçüm

Basit bir FPS sayacı veya zaman damgası ile performance.now() ölçümleri alarak JavaScript ve WASM sürümlerini kıyaslayın. Büyük çözünürlükteki görsellerde, Rust + WebAssembly yaklaşımının belirgin şekilde daha düşük gecikme ve daha yüksek kare/saniye ürettiğini göreceksiniz.

Sonuç

Rust ve WebAssembly, tarayıcıda yüksek performanslı görüntü işleme için güçlü ve sürdürülebilir bir çözüm sunar. Bu rehberde, sıfırdan bir gri tonlama filtresi yazarak derleme, entegrasyon ve optimizasyon adımlarını gördük. Aynı yöntemi keskinleştirme, bulanıklaştırma, kenar algılama gibi farklı filtrelerle genişletebilir, hatta gerçek zamanlı kamera akışlarına uygulayabilirsiniz. Modern web uygulamalarında performansı öne çıkarmak istiyorsanız, Rust + WASM öğrenme eğrisine kesinlikle değer.

16 Ekim 2025 Perşembe

Rust ve WebAssembly ile Tarayıcıda Görüntü İşleme: Adım Adım Rehber

Giriş

WebAssembly (WASM), tarayıcıda neredeyse yerlisi kadar hızlı çalışan kodlar yazmayı mümkün kılıyor. Eğer piksel piksel görüntü işleme, gerçek zamanlı filtreler veya CPU yoğun işlemlerle uğraşıyorsanız, JavaScript tek başına her zaman yeterli olmayabilir. Bu rehberde, Rust + WebAssembly ikilisini kullanarak tarayıcıda basit bir görüntü işleme modülü oluşturmayı ve performansı artırmanın pratik yollarını adım adım anlatıyorum.

Neden Rust + WebAssembly?

Performans: Rust derlenmiş kodu WebAssembly’ye taşıdığınızda, piksel manipülasyonu gibi yoğun işlemlerde belirgin bir hız kazanırsınız. Özellikle büyük görsellerde JavaScript döngülerinin sınırlamalarını aştığınızı hissedeceksiniz.

Bellek güvenliği: Rust’ın sahiplik modeli ve derleyici kontrolleri, tipik bellek hatalarını en başında engeller. Tarayıcı gibi hassas bir ortamda bu oldukça kritiktir.

Taşınabilirlik: WASM çıktısı, modern tüm tarayıcılarda çalışır. Rust tarafında yazdığınız çekirdek algoritmaları, Node.js veya Wasmtime gibi ortamlarda da kullanabilirsiniz.

Gereken Araçlar ve Kurulum

Rust kurulumu için resmi yönlendiriciyi tercih edin: rustup. Ardından WASM hedefini ekleyin: rustup target add wasm32-unknown-unknown. Paketleme ve bağlayıcılar için wasm-pack aracını kurun: cargo install wasm-pack. Tarayıcı tarafında modülü kullanmak için npm veya yarn da işinizi kolaylaştırır.

Yeni bir kütüphane projesi oluşturun: cargo new goruntu-wasm --lib. Proje klasörüne geçin ve Cargo.toml dosyasına wasm-bindgen bağımlılığını ekleyin.

Proje İskeleti ve Yapılandırma

Cargo.toml içine aşağıdakine benzer satırlar ekleyin: [dependencies] wasm-bindgen = "0.2". Derleme hedefi için [lib] bölümüne crate-type = ["cdylib", "rlib"] yazmayı unutmayın. Bu, Rust kütüphanesinin WASM olarak bağlanabilmesini sağlar.

Kaynak dosyası src/lib.rs içinde, JavaScript ile köprü kurmak için wasm_bindgen makrolarını kullanacağız. Temel bir dışa aktarma şöyle görünür: use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn versiyon() -> String { "0.1.0".into() }. Bu, tarayıcıda modül yüklendiğinde çağrılabilir bir fonksiyon üretir.

Tarayıcı Entegrasyonu

Derlemek için wasm-pack build --target web komutunu çalıştırın. Bu, pkg klasöründe ES modül uyumlu bir çıktı üretir. Ön yüzde bir modül dosyasında şu şekilde içe aktarabilirsiniz: import init, { versiyon } from "./pkg/goruntu_wasm.js"; await init(); console.log(versiyon());. Basit bir HTML sayfasında <script type="module"> kullanarak bu modülü kolayca yükleyebilirsiniz.

Paket yöneticisi ile entegre çalışmak isterseniz wasm-pack çıktısını bir NPM paketi gibi tüketebilirsiniz. Bu sayede Vite, Webpack veya Parcel ile ağaç sarsma ve önbellekleme gibi optimizasyonlardan faydalanırsınız.

Basit Bir Gri Tonlama (Grayscale) Örneği

Tarayıcıdan aldığınız ImageData nesnesi, RGBA kanal sıralı bir Uint8ClampedArray içerir. Bu diziyi WASM tarafına aktarıp geri almak için iki pratik yol var: kopyalamak veya paylaşılan bir tampon üzerinden erişmek. Başlangıç için, güvenli ve net olduğu için kopyalama yaklaşımı işinizi görecektir.

Rust tarafında bir fonksiyon düşünün: #[wasm_bindgen] pub fn grayscale(input: Vec<u8>) -> Vec<u8> { ... }. Algoritma basit: Her piksel için r, g, b değerlerinin ağırlıklı ortalamasını alın ve geri yazın. Yaygın bir yaklaşım: gray = 0.299*r + 0.587*g + 0.114*b. Rust’ta tamsayı işlemlerinde küçük bir yuvarlama eklemek renk doğruluğunu iyileştirir.

Ön yüzde, CanvasRenderingContext2D ile bir görüntüyü çizip getImageData ile pikselleri alın. Daha sonra const out = grayscale(new Uint8Array(imageData.data)); gibi bir çağrıyla sonuç dizisini alın ve putImageData ile tekrar tuvale yazın. Bu döngüde veriyi fazla kopyalamamak için işlemi toplu yapın; birden fazla filtre uygulayacaksanız tek bir WASM çağrısında zincirlemek daha etkilidir.

Performans İpuçları

SIMD desteği: Modern tarayıcılar WASM SIMD’i destekliyor. Rust’ta std::arch veya uygun crate’lerle vektörleştirme yaparak yaklaşık 2-4 kat hız artışı görebilirsiniz. Varsa RUSTFLAGS="-C target-feature=+simd128" deneyin.

Veri kopyalarını azaltın: Çok büyük görüntülerde her karede kopyalama pahalıdır. Orta vadede wasm-bindgen ile Uint8Array tamponunu paylaşmak veya WebAssembly.Memory üzerinden doğrudan yazmak daha iyi sonuç verir.

Web Workers: Ana iş parçacığını kilitlememek için görüntü işlemeyi bir Worker içine taşıyın. OffscreenCanvas kullanabiliyorsanız, çizim ve filtrelemeyi tamamen worker içine izole ederek UI akıcılığını korursunuz.

Ön ısıtma: Modülü sayfa yüklenir yüklenmez başlatıp küçük bir “ısındırma” çağrısı yapmak, JIT/optimizasyon basamaklarını kullanıcı etkileşimi öncesinde tamamlamaya yardımcı olur.

Hata Ayıklama ve Ölçüm

WASM kodunu debug modunda derlediğinizde boyut artar ve performans düşer; bu normaldir. Geliştirmede console.time/console.timeEnd ile uçtan uca süreleri ölçün, Performance.now() ile kare bazlı gecikmeyi takip edin. Rust tarafında log ve console_error_panic_hook kullanarak panik ve logları tarayıcı konsoluna yönlendirebilirsiniz.

Boyut optimizasyonu için üretim derlemesinde wasm-opt -O3 (Binaryen) deneyin. Ayrıca wasm-pack build --release kullanarak sembol isimlerini küçültür ve gereksiz debug bilgilerini atarsınız.

Sonuç

Rust ve WebAssembly, tarayıcıda görüntü işleme gibi CPU ağırlıklı görevlerde güvenli, hızlı ve öngörülebilir bir çalışma zemini sunuyor. Basit bir gri tonlama filtresiyle başladık; aynı yaklaşımı kenar algılama, bulanıklaştırma, renk düzeltme veya gerçek zamanlı kamera filtrelerine kolayca genişletebilirsiniz. Doğru veri aktarım stratejisi, SIMD ve Web Workers ile birleştiğinde, modern web uygulamalarında yerel uygulama hissi veren bir performans elde etmek mümkün. Bir kez kurduktan sonra, bu altyapıyı pek çok projede tekrar tekrar kullanabileceğinizi göreceksiniz.

7 Ekim 2025 Salı

WebGPU Destekli ONNX Runtime Web ile Tarayıcıda Yapay Zeka Çalıştırma: Adım Adım Rehber

Giriş

Tarayıcıda yapay zeka çalıştırmak, artık sadece demo projelerin konusu değil. WebAssembly (WASM) ve WebGPU sayesinde, masaüstü benzeri performansla gerçek zamanlı çıkarım almak mümkün. Bu rehberde, ONNX Runtime Web kullanarak bir modeli tarayıcıda çalıştırmayı, WebGPU ve WASM arasında nasıl seçim yapacağınızı ve performansla ilgili pratik ipuçlarını adım adım anlatıyorum.

Neden Tarayıcıda Yapay Zeka?

Tarayıcı üzerinde çıkarımın üç büyük avantajı var: gizlilik (veri cihazdan çıkmıyor), kurulum kolaylığı (ekstra bağımlılık yok) ve dağıtım hızı (sadece bir web sayfası). Örneğin bir görüntü sınıflandırma modeli, web uygulamanızda kullanıcı fotoğrafını anında analiz edebilir ve bu sırada veriyi sunucuya göndermenize gerek kalmaz. Üstelik WebGPU desteği olan tarayıcılarda GPU hızlandırma ile mobil cihazlarda bile akıcı performans elde edebilirsiniz.

Gereksinimler

- Güncel bir tarayıcı (Chrome 113+, Edge 113+, Safari 17+). WebGPU desteği yoksa WASM sağlayıcısı otomatik devreye girer.
- Basit bir HTTP sunucu (ör. npx serve veya python -m http.server). Güvenlik nedeniyle dosyaları doğrudan dosya sistemi üzerinden açmak yerine bir sunucu gerekli.
- Bir ONNX modeli (ör. MobilNet v2 sınıflandırma modeli). Dilerseniz kendi modelinizi torch.onnx.export ile dışa aktarabilirsiniz.

Proje Kurulumu

1) Klasör oluşturun: mkdir ort-web-demo && cd ort-web-demo
2) Model dosyasını model.onnx olarak kök dizine koyun.
3) Aşağıdaki basit HTML dosyasını index.html olarak kaydedin (CDN üzerinden ONNX Runtime Web yüklenecek):

<!doctype html>
<html lang="tr">
<head>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <title>ONNX Runtime Web Demo</title>
</head>
<body>
  <h3>Tarayıcıda Yapay Zeka (WebGPU / WASM)</h3>
  <input type="file" id="file" accept="image/*"/>
  <div id="log">Hazır...</div>
  <script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
  <script>
  (async () => {
    // WebGPU uygunsa önce onu, değilse WASM'ı dene
    const providers = (navigator.gpu) ? ['webgpu', 'wasm'] : ['wasm'];
    ort.env.wasm.simd = true; // SIMD hızlandırma
    ort.env.wasm.numThreads = Math.min(4, navigator.hardwareConcurrency || 2);

    const session = await ort.InferenceSession.create('model.onnx', { executionProviders: providers });
    document.getElementById('log').innerText = 'Model yüklendi. Sağlayıcı: ' + session.executionProvider;

    const fileInput = document.getElementById('file');
    fileInput.onchange = async () => {
      const file = fileInput.files[0];
      if (!file) return;
      const img = new Image();
      img.src = URL.createObjectURL(file);
      await img.decode();

      // Basit ön işleme: 224x224'e ölçekle, [0,1] normalizasyonu
      const canvas = document.createElement('canvas');
      canvas.width = 224; canvas.height = 224;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(img, 0, 0, 224, 224);
      const { data } = ctx.getImageData(0, 0, 224, 224);
      const input = new Float32Array(1 * 3 * 224 * 224);
      for (let i = 0; i < 224 * 224; i++) {
        const r = data[i * 4] / 255;
        const g = data[i * 4 + 1] / 255;
        const b = data[i * 4 + 2] / 255;
        input[i] = r; input[i + 224 * 224] = g; input[i + 2 * 224 * 224] = b;
      }

      const tensor = new ort.Tensor('float32', input, [1, 3, 224, 224]);
      const feeds = {}; feeds[session.inputNames[0]] = tensor;
      const t0 = performance.now();
      const results = await session.run(feeds);
      const t1 = performance.now();
      const output = results[session.outputNames[0]].data;
      const maxIndex = output.indexOf(Math.max(...output));
      document.getElementById('log').innerText = `Sınıf: ${maxIndex}, Süre: ${(t1 - t0).toFixed(1)}ms`;
    };
  })();
  </script>
</body>
</html>

Uygulamayı Çalıştırma

Kök dizinde küçük bir sunucu başlatın. Node.js varsa: npx serve . veya Python ile: python -m http.server 8080. Ardından tarayıcıdan http://localhost:8080 adresine gidin. Bir görsel seçtiğinizde model çıkarımı yapacak ve süreyi ms cinsinden gösterecektir. WebGPU mevcutsa sağlayıcı olarak webgpu, değilse wasm kullanılır.

Performans İpuçları

- SIMD ve çok iş parçacığı: Kodda ort.env.wasm.simd = true ve numThreads ayarları etkin. Tarayıcı buna izin veriyorsa WASM performansı ciddi artar.
- WebGPU avantajı: Büyük modellerde GPU hızlandırma dramatik fark yaratır. Ancak WebGPU, HTTPS ve güvenli bağlam gerektirir. Üretimde daima HTTPS kullanın.
- Model optimizasyonu: ONNX modeli fuse ve constant folding ile optimize edin. INT8 quantization (ör. onnxruntime-tools veya optimum) tarayıcıda boyutu küçültür ve hız kazandırır.
- Lazy yükleme: Modeli sayfa yüklendiğinde değil, kullanıcı etkileşimi başladığında indirin. İlk TTI süresini iyileştirir.
- Önbellek: Model dosyasını IndexedDB veya Cache Storage ile saklayın. İlk açılıştan sonra bekleme neredeyse sıfırlanır.

Hata Ayıklama ve Uyumluluk

- Giriş/çıkış adları: Bazı modellerde giriş ismi input değil, farklı olabilir. session.inputNames ve session.outputNames ile dinamik alın.
- Bellek limitleri: Büyük modeller mobilde bellek sınırına takılabilir. Daha küçük veya quantized sürüme geçin.
- CORS: Modeli farklı bir domain’den çağırıyorsanız CORS başlıklarını doğru ayarlayın (Access-Control-Allow-Origin).
- Tarayıcı farkları: Safari’de GPU bellek kotaları daha katı olabilir; WASM yedek planınızın iyi çalıştığından emin olun.

Güvenlik ve Gizlilik

Tarayıcıda çıkarımın en güçlü yanı, verinin cihazda kalmasıdır. Yine de kullanıcı içeriğini asla arka plana otomatik yüklemeyin ve gerekli olmadıkça loglamayın. Model dosyalarınızı bütünlüğü doğrulanmış bir CDN’den servis edin ve içerik güvenlik politikanızda (Content-Security-Policy) sadece ihtiyaç duyulan kaynaklara izin verin.

Sonuç

ONNX Runtime Web ile WebGPU/WASM arasında otomatik geçiş yaparak, modern tarayıcılarda güçlü bir yapay zeka deneyimi sunmak mümkün. Yukarıdaki basit örnek; görüntü sınıflandırma, metin analizi veya poz tahmini gibi pek çok senaryonun temelini oluşturur. Üretime geçerken model optimizasyonu, önbellekleme ve güvenlik adımlarını uyguladığınızda, native’e yakın bir hız ve akıcılık elde edebilirsiniz.

3 Ekim 2025 Cuma

WASI ile WebAssembly CLI Dağıtımı: Wasmtime Kullanarak Docker’sız, Taşınabilir Araçlar

Giriş

CLI araçlarını farklı işletim sistemlerine dağıtmak çoğu zaman zahmetlidir. Her platform için ayrı derlemeler, paylaşımlı kütüphane bağımlılıkları ve güvenlik kısıtları bir araya gelince, iş büyür. WebAssembly (WASM) ve WASI (WebAssembly System Interface), bu sorunu modern ve güvenli bir yaklaşımla çözüyor. WASI sayesinde uygulamanızı tek bir .wasm dosyası olarak paketleyip, Wasmtime gibi bir çalışma zamanı üzerinde Linux, macOS ve Windows’ta aynı şekilde çalıştırabilirsiniz. Bu öğreticide, Rust ile küçük bir CLI aracını WASI için derleyip Wasmtime ile çalıştırmayı ve pratik ipuçlarını paylaşacağım.

WASM ve WASI Nedir?

WASM, sandbox edilmiş bir bytecode formatıdır; bir kez derlediğiniz kodu farklı ortamlarda güvenle koşturmanıza olanak tanır. WASI ise dosya sistemi, çevre değişkenleri, saat ve benzeri sistem kaynaklarına erişim için standart bir arayüz sunar. En kritik avantajı, yetenek tabanlı (capability-based) güvenlik modelidir: Uygulama dosya sistemine, ağ veya diğer kaynaklara varsayılan olarak erişemez; hangi izinleri verdiyseniz yalnızca onlarla çalışır.

Gereksinimler

- Rust ve cargo (rustup ile kurulabilir)
- Wasmtime çalışma zamanı (brew install wasmtime ya da choco install wasmtime)
- Rust için WASI hedefi: rustup target add wasm32-wasi

Adım Adım: Rust CLI’yi WASI için Derlemek

1) Yeni bir proje oluşturun: cargo new hello-wasi komutundan sonra dizine girin.
2) src/main.rs içine basit bir örnek koyun. Argümanları yazdıran ve bir dosyayı okuyan minimal bir gövde şöyle olabilir: fn main() { let args: Vec<String> = std::env::args().collect(); eprintln!("Argümanlar: {:?}", args); let path = std::env::var("INPUT").unwrap_or("input.txt".into()); let data = std::fs::read_to_string(path).unwrap_or_default(); println!("{}", data); }
3) WASI hedefi için derleyin: cargo build --release --target wasm32-wasi. Üretilen dosya: target/wasm32-wasi/release/hello-wasi.wasm

Wasmtime ile Çalıştırma

WASI, dosya sistemi erişimine varsayılan izin vermez. Çalıştırırken hangi dizinlere erişileceğini belirtmelisiniz. Örneğin, geçerli dizine erişim verip bir argüman da geçmek için: wasmtime --dir=. target/wasm32-wasi/release/hello-wasi.wasm merhaba. Eğer program dosya okuyacaksa, çevre değişkenlerini de iletebilirsiniz: wasmtime --dir=. --env INPUT=input.txt target/wasm32-wasi/release/hello-wasi.wasm. Bu şekilde uygulama yalnızca izin verdiğiniz yollara ulaşır; kök sisteme doğrudan erişemez.

Paketleme ve Dağıtım Stratejileri

- Tek dosya yaklaşımı: Uygulamanızı yalnızca .wasm olarak paylaşın ve kullanıcılara Wasmtime kurmalarını söyleyin. Çoğu Linux/macOS/Windows ortamında kurulum dakikalar içinde yapılır.
- Önceden derlenmiş modüller: wasmtime compile -o app.cwasm app.wasm ile JIT yerine AOT derlenmiş bir çıktı üretip daha hızlı başlangıç süreleri elde edebilirsiniz.
- Küçük runner ekleme: Bazı takımlarda, Wasmtime binary’si ile .wasm dosyasını aynı pakete koyup basit bir wrapper script ile kullanım sağlamak yaygındır. Bu, “docker’sız, tek arşiv” dağıtımı kolaylaştırır.

Performans ve Boyut

WASM performansı, CPU-ağırlıklı olmayan CLI’larda çoğu kullanım için yeterince hızlıdır. Başlangıç süresi kısa, bellek tüketimi kontrollüdür. Rust tarafında LTO ve strip ayarlarıyla boyutu küçültebilirsiniz: [profile.release] lto = "thin", opt-level = "z" gibi ayarlar ve cargo build --release sonrası wasm-opt -Oz (Binaryen) ek sıkıştırma sağlayabilir. Tipik bir basit araç 300 KB – birkaç MB aralığında olur.

Sınırlamalar ve Çözüm Yolları

- Ağ erişimi: WASI’nin ağ API’leri hâlâ olgunlaşma aşamasında. Wasmtime deneysel soket uzantılarıyla çalışabilir, ancak üretimde dikkatle değerlendirin. Alternatif olarak, ağ erişimini bir proxy süreci veya HTTP üzerinden borulama (stdin/stdout) ile soyutlayabilirsiniz.
- Çoklu thread’ler: WASI-threads yaygınlaşsa da her çalışma zamanı aynı olgunlukta değil. CLI tarafında işbirlikçi asenkron mimari (ör. tokio + wasm32-wasi) çoğu senaryoda yeterli olur.
- Dinamik bağlama: Paylaşımlı kütüphaneler yerine statik ve portable bağımlılıklar tercih edin. Bu yaklaşım zaten WASM’in tasarım felsefesine daha uygundur.

Alternatif Diller ve Araçlar

Rust en iyi deneyimlerden birini sunar, ancak tek seçenek değil. TinyGo ile Go kodunu GOOS=js GOARCH=wasm yerine doğrudan wasm32-wasi hedefiyle derlemek mümkün. Zig ve C/C++ projeleri de WASI için güçlü adaylardır. JavaScript tarafında Node’un WASI modülü ile sınırlı ama işe yarar kullanım alanları mevcuttur.

Güvenlik ve Uyumluluk

WASI’nin yetenek tabanlı modeli, yanlışlıkla sistem dosyalarını silme veya gizli ortam değişkenlerine erişme riskini kökten azaltır. Komut satırında her hak açıkça verilir: --dir, --env gibi bayrakları kullanmadığınız sürece uygulamanız “kör ve sağır” bir kutuda çalışır. Bu, regülasyonlu ortamlarda denetlenebilirlik ve asgari ayrıcalık ilkesi açısından büyük bir artıdır.

Gerçek Dünya Senaryoları

- İç araçlar: Veri dönüştürücüler, şema doğrulayıcılar, log filtreleyiciler tek .wasm olarak dağıtılabilir.
- CI/CD adımları: Çoklu işletim sistemi matrislerinde aynı .wasm’ı koşarak “build once, run anywhere” elde edersiniz.
- Eklenti mimarileri: Ana uygulama, .wasm eklentilerini güvenli sandbox’ta çalıştırarak güvenlik yüzeyini daraltabilir.

Sonuç

WASI destekli WebAssembly, CLI araçlarının dağıtımını basitleştirirken güvenlik ve taşınabilirliği artırır. Wasmtime ile birkaç komutla hem geliştirme hem de çalıştırma deneyimi elde edersiniz. Ağ ve thread’ler gibi bazı alanlar hâlâ olgunlaşsa da, bugün itibarıyla dosya işleme, metin dönüştürme, doğrulama ve otomasyon görevleri için üretime hazır bir seçenek. Eğer farklı platformlarda aynı davranışı sunan, Docker kurulumuna bağımlı olmayan ve denetlenebilir izinlerle çalışan araçlar istiyorsanız, bir sonraki CLI’nızı WASI hedefiyle derlemeyi ciddi biçimde düşünün.

24 Ağustos 2025 Pazar

Rust ile WebAssembly (WASM) Performans Optimizasyonu: Adım Adım Rehber

Giriş — Neden Rust + WASM?

Rust ile WebAssembly (WASM) birbirini tamamlayan iki teknoloji: Rust'ın bellek güvenliği ve sıfır maliyet soyutlamaları, WASM'in tarayıcıda çalışabilen düşük seviyeli modülleriyle birleştiğinde hem performans hem de güvenlik sağlar. Bu rehberde, Rust ile yazılmış bir WASM modülünü oluştururken karşılaşacağınız temel yapılandırmaları, performans tuzaklarını ve optimizasyon tekniklerini adım adım ele alacağım.

Hazırlık ve araçlar

İhtiyacınız olanlar: Rust toolchain (rustup), wasm-pack veya cargo + wasm-bindgen, binaryen/wasm-opt (wabt ve binaryen paketleri) ve bir frontend paketleyici (ör. webpack veya Vite). Başlangıç için terminalde rustup target add wasm32-unknown-unknown, cargo install wasm-pack ve wasm-opt kurulumunu yapın. Bu araçlar derleme, bağlama ve ikili optimizasyon süreçlerinde kritik öneme sahip.

Basit bir örnek: fonksiyonları dışa aktarma

Rust'ta basit bir fonksiyonu WASM'e dışa aktarmak için wasm-bindgen kullanın. Örnek:

use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn sum(a: i32, b: i32) -> i32 {
    a + b
}

Bu kodu wasm-pack build --target web ile derleyip, tarayıcı tarafında import ederek kullanabilirsiniz. Ancak performans için dikkat edilmesi gerekenler yalnızca derlemek değildir; nasıl çağırdığınız ve veri taşıdığınız da önemlidir.

Performans odaklı ipuçları

1) JS↔WASM sınırını minimize edin: Her JS-WASM çağrısı CPU yükü ve marjinal overhead getirir. Küçük, sık yapılan çağrılar yerine veri blokları gönderip tek seferde işlemek genelde daha verimlidir.

2) Bellek yönetimi: WASM lineer belleği kullanır. Büyük veri için Vec kullanıp pointer ve uzunluk dönerek SharedArrayBuffer/ArrayBuffer üzerinden doğrudan erişim sağlayın. Böylece kopyalamaları azaltırsınız.

3) Veri tiplerini basit tutun: Karmaşık nesne serileştirmeleri yerine ikili formatlar veya sabit tipli diziler kullanın. JSON yerine biner format performansı belirgin şekilde artırır.

4) SIMD ve multi-threading: Tarayıcılar artık SIMD ve Threads için deneysel destek sunuyor. simd128 ve atomics özelliklerini kullanmak büyük hesaplamalarda hız verir, ancak Cross-Origin-Opener-Policy (COOP) ve Cross-Origin-Embedder-Policy (COEP) başlıkları gerektirir.

Derleme ve optimizasyon bayrakları

Release derlemelerinde cargo build --release veya wasm-pack build --release kullanın. Ek olarak RUSTFLAGS ile LTO (link time optimization) ve hedef özelliklerini açabilirsiniz:

export RUSTFLAGS="-C opt-level=z -C linker-plugin-lto -C codegen-units=1"
wasm-pack build --release

Opt-level=z dosya boyutuna odaklanır; -C opt-level=3 ise hız odaklıdır. Ardından wasm-opt -Oz ile ikiliyi küçültün ve performans profili doğrultusunda -O3 seçeneğini değerlendirin.

Boyut azaltma ve dağıtım

WASM modüllerini gzip veya brotli ile sıkıştırıp sunmak yükleme süresini büyük ölçüde azaltır; brotli genelde daha iyi sıkıştırma sağlar. Ayrıca kullanılmayan kodu elimine eden tree-shaking ve cargo features ile gereksiz bağımlılıkları kaldırın. wasm-snip veya cargo-udeps gibi araçlar gereksiz kodu tespit etmekte yardımcı olur.

Profiling ve ölçme

Performans iyileştirmelerinin etkisini ölçmeden uygulamak yanıltıcı olabilir. Tarayıcıların Performans/Profiler araçları, WASM hotspot'larını görmenizi sağlar. Ayrıca wasm-objdump ve wasm-validate ile ikiliyi analiz edin. Gerçek dünya yüklerini taklit eden benchmark'lar oluşturun; mikro benchmark'lar yanıltıcı olabilir.

Sık yapılan hatalar ve çözüm önerileri

- Çok küçük fonksiyonları sık çağırmak: Bunları birleştirin veya toplu işleyin. - Aşırı kopyalama: Bellek penceresi kullanarak kopyalamayı azaltın. - Yanlış derleme bayrakları: test ve release davranışını karıştırmayın; release ile ölçün. - COOP/COEP gereksinimlerini göz ardı etmek: Threaded WASM için server başlıklarını doğru ayarlayın.

Sonuç

Rust + WASM ile yüksek performanslı web modülleri oluşturmak mümkün ve sürdürülebilir. Temel prensipler: JS-WASM sınırını akıllıca yönetmek, bellek erişimini optimize etmek, doğru derleme ve ikili optimizasyonları kullanmak ve sonuçları dikkatle ölçmektir. Bu rehber, bir başlangıç yolu sunar; gerçek uygulamalar için spesifik profil verilerine dayanarak ince ayar yapmanız en iyi sonucu verecektir.

22 Ağustos 2025 Cuma

Rust ile WebAssembly (WASM) Kullanarak Yüksek Performanslı Web Uygulamaları Geliştirme

Giriş

Web uygulamalarında CPU yoğunluklu işlemleri tarayıcıya taşımak gerektiğinde WebAssembly (WASM) önemli bir seçenek sunar. Rust ise bellek güvenliği, performans ve derleyici garantileriyle WASM için sık tercih edilen dillerden biridir. Bu yazıda, Rust ile WASM geliştirirken dikkat edilmesi gereken temel adımları, optimizasyonları ve üretime hazırlık süreçlerini sade ve uygulamalı şekilde ele alacağım.

Hazırlık ve araçlar Öncelikle sisteminizde Rust kurulu olmalı. rustup üzerinden güncel toolchain'i kurduktan sonra hedef olarak wasm32-unknown-unknown eklenir: rustup target add wasm32-unknown-unknown. Ardından proje paketlemeyi kolaylaştıran wasm-pack veya doğrudan wasm-bindgen tercih edilebilir. İyi bir optimizasyon için Binaryen'in wasm-opt aracını da kurmanızı öneririm.

Basit bir başlangıç örneği

Yeni bir kütüphane projesi oluşturup JavaScript ile çağırılabilir fonksiyonler yazalım. Cargo projesi oluşturduktan sonra Cargo.toml'a wasm-bindgen ekleyin ve Rust kodunda şu örneği kullanın:

use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn heavy_compute(n: u32) -> u64 { (0..n as u64).map(|x| x * x).sum() }

Derleme aşaması için iki yaygın yol var: wasm-pack build --target web --release ile paketleyip doğrudan bir modül olarak kullanmak veya cargo build --target wasm32-unknown-unknown --release sonrası wasm-bindgen CLI ile çıktıyı hazırlamak. wasm-pack yeni başlayanlar için entegrasyon kolaylığı sağlar.

Performans ipuçları

WASM ve Rust kombinasyonunda performansı etkileyen başlıca noktalar şunlardır: bellek tahsisi, JavaScript ile sınır-maliyetli geçişler, veri kopyalama ve algoritma seçimi. Fonksiyonlar arasında sık sık büyük veri yapıları geçiriyorsanız, işinizi Rust içinde bitirip tek bir sonuç döndürmeye çalışın. JS-Rust dönüşümlerinde serializasyon maliyetini azaltmak için serde-wasm-bindgen kullanabilirsiniz.

Ayrıca, release derlemelerinde --release kullanmak ve mümkünse wasm-opt -Oz ile sıkıştırma yapmak önemlidir. Örnek: wasm-opt pkg/your_crate_bg.wasm -Oz -o pkg/your_crate_bg.wasm. Bunun yanında wasm-strip ile gereksiz sembolleri kaldırabilirsiniz.

Tarayıcı özellikleri: SIMD ve threads

WASM SIMD ve threads (Web Workers + SharedArrayBuffer) performansı ciddi oranda artırabilir, ancak tarayıcı desteği ve güvenlik başlıkları gerektirir. Threads kullanmak için sunucunuzda COOP/COEP başlıklarını ayarlayarak cross-origin isolation sağlamalısınız. SIMD ise belirli tarayıcı sürümlerinde etkin olur; derleme sırasında RUSTFLAGS="-C target-feature=+simd128" gibi bayraklar kullanılabilir ve hedef desteğine dikkat edilmelidir.

Hata ayıklama ve geliştirici deneyimi

WASM çıktıları doğrudan okunması zor olabilir. Rust tarafında panik mesajlarını tarayıcı konsoluna almak için console_error_panic_hook kullanın: console_error_panic_hook::set_once(). Kaynak haritaları (source maps) ile Rust kaynaklarına dönebilmek için ilgili araçları etkinleştirin. Ayrıca wasm-bindgen çıktılarındaki JS wrapper'ları incelenebilir; onlar JS tarafında yapılması gereken hafif köprüleri gösterir.

Dağıtım ve boyut azaltma

Üretim ortamında paket boyutu ve yükleme süresi önemlidir. Aşağıdaki adımlar genelde iyi sonuç verir: release derleme, wasm-opt -Oz, gzip ya da brotli sıkıştırma, ve JS paketleyicide tree-shaking. Eğer proje büyükse, kritik olmayan kodu WebAssembly yerine JS veya dinamik modüller olarak ayırmak da yararlı olabilir.

Frameworkler ve örnekler

Tek başına WASM kullanmak kadar Yew veya Seed gibi Rust tabanlı çerçevelerle SPA geliştirmek de mümkün. Bu çerçeveler geliştirme deneyimini hızlandırır ancak çıktı büyüklüğünü etkileyebilir; dolayısıyla ön testler yapın ve yalnızca ihtiyaç duyulan parçaları kullanın.

Sonuç Rust + WebAssembly modern web uygulamalarında performansı artırmak için güçlü bir kombinasyon sunar. Ancak başarı için derleme ve optimizasyonda dikkatli olmak, JS-etkileşim maliyetlerini minimize etmek ve tarayıcı özellikleri ile kısıtlamalarını bilmek gerekir. Küçük bir modül ile başlayın, profilleyin ve adım adım üretim güvenliğine geçin.

21 Ağustos 2025 Perşembe

Rust ile WebAssembly (Wasm) Performans ve Güvenlik Rehberi

Rust ile WebAssembly: Neden ve Ne Zaman?

WebAssembly (Wasm) son yıllarda tarayıcı dışı ortamlarda da popüler hale geldi; performans-kritik hesaplamalar, edge uygulamaları ve güvenli eklentiler için ideal bir hedef sunuyor. Rust ise bellek güvenliği ve düşük seviyeli kontrol vaat ettiği için Wasm ile doğal bir uyum sağlıyor. Bu makalede Rust ile Wasm geliştirmeye başlarken dikkat etmeniz gereken performans optimizasyonları ve güvenlik uygulamalarını, pratik adımlarla ele alıyoruz.

Gereksinimler ve Araç Zinciri

Başlamak için sisteminizde Rust (stable), wasm-pack veya doğrudan cargo ve wasm-bindgen, ayrıca wasm optimizasyonu için binaryen (içindeki wasm-opt) kurulu olmalı. Sunucu tarafı veya local testler için wasmtime veya wasmer gibi runtime'lar işinizi kolaylaştırır. Tarayıcı hedefleri için wasm-bindgen + wasm-pack hala en yaygın yol.

Proje Oluşturma ve Temel Ayarlar

Yeni bir proje oluşturun: cargo new --lib my_wasm. Ardından Cargo.toml içine wasm-bindgen bağımlılığını ekleyin. Optimize derlemeler için [profile.release] bölümünde opt-level = "z" veya "s", lto = true, codegen-units = 1 gibi ayarlar performansı ve ikili boyutunu iyileştirir. Panik davranışını küçültmek için panic = "abort" kullanın.

Basit Bir Örnek Fonksiyon

Birkaç basit fonksiyon yazarak arayüz maliyetlerini görün: örneğin büyük veri üzerinde hesaplama yapan bir fonksiyonun JS-Wasm sınırını sık çağırmamak gerekir. Veri paylaşımı için tercihen linear memory üzerinde bloklar kullanın ve küçük çağrıları birleştirin. Aşağıdaki gibi bir örnek düşünün:

#[wasm_bindgen]
pub fn sum_slice(ptr: *const u32, len: usize) -> u64 {
    // Güvenli sınır kontrolleri ve hızlı iterasyon
}

Performans İpuçları

1) Arayüz sınırlarını azaltın: JS ile her çağrıda veri kopyalamak pahalıdır; büyük tamponları paylaşılan bellekte tutun. 2) Bellek allokasyonlarını sınırlayın: Rust tarafında sık alıştırma/serbest bırakma yerine önceden ayrılmış buffer'lar kullanın. 3) wasm-opt -O3 ve strip işlemleriyle çıktıyı küçültün. 4) Gereksiz özelllikleri dışarıda bırakın (std yerine core, alloc tercihleri). 5) Profiling: tarayıcıda Performance tab, Wasmtime profil araçları veya console_log kullanarak darboğazları tespit edin.

Güvenlik Hususları

Wasm doğal olarak sandboxlıdır fakat host ile etkileşimde dikkatli olmak gerekir. Host fonksiyonlarını minimal ve kontrollü tutun; mümkünse capability-based model uygulayın. Kullanıcı tarafından sağlanan girişleri her zaman doğrulayın (uzunluk kontrolleri, sınır aşımı kontrolleri). Sunucu tarafında Wasmtime gibi runtime'larda sadece gerekli WASI izinlerini verin. Tarayıcıda Content Security Policy (CSP) ve COOP/COEP başlıkları ile dış yükleme riskini azaltın.

Runtime Seçimi: Tarayıcı vs Sunucu

Tarayıcı uygulamaları için wasm-bindgen ve wasm-pack ideal; threading (WebWorkers) gerekiyorsa SharedArrayBuffer izinleri ve uygun başlıklar gerekli. Sunucu tarafında ise Wasmtime/Wasmer daha fazla kontrol ve performans sunar; ayrıca native I/O bağlayıcılarıyla entegrasyon mümkündür. Hangi runtime'ı seçerseniz seçin, bellek sınırlarını ve CPU kaynaklarını kısıtlayacak politikalar uygulayın.

Dağıtım ve İzleme

Üretilen .wasm dosyalarını CDN üzerinde sunmak performansı iyileştirir. Sürüm yönetimini sıkı tutun; geri uyumluluğu sağlamak için semantik versiyonlama kullanın. Canlı ortamda bellek kullanımı, çağrı frekansı ve hata logları için telemetri ekleyin. Hatalı veya saldırıya açık yüklerin fark edilmesi hızlı müdahale sağlar.

Sonuç olarak, Rust ile Wasm güçlü ve güvenli uygulamalar yazmanıza olanak tanır fakat başarılı olmak için arayüz maliyetlerini, bellek yönetimini ve runtime politikalarını bilinçli ele almak gerekir. Küçük optimizasyonlar bile büyük performans ve boyut kazanımları sağlayabilir; güvenlik ise tasarım aşamasında düşünülmelidir.