Node.js va WebAssembly


ULASHISH

WebAssembly nima?

WebAssembly (Wasm) C, C++ va Rust kabi yuqori darajali tillar uchun ko‘chma kompilyatsiya maqsadi sifatida yaratilgan binar instruksiyalar formatidir.

WebAssembly ning asosiy xususiyatlari quyidagilardan iborat:

  • Ikkilik format - JavaScript-dan tezroq yuklanadigan va bajariladigan ixcham o‘lcham
  • Yaqin-mahalliy ishlash - mahalliy mashina kodiga yaqin tezlikda ishlaydi
  • Platformadan mustaqil - Brauzerlar, Node.js va boshqa muhitlarda ishlaydi
  • Xavfsizlik - Kuchli xavfsizlik modeliga ega sinov muhitida ishlaydi

JavaScript-dan farqli o‘laroq, WebAssembly qo‘lda yozish uchun mo‘ljallanmagan past darajadagi ikkilik formatdir.

Buning o‘rniga siz boshqa tillardan kodni WebAssemblyga kompilyatsiya qilasiz.


Node.js da WebAssembly yordami

Node.js global WebAssembly obyekti orqali WebAssembly’ni o‘rnatilgan holda qo‘llab-quvvatlaydi (xuddi brauzerlardagidek).

Node.js versiyangiz WebAssembly-ni qo‘llab-quvvatlaydimi yoki yo‘qligini tekshirish uchun:

Misol: WebAssembly Support-ni tekshiring

console.log(typeof WebAssembly === 'object');
console.log(WebAssembly);

Eslatma: WebAssembly qo‘llab-quvvatlashi birinchi marta Node.js v8.0.0 da qo‘shilgan va keyingi versiyalarda yaxshilandi.



Node.js da WebAssembly dan foydalanish

Node.js-dagi WebAssembly API WebAssembly modullari bilan ishlashning bir necha usullarini taqdim etadi:

Metod Tavsif
WebAssembly.compile() WebAssembly ikkilik kodini WebAssembly moduliga kompilyatsiya qiladi
WebAssembly.instantiate() WebAssembly kodini kompilyatsiya qiladi va joriy qiladi
WebAssembly.validate() WebAssembly ikkilik formatini tasdiqlaydi
WebAssembly.Module Kompilyatsiya qilingan WebAssembly modulini ifodalaydi
WebAssembly.Instance Taqdim etilgan WebAssembly modulini ifodalaydi
WebAssembly.Memory WebAssembly xotirasini ifodalaydi

Quyida WebAssembly modulini yuklash va ishga tushirishning asosiy misoli keltirilgan:

Misol: Node.js da WebAssemblyni ishga tushirish

const fs = require('fs');

// Read the WebAssembly binary file
const wasmBuffer = fs.readFileSync('./simple.wasm');

// Compile and instantiate the module
WebAssembly.instantiate(wasmBuffer).then(result => {
  const instance = result.instance;
  
  // Call the exported 'add' function
  const sum = instance.exports.add(2, 3);
  console.log('2 + 3 =', sum); // Output: 2 + 3 = 5
});

Eslatma: Ushbu misoldagi simple.wasm fayli add funksiyasini eksport qiluvchi kompilyatsiya qilingan WebAssembly moduli bo‘ladi.

Siz buni odatda C, C++ yoki Rust kodini kompilyatsiya qilish orqali yaratasiz.


Turli tillar bilan ishlash

Node.js da foydalanish uchun WebAssembly ga turli tillarni kompilyatsiya qilishingiz mumkin:

Emscripten bilan C/C++

Emscripten - bu WebAssembly-ni chiqaradigan C/C++ uchun kompilyator asboblar zanjiri.

Misol C kodi (add.c):

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
  return a + b;
}

WebAssembly-ga kompilyatsiya qiling:

emcc add.c -s WASM=1 -s EXPORTED_FUNCTIONS='["_add"]' -o add.js

Wasm-pack bilan zang

wasm-pack Rust tomonidan yaratilgan WebAssembly yaratish vositasidir.

Rust kodiga misol (src/lib.rs):

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
   a + b
}

Wasm-pack bilan yarating:

wasm-pack build --target nodejs

Kengaytirilgan WebAssembly foydalanish

1. Murakkab ma’lumotlar tuzilmalari bilan ishlash

JavaScript va WebAssembly o‘rtasida murakkab ma’lumotlarni uzatish xotirani ehtiyotkorlik bilan boshqarishni talab qiladi:

Misol: Massivlarni WebAssembly ga o‘tkazish

// JavaScript code
const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
  env: {
    memory: new WebAssembly.Memory({ initial: 1 })
  }
});
// Allocate memory for an array of 10 integers (4 bytes each)
const arraySize = 10;
const ptr = wasmModule.exports.alloc(arraySize * 4);
const intArray = new Int32Array(wasmModule.exports.memory.buffer, ptr, arraySize);
// Fill array with values
for (let i = 0; i < arraySize; i++) {
  intArray[i] = i * 2;
}
// Call WebAssembly function to process the array
const sum = wasmModule.exports.processArray(ptr, arraySize);
console.log('Sum of array:', sum);
// Don't forget to free the memory
wasmModule.exports.dealloc(ptr, arraySize * 4);

Tegishli C kodi (WebAssemblyga tuzilgan):

#include <stdlib.h>

int* alloc(int size) {
  return (int*)malloc(size);
}

void dealloc(int* ptr, int size) {
  free(ptr);
}

int processArray(int* array, int length) {
  int sum = 0;
  for (int i = 0; i < length; i++) {
    sum += array[i];
  }
  return sum;
}

2. WebAssembly bilan ko‘p qirrali

WebAssembly Web Workers va SharedArrayBuffer orqali ko‘p ish zarralarini qo‘llab-quvvatlaydi:

Misol: WebAssembly bilan parallel ishlov berish

// main.js
const workerCode = `
  const wasmModule = await WebAssembly.instantiate(wasmBuffer, {
    env: { memory: new WebAssembly.Memory({ initial: 1, shared: true }) }
  });

  self.onmessage = (e) => {
    const { data, start, end } = e.data;
    const result = wasmModule.exports.processChunk(data, start, end);
    self.postMessage({ result });
  };
`;

// Create worker pool
const workerCount = navigator.hardwareConcurrency || 4;
const workers = Array(workerCount).fill().map(() => {
  const blob = new Blob([workerCode], { type: 'application/javascript' });
  return new Worker(URL.createObjectURL(blob));
});

// Process data in parallel
async function processInParallel(data, chunkSize) {
  const results = [];
  let completed = 0;

  return new Promise((resolve) => {
    workers.forEach((worker, i) => {
      const start = i * chunkSize;
      const end = Math.min(start + chunkSize, data.length);

      worker.onmessage = (e) => {
        results[i] = e.data.result;
        completed++;

        if (completed === workerCount) {
          resolve(results);
        }
      };

      worker.postMessage({ data, start, end });
    });
  });
}

3. WebAssembly diskini tuzatish

WebAssembly diskini tuzatish qiyin bo‘lishi mumkin, ammo zamonaviy vositalar yordam berishi mumkin:

Emscripten bilan manba xaritalaridan foydalanish

# Compile with debugging information and source maps
emcc -g4 --source-map-base http://localhost:8080/ -s WASM=1 -s EXPORTED_FUNCTIONS='["_main","_my_function"]' -o output.html source.c

Chrome DevTools-da debug

  1. Open Chrome DevTools (F12)
  2. "Manbalar" yorlig‘iga o‘ting
  3. Fayl daraxtida WebAssembly faylingizni toping
  4. To‘xtash nuqtalarini o‘rnating va JavaScript-dagi kabi o‘zgaruvchilarni tekshiring

Haqiqiy dunyo WebAssembly misollari

1. WebAssembly yordamida tasvirni qayta ishlash

WebAssembly tasvirni qayta ishlash kabi protsessor talab qiladigan vazifalarni bajarishda ustunlik qiladi:

// JavaScript wrapper for WebAssembly image processing
async function applyFilter(imageData, filterType) {
  const { instance } = await WebAssembly.instantiate(wasmBuffer, {
    env: { memory: new WebAssembly.Memory({ initial: 1 }) }
  });

  const { width, height, data } = imageData;

  // Allocate memory for image data
  const imageDataSize = width * height * 4; // RGBA
  const imageDataPtr = instance.exports.alloc(imageDataSize);

  // Copy image data to WebAssembly memory
  const wasmMemory = new Uint8Array(instance.exports.memory.buffer);
  wasmMemory.set(new Uint8Array(data.buffer), imageDataPtr);

  // Apply filter
  instance.exports.applyFilter(imageDataPtr, width, height, filterType);

  // Copy result back to ImageData
  const resultData = new Uint8ClampedArray(
    wasmMemory.slice(imageDataPtr, imageDataPtr + imageDataSize)
  );

  // Free allocated memory
  instance.exports.dealloc(imageDataPtr, imageDataSize);

  return new ImageData(resultData, width, height);
}

2. Kriptografiya

WebAssembly bilan yuqori samarali kriptografik operatsiyalar:

// Example: Using the Web Crypto API with WebAssembly
async function encryptData(data, keyMaterial) {
  // Import WebAssembly crypto module
  const { instance } = await WebAssembly.instantiateStreaming(
    fetch('crypto.wasm'),
    { env: { memory: new WebAssembly.Memory({ initial: 1 }) } }
  );

  // Generate IV (Initialization Vector)
  const iv = window.crypto.getRandomValues(new Uint8Array(12));

  // Prepare data
  const dataBytes = new TextEncoder().encode(JSON.stringify(data));
  const dataPtr = instance.exports.alloc(dataBytes.length);
  new Uint8Array(instance.exports.memory.buffer, dataPtr, dataBytes.length)
    .set(dataBytes);

  // Encrypt data using WebAssembly
  const encryptedDataPtr = instance.exports.encrypt(dataPtr, dataBytes.length);

  // Get encrypted data from WebAssembly memory
  const encryptedData = new Uint8Array(
    instance.exports.memory.buffer,
    encryptedDataPtr,
    dataBytes.length // In real usage, you'd track the actual encrypted size
  );

  // Clean up
  instance.exports.dealloc(dataPtr, dataBytes.length);

  return {
    iv: Array.from(iv),
    encryptedData: Array.from(encryptedData)
  };
}

Resurslar va keyingi qadamlar

Node.js-dagi WebAssembly bir nechta afzalliklarni taqdim etadi:

  • Umumiylik - Intensiv hisoblash vazifalari uchun deyarli mahalliy ijro tezligi
  • Til tanlash - Node.js ilovalarida C, C++, Rust, Go va boshqalar kabi tillardan foydalaning.
  • Kodni qayta ishlatish - Boshqa tillardagi mavjud kutubxonalar va kod bazalarini qayta ishlatish
  • Izomorf kod - Brauzer va server o‘rtasida WebAssembly modullarini almashish

Umumiy foydalanish holatlariga quyidagilar kiradi:

  • Rasm va videoga ishlov berish
  • Haqiqiy vaqtda audio ishlov berish
  • Kriptografiya va shifrlash
  • Ilmiy hisoblash va simulyatsiyalar
  • O‘yinni rivojlantirish
  • Mashinani o‘rganish algoritmlari

Samaradorlikni taqqoslash

Ishlash afzalliklarini namoyish qilish uchun keling, Fibonachchi rekursiv funksiyasining JavaScript va WebAssembly ilovalarini solishtiramiz:

JavaScript-ni amalga oshirish:

// Recursive Fibonacci in JavaScript (inefficient for demonstration)
function fibonacciJS(n) {
  if (n <= 1) return n;
  return fibonacciJS(n - 1) + fibonacciJS(n - 2);
}

C Amalga oshirish (WebAssemblyga kompilyatsiya qilinadi):

#include <emscripten.h>

// WebAssembly-optimized Fibonacci function
EMSCRIPTEN_KEEPALIVE
int fibonacci_wasm(int n) {
  if (n <= 1) return n;
  
  int a = 0, b = 1, temp;
  for (int i = 2; i <= n; i++) {
    temp = a + b;
    a = b;
    b = temp;
  }
  
  return b;
}
    b = temp;
  }
  
  return b;
}

Samaradorlikni taqqoslash kodi:

const fs = require('fs');
const path = require('path');

// Read the WebAssembly binary file
const wasmBuffer = fs.readFileSync('./fibonacci.wasm');

// JavaScript implementation for comparison
function fibonacciJS(n) {
  if (n <= 1) return n;
  return fibonacciJS(n - 1) + fibonacciJS(n - 2);
}

// Compile and instantiate the WebAssembly module
WebAssembly.instantiate(wasmBuffer).then(result => {
  const { fibonacci_wasm } = result.instance.exports;
  
  // Test with a value that's computationally expensive
  const n = 40;
  
  // Measure WebAssembly performance
  const wasmStart = performance.now();
  const wasmResult = fibonacci_wasm(n);
  const wasmEnd = performance.now();
  
  // Measure JavaScript performance
  const jsStart = performance.now();
  const jsResult = fibonacciJS(n);
  const jsEnd = performance.now();
  
  console.log(`Fibonacci(${n})`);
  console.log(`WebAssembly: ${wasmResult} (${(wasmEnd - wasmStart).toFixed(2)} ms)`);
  console.log(`JavaScript: ${jsResult} (${(jsEnd - jsStart).toFixed(2)} ms)`);
});

WebAssembly versiyasi rekursiv yondashuvdan ancha tezroq bo‘lgan iterativ algoritmdan foydalanadi.

Hatto bir xil algoritmlarga ega bo‘lsa ham, WebAssembly o‘zining kompilyatsiya qilingan tabiati tufayli odatda protsessor talab qiladigan operatsiyalar uchun yaxshiroq ishlaydi.

Haqiqiy dunyo ilovalari

Node.js bilan WebAssembly ishlatadigan ba’zi mashhur kutubxonalar:

Kutubxona Maqsad Tillar
O‘tkir Yuqori samarali tasvirni qayta ishlash C++
ffmpeg.wasm Video va audio qayta ishlash C
sql.js JavaScript uchun SQLite C
zxing-wasm Shtrix-kodni skanerlash C++
TensorFlow.js Mashinani o‘rganish C++

Xotira boshqaruvi

WebAssembly modullari chiziqli xotirada ishlaydi, bu ham WebAssembly, ham JavaScript-dan foydalanish mumkin bo‘lgan ulashgan, o‘zgaruvchan baytlar massividir.

WebAssembly xotirasini tushunish

WebAssembly xotirasi sahifalarga bo‘lingan, har bir sahifa 64KB (65 536 bayt).

Xotira JavaScript yoki WebAssembly modulining o‘zi tomonidan yaratilishi mumkin.

  • boshlang‘ich: sahifalarning dastlabki soni (minimal o‘lcham)
  • maksimal: Xotira o‘sishi mumkin bo‘lgan ixtiyoriy maksimal sahifalar soni
  • birgalikda: Xotirani ishchilar o‘rtasida bo‘lishish mumkinmi (ko‘p stream uchun)

WebAssembly xotirasini yaratish va unga kirish

// Create a new WebAssembly Memory instance with 1 page (64KB) initially,
// and a maximum of 10 pages (640KB)
const memory = new WebAssembly.Memory({
  initial: 1,
  maximum: 10
});

// Access the memory as a typed array in JavaScript
let bytes = new Uint8Array(memory.buffer);

// Write data to memory
for (let i = 0; i < 10; i++) {
  bytes[i] = i * 10; // Write values 0, 10, 20, ..., 90
}

// Read data from memory
console.log('Memory contents:', bytes.slice(0, 10));

// Grow the memory by 1 page (returns the previous size in pages)
const previousPages = memory.grow(1);
console.log(`Memory grown from ${previousPages} to ${memory.buffer.byteLength / 65536} pages`);

// IMPORTANT: After growing memory, we need to create a new view
// because the ArrayBuffer is detached when memory grows
bytes = new Uint8Array(memory.buffer);
console.log('Memory size now:', bytes.length, 'bytes');

Ogohlantirish: WebAssembly xotirasi kattalashganda, asosiy ArrayBuffer ajratiladi va yangisi yaratiladi.

Bu shuni anglatadiki, xotiraning har qanday JavaScript TypedArray ko‘rinishlari xotira o‘sishidan keyin qayta yaratilishi kerak.

Turli TypedArray ko‘rinishlaridan foydalanish

Ma’lumotlarni turli yo‘llar bilan izohlash uchun bir xil xotiraning turli ko‘rinishlarini yaratishingiz mumkin:

Turli xil ma’lumotlar turlari bilan ishlash

const memory = new WebAssembly.Memory({ initial: 1 });

// Different views of the same memory
const bytes = new Uint8Array(memory.buffer); // Unsigned 8-bit integers
const ints = new Int32Array(memory.buffer); // Signed 32-bit integers
const floats = new Float32Array(memory.buffer); // 32-bit floating point

// Write an integer at the beginning of memory
ints[0] = 42;

// The same memory location viewed as bytes
console.log('42 as bytes:', Array.from(bytes.slice(0, 4)));

// Write a float
floats[1] = 3.14159;

// View the float as bytes and as an integer
const floatByteOffset = 1 * Float32Array.BYTES_PER_ELEMENT;
const floatIntValue = ints[floatByteOffset / Int32Array.BYTES_PER_ELEMENT];
console.log('3.14159 as bytes:', Array.from(bytes.slice(floatByteOffset, floatByteOffset + 4)));
console.log('3.14159 as int32:', floatIntValue);

Rasmga ishlov berish misoli

Rasmni qayta ishlash uchun WebAssembly xotirasidan foydalanishning amaliy misoli:

Kulrang rangga aylantirish uchun WebAssembly C kodi

#include <emscripten.h>
#include <stdint.h>

// WebAssembly optimized grayscale conversion
EMSCRIPTEN_KEEPALIVE
void grayscale_wasm(uint8_t* pixels, int length) {
  // Process each pixel (RGBA format)
  for (int i = 0; i < length; i += 4) {
    // Calculate grayscale value using luminance formula
    uint8_t gray = (uint8_t)(
      (0.299 * pixels[i]) +     // Red
      (0.587 * pixels[i + 1]) + // Green
      (0.114 * pixels[i + 2])   // Blue
    );
    
    // Set RGB channels to gray value
    pixels[i] = gray;     // Red
    pixels[i + 1] = gray; // Green
    pixels[i + 2] = gray; // Blue
    // Alpha channel (pixels[i + 3]) remains unchanged
  }
}

WebAssembly modulidan foydalanish uchun Node.js kodi

const fs = require('fs');
const wasmBuffer = fs.readFileSync('./image_processing.wasm');

// Sample image data (RGBA format, 2x2 pixel image)
const imageData = new Uint8Array([
  255, 0, 0, 255,    // Red pixel
  0, 255, 0, 255,    // Green pixel
  0, 0, 255, 255,    // Blue pixel
  255, 255, 0, 255   // Yellow pixel
]);

// Instantiate the WebAssembly module
WebAssembly.instantiate(wasmBuffer, {
  env: {
    memory: new WebAssembly.Memory({ initial: 1 })
  }
}).then(result => {
  const instance = result.instance;
  const { grayscale_wasm } = instance.exports;
  const memory = instance.exports.memory;
  
  // Get a view of the WebAssembly memory
  const wasmMemory = new Uint8Array(memory.buffer);
  
  // Copy image data to WebAssembly memory
  wasmMemory.set(imageData);
  
  // Process the image (convert to grayscale)
  grayscale_wasm(0, imageData.length);
  
  // Get processed image data from WebAssembly memory
  const processedData = wasmMemory.slice(0, imageData.length);
  
  console.log('Original image:', imageData);
  console.log('Grayscale image:', processedData);
});
// Write data to memory
bytes[0] = 123;

console.log(bytes[0]); // Output: 123

// Grow the memory by 1 page (to 128KB total)
memory.grow(1);

console.log(`Memory size: ${memory.buffer.byteLength / 1024}KB`);

JavaScript bilan integratsiya

WebAssembly va JavaScript Node.js da muammosiz birga ishlashi mumkin:

Misol: JavaScript va WebAssembly integratsiyasi

const fs = require('fs');
const wasmBuffer = fs.readFileSync('./math.wasm');

// JavaScript function that will use WebAssembly
async function calculateFactorial(n) {
  // Instantiate the module
  const result = await WebAssembly.instantiate(wasmBuffer);
  const wasm = result.instance.exports;
  
  // Use the WebAssembly factorial function
  return wasm.factorial(n);
}

// Use our mixed JS/WebAssembly function
async function main() {
  console.log('Calculating factorials:');
  for (let i = 1; i <= 10; i++) {
    const result = await calculateFactorial(i);
    console.log(`${i}! = ${result}`);
  }
}

main().catch(console.error);

Eng yaxshi amaliyot: Dasturchilarning tajribasini yaxshilash uchun JavaScript-da ilova mantig‘ini saqlangan holda ilovangizning ishlashi uchun muhim bo‘lgan qismlari uchun WebAssembly-dan foydalaning.


Xulosa

WebAssembly Node.js imkoniyatlarini kengaytirib, sizga quyidagilarga imkon beradi:

  • C, C++ va Rust kabi tillardan tuzilgan kodni ishga tushiring
  • Intensiv hisoblash vazifalari uchun mahalliyga yaqin ishlashga erishing
  • Boshqa tillardagi mavjud kod bazalari va kutubxonalaridan qayta foydalaning
  • Brauzer va server muhitlari o‘rtasida kod almashish

Bu Node.js-ni kengroq ko‘lamli ilovalar, ayniqsa yuqori unumdorlikni talab qiluvchi ilovalar uchun yanada ko‘p qirrali platformaga aylantiradi.




W3Schools Pathfinder

Yutuqlaringizni kuzating – bu bepul!