Bài viết Câu hỏi About RongvangIT
profile Pic
0
0

Đăng ngày:

  48 Lượt xem

Quá khứ, hiện tại và tương lai của WebAssembly

JavaScriptWebAssemblyGo

Giới thiệu

Trong WebAssembly (viết tắt là Wasm), có nhiều đặc tả như WASI, WIT, Component Model, và nhiều đặc tả khác. Bằng cách hiểu về lịch sử và động lực của mỗi đặc tả này, chúng ta có thể nắm bắt tổng quan về WebAssembly theo thời gian từ quá khứ đến hiện tại và tương lai. Bài viết này sẽ sắp xếp theo dạng thời gian.

Trước tiên, sau khi đưa ra một giới thiệu ngắn gọn về Wasm và các đặc điểm của nó, chúng ta sẽ tìm hiểu về quá khứ của Wasm, bao gồm nguồn gốc và động lực của nó. Tiếp theo, chúng ta sẽ tìm hiểu về sự chú ý đặc biệt đối với Wasm hiện tại, cũng như về các đặc tả đang được xây dựng và mục tiêu trong tương lai.

WebAssembly là gì

web-assembly-logo

WebAssembly là một đặc tả về định dạng lệnh nhị phân cho máy ảo dựa trên ngăn xếp. Viết tắt là Wasm. Tệp Wasm (hoặc mô-đun Wasm) thường được biểu diễn bằng phần mở rộng .wasm và được thực thi bởi máy ảo ngăn xếp được gọi là Wasm runtime.

Wasm được chuẩn hóa bởi W3C. Nó có những đặc điểm tiêu biểu sau:

  • Language-independent (Không phụ thuộc vào ngôn ngữ)
  • Portable/Platform-independent (Dễ di động/Không phụ thuộc vào nền tảng)
  • Safe (An toàn)
  • Fast (Nhanh)

Không phụ thuộc vào ngôn ngữ

Wasm có đặc điểm “Language-Independent” (Không phụ thuộc vào ngôn ngữ). Điều này có nghĩa là nó có thể được biên dịch từ nhiều ngôn ngữ lập trình khác nhau như Rust, Go, C/C++, Zig thành mô-đun Wasm (tệp có phần mở rộng .wasm). Đặc biệt, LLVM, nền tảng biên dịch được sử dụng trong nhiều ngôn ngữ, hỗ trợ Wasm, mở rộng phạm vi của ngôn ngữ có thể biên dịch thành Wasm.

Language-Independent

Dễ di động/Không phụ thuộc vào nền tảng

Một đặc điểm quan trọng khác của Wasm là tính “Portable” (Dễ di động) và “Platform-independent” (Không phụ thuộc vào nền tảng). Mô-đun Wasm không phụ thuộc vào một nền tảng cụ thể nào. Chúng có thể chạy trên máy chủ sử dụng Wasm runtime như Wasmtime hoặc trình duyệt sử dụng Wasm runtime được triển khai trong trình duyệt như V8 Engine của Google Chrome. Hơn nữa, Wasm không phụ thuộc vào hệ điều hành hoặc kiến trúc CPU, điều này đồng nghĩa với việc nó có thể chạy trên các môi trường khác nhau về hệ điều hành (Windows, Mac, Linux) và kiến trúc CPU (x86-64, ARM) mà không yêu cầu sự chú ý từ ứng dụng Wasm.

Portable/Platform-independent

An toàn

Mô-đun Wasm chạy trong một môi trường hộp cát, mang lại tính an toàn. Môi trường hộp cát này bao gồm các ràng buộc sau:

  • Chỉ có thể thực hiện các hàm máy chủ đã cung cấp
  • Chỉ có thể truy cập vào bộ nhớ được cấp phát

Chỉ có thể thực hiện các hàm máy chủ đã cung cấp

Các hàm máy chủ (Host functions) [1] là những thứ được chuyển từ Wasm runtime vào mô-đun Wasm. Mô-đun Wasm phải rõ ràng khai báo những hàm máy chủ mà nó sẽ sử dụng thông qua import. Điều này giúp đảm bảo rằng mô-đun Wasm không thể sử dụng những hàm máy chủ nguy hiểm hoặc yêu cầu những hàm máy chủ quá mức.

Ví dụ, nếu Wasm runtime chỉ cung cấp hàm getrandom cho mô-đun Wasm, mô-đun này chỉ có thể sử dụng getrandom và không thể thực hiện các hàm khác như open hoặc write.

WebAssembly

Chỉ có thể truy cập vào bộ nhớ được cấp phát

Mô-đun Wasm không thể truy cập toàn bộ bộ nhớ của quy trình mà nó đang chạy, mà chỉ có

thể thao tác trong khu vực bộ nhớ được cấp phát cho nó. Điều này đảm bảo rằng, ngay cả khi có thông tin bí mật trong các phần khác của bộ nhớ, mô-đun Wasm không thể truy cập vào chúng, giữ cho tính an toàn của ứng dụng.
WebAssembly

Nhanh

Wasm đặt mục tiêu là đạt được tốc độ gần như bằng mã máy, vượt xa JavaScript trong trình duyệt. Nó cũng có thể chạy nhanh hơn so với các ứng dụng chạy bên ngoài trình duyệt khi so sánh với container, chủ yếu là do Wasm chỉ cần runtime Wasm để hoạt động và kích thước mô-đun Wasm thường nhỏ hơn hình ảnh container thông thường. Điều này giúp giảm thời gian tải và khởi động, và Wasm có thể khởi động mà không cần đợi cho tất cả các tệp tin được tải.

Sự khác biệt so với JVM

Wasm thường được so sánh với JVM (Java Virtual Machine). Điểm tương đồng giữa chúng là “Write once, run anywhere” (Viết một lần, chạy ở mọi nơi). Tuy nhiên, Wasm khác biệt ở chỗ nó hỗ trợ nhiều ngôn ngữ, không bị chiếm đóng bởi một doanh nghiệp duy nhất, là một môi trường hộp cát, có tốc độ khởi động nhanh, kích thước bộ nhớ nhỏ, và đặc tả ngôn ngữ nhỏ.

Thực hành tạo mô-đun Wasm

Dưới đây là một ví dụ về việc tạo một mô-đun Wasm đơn giản. Vì Go từ phiên bản 1.21 trở đi hỗ trợ WASI, chúng ta có thể tạo một mô-đun Wasm chạy trên Wasm runtime như Wasmtime bằng Go.

Dưới đây là một chương trình Go đơn giản in ra chuỗi “Hello World”:

package main

import "fmt"

func main() {
    fmt.Println("Hello World")
}

Khi biên dịch mô-đun Wasm bằng Go, ta sẽ cài đặt biến môi trường GOOS=wasip1. Điều này đại diện cho gói WASI phiên bản 1. GOARCH sẽ là wasm.

Sau khi biên dịch mô-đun Wasm, nó có thể được thực thi bằng cách sử dụng Wasm runtime như wasmtime hoặc wasmer. Dưới đây là ví dụ về các lệnh biên dịch và thực thi:

# Biên dịch và xuất hello.wasm
$ GOOS=wasip1 \
  GOARCH=wasm \
  go build -o hello.wasm \
  main.go

# Thực thi hello.wasm bằng wasmtime (Wasm runtime)
$ wasmtime hello.wasm
Hello World

# hello.wasm là một tệp nhị phân
$ xxd hello.wasm | head
00000000: 0061 736d 0100 0000 00f2 8080 8000 0a67  .asm...........g
00000010: 6f3a 6275 696c 6469 64ff 2047 6f20 6275  o:buildid. Go bu
00000020: 696c 6420 4944 3a20 2243 4a48 3844 6c4c  ild ID: "CJH8DlL
00000030: 3061 4f64 5578 3033 7679 7647 482f 4e36  0aOdUx03vyvGH/N6
00000040: 3732 4f46 7853 654c 7465 534a 5274 4945  72OFxSeLteSJRtIE
00000050: 7464 2f73 4c4b 7730 6b7a 544f 4b67 534c  td/sLKw0kzTOKgSL
00000060: 4239 6768 6849 472f 5279 6644 4c44 5672  yA-p16OP2UlP". .
00000070: 7941 2d70 3136 4f50 3255 6c50 220a 20ff  yA-p16OP2UlP". .
00000080: 01d0 8080 8000 0e60 017f 017f 6000 017f  .......`....`...
00000090: 6001 7f00 6002 7f7f 017f 6003 7f7e 7f01  `...`.....`..~..

Quá khứ của Wasm

Wasm đã ra đời như một kết quả của nhu cầu tạo ra môi trường thực thi nhanh hơn trên trình duyệt so với JavaScript.

Năm 2008, trình biên dịch JIT của JavaScript đã được phát triển, đánh dấu sự bắt đầu của lịch sử tăng tốc môi trường thực thi trên trình duyệt. Tuy nhiên, JavaScript là một ngôn ngữ động, và rõ ràng đã có giới hạn trong việc tăng tốc.

Do đó, có hai cố gắng khác nhau để phát triển môi trường thực thi nhanh hơn trên trình duyệt. Một là dự án NaCl (Native Client) do Google dẫn đầu, và hai là sự kết hợp của Emscripten và asm.js.

NaCl

NaCl nhằm mục đích thực thi mã nguồn native dưới một môi trường cách ly, mang lại tốc độ và an toàn. Tuy nhiên, dự án này đã đối mặt với hai vấn đề. Thứ nhất, nó phụ thuộc vào API plugin được xem là lỗi thời, và kết quả là không được cộng đồng chấp nhận tốt. Thứ hai, vấn đề về tính di động, cần mã máy khác nhau cho các kiến trúc CPU như x86 hoặc ARM.

Emscripten + asm.js

Cùng với NaCl, vào thời điểm đó, Alon Zakai của Mozilla đã khởi đầu dự án Emscripten. Emscripten, ban đầu được bắt đầu như một dự án cá nhân của Alon Zakai, sau đó trở thành một dự án của Mozilla. Emscripten là một công cụ biên dịch mã nguồn C++ thành mã nguồn JavaScript.

asm.js là một phụ thuộc của JavaScript, cho phép tối ưu hóa thông qua việc ép kiểu. Tuy nhiên, asm.js cũng đối mặt với vấn đề về tính mở rộng và tốc độ phân tích cú pháp chậm do phụ thuộc vào cú pháp JavaScript.

asm.js được biểu diễn như sau:

function add(x, y){
    x = x | 0;         // Thêm `| 0` (hoặc 0) để giữ nguyên giá trị
    y = y | 0;         // Ép kiểu và giữ nguyên dưới dạng số nguyên 32 bit có dấu.
    return x + y | 0;  // Tương tự với giá trị trả về.
}

asm.js sử dụng các chú thích kiểu (| 0) như vậy để giữ nguyên giá trị và ép kiểu chúng thành số nguyên 32 bit có dấu, điều này giúp tối ưu hóa vì kiểu đã được xác định.

Sự hợp tác của Google và Mozilla

Năm 2013, Google và Mozilla bắt đầu hợp tác, và vào năm 2015, họ cùng nhau khởi động dự án WebAssembly. Do đó, Wasm đã tích hợp những điểm mạnh của NaCl và Emscripten + asm.js. Wasm không sử dụng cơ sở trên JavaScript như asm.js, nhưng lại sử dụng mã nhị phân giống NaCl. Nó cũng tích hợp những điểm mạnh của asm.js như việc hoạt động trong cùng một quá trình với DOM và khả năng gọi trực tiếp Web API thông qua JavaScript.

Các ứng dụng WebAssembly trong quá khứ

Wasm ra đời để tăng tốc trình duyệt. Vào thời điểm đó, Wasm được sử dụng chủ yếu trong trình duyệt. Một số ứng dụng tiêu biểu bao gồm các game engine như Unity và Google Earth. Những ứng dụng này đã tận dụng hiệu suất nhanh của Wasm để mang lại trải nghiệm trình duyệt phong phú hơn.

Wasm hiện tại

Hiện nay, Wasm đang thu hút sự chú ý khi được sử dụng ngoài trình duyệt. Hãy xem xét quá trình này.

Sự xuất hiện của WASI (WebAssembly System Interface)

wasi

Năm 2019, WebAssembly System Interface (WASI) đã được công bố. WASI chuẩn hóa giao diện để Wasm có thể tương tác với hệ thống, và hiện tại, phiên bản xem trước 1 của nó đang được rộng rãi sử dụng.

Nguồn gốc của WASI

WASI được phát triển do sự xuất hiện của Wasm bắt đầu được sử dụng ngoài trình duyệt. Cụ thể, các tổ chức như Fastly [2] và Node.js đã bắt đầu sử dụng Wasm ngoài trình duyệt, tạo nhu cầu để tương tác với hệ thống ngoài trình duyệt, và việc chuẩn hóa giao diện hệ thống đã được triển khai.

Một số ví dụ cụ thể của WASI bao gồm fd_write (ghi vào FileDescriptor), random_get (lấy giá trị ngẫu nhiên vào bộ đệm), environ_get (lấy biến môi trường). Để biết thêm chi tiết, hãy tham khảo WASI Specification của WebAssembly/WASI.

Tính di động của WASI

WASI cho phép Wasm tương tác với hệ thống mà không làm mất tính di động của nó. WASI hoạt động như một trừu tượng hóa các cuộc gọi hệ thống. Các mô-đun Wasm có thể gọi WASI và các runtime Wasm sẽ xử lý sự khác biệt giữa các hệ điều hành.

wasi-port

An toàn thông qua WASI

Giống như đặc điểm của hộp cát của Wasm mà chúng ta đã trình bày trước đó, mô-đun Wasm phải rõ ràng nhập các phụ thuộc mà nó sử dụng. Đối với các hàm WASI cũng giống như vậy, nếu chúng không được nhập khẩu, chúng sẽ không thể sử dụng. Do đó, tính an toàn của hộp cát Wasm có thể được áp dụng trực tiếp cho WASI.

Sự Thay Đổi Trong Việc Sử Dụng Wasm

Với sự giới thiệu của WASI, việc sử dụng Wasm đã mở rộng ra khỏi trình duyệt. Người sáng lập Docker đã nói rằng nếu Wasm và WASI đã tồn tại vào năm 2008, thì việc tạo ra Docker có lẽ không cần thiết.

Cụ thể, như là môi trường thực thi Wasm, Azure hỗ trợ thực thi Wasm thông qua Azure Kubernetes Service, Fastly hỗ trợ thực thi Wasm trong môi trường Edge Computing, và có cả nền tảng PaaS như Fermyon chạy Wasm.

Ngoài ra, có các ví dụ sử dụng Wasm như là hệ thống plugin, ví dụ như Envoy có hỗ trợ, và kube-scheduler đang xem xét sử dụng.

Đối với chi tiết hơn, bạn có thể tham khảo Wasm như một Plugin Execution Engine.

Tương Lai của Wasm

Wasm có thể mang lại sự cách mạng cho hệ sinh thái phát triển phần mềm trong tương lai. Một trong những điểm đáng chú ý là đặc tả đang được phát triển hiện tại, được gọi là “Component Model”.

Component Model

Component Model là một đặc tả bổ sung để hỗ trợ tương tác giữa các module Wasm. Nó bao gồm hai thành phần chính: WIT (WebAssembly Interface Type) và Canonical ABI, là biểu diễn nhị phân của WIT.

Nguyên Nhân của Component Model

Component Model được phát triển để nâng cao khả năng tái sử dụng của các module Wasm. Hiện tại, đặc tả cơ bản của Wasm chỉ có một số ít loại kiểu dữ liệu như số nguyên 32-bit, số nguyên 64-bit, số thực 32-bit, số thực 64-bit, và vector 128-bit dành cho SIMD. Điều này làm cho việc truyền những kiểu dữ liệu phức tạp như chuỗi hay cấu trúc giữa các module trở nên khó khăn. WIT (WebAssembly Interface Type) được phát triển để giải quyết vấn đề này.

WIT (WebAssembly Interface Type)

WIT là một ngôn ngữ mô tả giao diện (IDL - Interface Definition Language) cho phép mô tả rõ ràng các thành phần mà một module Wasm nhập và xuất. Bạn có thể tưởng tượng WIT giống như Protocol Buffer. Điều này giúp sử dụng các kiểu dữ liệu phức tạp như chuỗi, cấu trúc, danh sách, ngoài các kiểu cơ bản của Wasm.

Ví dụ, trong đoạn mã WIT dưới đây, my-world là một component mà module khác có thể nhập và sử dụng. Nó cung cấp một hàm log (nhận một chuỗi làm tham số) để bên ngoài có thể sử dụng, và nó xuất một hàm run mà bên ngoài có thể gọi.

package local:demo

world my-world {
  import log: func(message: string)

  export run: func()
}

Kết Hợp Các Component

Do mỗi component đều xác định nhập và xuất thông qua WIT, nên để kết hợp các component, chúng ta chỉ cần đảm bảo rằng các yêu cầu nhập của một component được đáp ứng bởi các component khác.

Trong ví dụ dưới đây, component app đang import các hàm addlog. Để đáp ứng nhu cầu này, chúng ta cần cung cấp cho nó hai component khác là calc (xuất hàm add) và logger (xuất hàm log). Như vậy, app có thể thỏa mãn yêu cầu của mình.

compose

Component Model và Bytecode Alliance

Component Model đang cố gắng giải quyết vấn đề của Bytecode Alliance, một tổ chức thành lập vào năm 2019 bởi Mozilla, Fastly, Intel và Red Hat. Bytecode Alliance tập trung vào việc thúc đẩy và triển khai tiêu chuẩn WebAssembly và WASI, đặt mục tiêu tạo ra tương lai của WebAssembly ngoài trình duyệt.

Những Thách Thức Theo Đánh Giá Của Bytecode Alliance

Byte

code Alliance chỉ trích việc 80% phần mềm hiện tại được cấu thành từ mã nguồn mở và module được phát triển bởi người khác, tăng nguy cơ an ninh. Hiện nay, quyền truy cập được ủy quyền cho phần mềm giống như là cho các thư viện mà nó phụ thuộc. Bytecode Alliance tin rằng điều này tạo ra rủi ro bảo mật khi thư viện có thể chứa mã độc hại hoặc lỗ hổng bảo mật.

Component Model Giải Quyết Vấn Đề

Component Model giúp tăng cường tương tác giữa các module Wasm, từ đó giảm thiểu vấn đề về bảo mật. Điều này là do không gian bộ nhớ của mỗi module Wasm được cô lập, ngăn chặn sự truy cập không hợp pháp từ các module khác. Nó cũng giúp giải quyết vấn đề liên quan đến việc sử dụng các thư viện từ các ngôn ngữ lập trình khác nhau, mở rộng tiềm năng của WebAssembly.

bytecode2

Điều này không chỉ giúp giảm rủi ro an ninh mà còn giải quyết vấn đề phân tách ngôn ngữ lập trình. Với Component Model, có khả năng kết hợp các module Wasm được tạo bằng các ngôn ngữ lập trình khác nhau, ví dụ như sử dụng một module được tạo bằng Go trong một ứng dụng được phát triển bằng C++ hoặc Rust.

Tổng Kết

Bài viết trình bày tổng quan về WebAssembly (Wasm), giải thích lý do nó ra đời, và lý do nó đang thu hút sự chú ý. Sự đa ngôn ngữ, độc lập với nền tảng, an toàn và hiệu suất cao là những đặc tính đặc biệt của Wasm, tạo ra một hệ sinh thái công nghệ độc đáo.

Đặc biệt, việc giới thiệu WASI mở ra khả năng sử dụng Wasm ngoài trình duyệt, mở rộng ứng dụng của nó từ web sang các lĩnh vực khác. Các mô hình như Component Model đang được đề xuất để giải quyết các thách thức về tương tác giữa các module Wasm, cũng như tăng cường sự an toàn và tính tương thích giữa các ngôn ngữ lập trình.

Hy vọng rằng sự phát triển của Wasm sẽ tiếp tục mang lại những cơ hội mới và thay đổi cách chúng ta phát triển phần mềm trong tương lai.

dev_pro_it
Đang làm IT tại Japan

Bình luận

Bài viết chưa có bình luận. Hãy trở thành người bình luận đầu tiên!
Sign up for free and join this conversation.
Sign Up
If you already have a RongvangIT account Login
Danh sách thư mục
Bắt đầu ngay với RồngVàngIT - nền tảng chia sẻ kiến thức lập trình tuyệt vời cho kỹ sư Việt Nam!

Hãy đăng nhập để sử dụng hàng loạt các chức năng tuyệt vời của RồngVàngIT !

  1. 1. Bạn sẽ nhận được các bài viết phù hợp bằng chức năng theo dõi tag và người dùng.
  2. 2. Bạn có thể đọc lại các thông tin hữu ích bằng chức năng lưu trữ nội dung.
  3. 3. Chia sẻ kiến thức, đặt câu hỏi và ghi lại quá trình trưởng thành của mình cùng RồngVàngIT !
Tạo tài khoản Đăng nhập
profile Pic