Với sự phát triển và nổi lên của javascript những năm gần đây, các website đã tiến hóa trở thành các web app và ngày càng trở nên phức tạp. Tuy nhiên, dù cho mang lại những lợi ích như: tốc độ phát triển, chạy trên mọi hệ điều hành (chỉ cần có trình duyệt), web app cũng không thể đọ lại native app về mặt hiệu năng. Từ hạn chế này, WebAssembly ra đời với mục đích: kéo dãn khoảng cách về mặt hiệu năng của web app đến gần như native app.

WebAssembly là gì?

Theo như trang chủ webassembly.org

WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

Tạm dịch:

WebAssemly (viết tắt Wasm) là một dạng tập lệnh nhị phân cho các máy ảo dựa trên ngăn xếp. Wasm được thiết kế để có thể biên dịch từ các ngôn ngữ bậc cao như C/C++/Rust, cho phép các ngôn ngữ đó có thể thực thi trên các ứng dụng web ở cả client và server.

Giải thích:

Việc thực thi javascript trên trình duyệt thông qua các máy ảo - ví dụ ở Chrome là V8. Các máy ảo này thực thi theo cơ chế thông dịch - tức vừa đọc từng dòng code vừa dịch trực tiếp dòng code đó ra mã máy để máy tính có thể hiểu và thực thi.

WebAssembly cũng được thực thi theo cách tương tự. Tuy nhiên do đã là dạng nhị phân nên tốc độ đọc code nhị phân của máy ảo nhanh hơn nhiều so với dạng văn bản, cũng như việc dịch code Wasm ra mã máy tương ứng (theo từng loại hệ điều hành và cpu) đem lại ít overhead (phí tổn) hơn. Do đó, WebAssembly mang lại tốc độ thực thi nhanh hơn nhiều - theo như hứa hẹn từ trang chủ thì sẽ gần bằng native - cũng như sử dụng bộ nhớ hiệu quả hơn so với Javascript.

Ở đây ai đã hiểu cơ chế của ngôn ngữ Java và bytecode máy ảo của nó sẽ thấy rằng WebAssembly cũng tương tự. Đúng như vậy Java có bytecode thông dịch trên máy ảo Java thì WebAssembly chính là bytecode thông dịch trên máy ảo Wasm hoạt động ở trình duyệt.

Tuy nhiên, vì là dạng nhị phân nên Wasm không phải được thiết kế để viết bằng tay mà như là mục tiêu biên dịch của các ngôn ngữ bậc cao như C/C++/Rust để chúng có thể chạy được trên trình duyệt hiệu quả.

Trạng thái hiện tại

Khởi đầu từ tháng 4 năm 2015 từ nỗ lực hợp tác của các khổng lồ công nghệ như Apple, Google, Microsoft, Mozilla,vv . Hiện tại, WebAssembly đang ở mức sản phẩm tối thiểu (MVP) nhưng tiềm năng của nó rất đáng hứa hẹn trong tương lai.

WebAssembly 1.0 đã được triển khai trên bốn trình hiện đại nhất bao gồm FireFox, Chrome, Safari, Edge. Trong tương lai gần, WebAssembly sẽ khổng thể thay thế Javascript bởi hệ sinh thái lớn mạnh của nó. Hiện tại để chạy code Wasm ta phải thông qua các Javascript API.

Luồng thực thi code Wasm cơ bản như sau:

workflow

Wasm workflow

Chạy Wasm đơn giản

Sau đây, chúng ta sẽ chạy hàm sum tính tổng đơn giản được viết bằng c và chạy trên trình duyệt.

1. Cài đặt compiler tool

Hiện tại compiler tool hỗ trợ tốt nhất cho WebAssembly là LLVM. Tuy nhiên tool này rất khó sử dụng. 1 giải pháp thay thế mà dễ sử dụng là Emscripten thích hợp cho việc demo này.

Truy cập https://webassembly.org/getting-started/developers-guide/ để cài đặt Emscripten theo hướng dẫn của trang chủ.

2. Tạo file sum.c

Viết hàm tính tổng số nguyên trong file

# sum.c
int sum(int a, int b) {
  return a + b;
}

3. Biên dịch file c

Tại thư mục chứa file sum.c, gõ dòng lệnh sau để build

emcc sum.c -o sum.js -s EXPORTED_FUNCTIONS='["_sum"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'

Sau khi build sẽ có 2 file mới được tạo ra:

  • sum.wasm : file nhị phân được biên dịch từ sum.c
  • sum.js: file chứa code javascript tạo object Module từ file sum.wasm

4. Tạo file sum.html

<!DOCTYPE html>
<html>
<head>

</head>
<body>
<label>a</label>
<input id="a" type="number">
<label>b</label>
<input id="b" type="number">
<button onClick="btnClick()">Sum</button>
<input id="result" type="number">

<script type="text/javascript" src="sum.js"></script>

<script type="text/javascript">
var sum = Module.cwrap('sum', 'number', ['number', 'number']);

function btnClick() {
  var a = parseInt(document.getElementById("a").value);
  var b = parseInt(document.getElementById("b").value);
  var result = document.getElementById("result");

  result.value = sum(a, b);
}
  

</script>
</body>
</html>

Load file kết nối

<script type="text/javascript" src="sum.js"></script>

Hàm sum trong c được bọc thành hàm sum trong javascript thông qua

var sum = Module.cwrap('sum', 'number', ['number', 'number']);

5. Chạy file sum.html

Gõ lệnh sau để tạo server http phục vụ các file trong thư mục

emrun --no_browser --port 8080 .

Truy cập link sau trên trình duyệt hỗ trợ WebAssembly

localhost:8080/sum.html 

Chúc mừng, đây là code c chạy trên trình duyệt đầu tiên của bạn.

Ứng dụng WebAssembly thực tế

Nếu bạn thấy ví dụ trên chưa đủ cool thì hãy đến với các ví dụ sau

1. Tanks Demo

Các developer WebAssembly đã tạo một demo game sử dụng Unity và export sang WebAssembly để chạy trên web. Thử xem:

2. Construct 3

Đây là một game web editor được tạo bởi WebAssembly. Rất tuyệt phải không

3. Tool nén ảnh Online

Đây là một tool nén ảnh online được tạo bởi Alex Danilo. Điều tuyệt vời của nó là gì? Đó là tool này nén ảnh trên trình duyệt và xem ảnh real-time. Thử xem:
http://alex-wasm.appspot.com/jpeg/index.html

4. WebAssembly Video Editor

Nếu nén ảnh chưa đủ cool thì tool edit video sau sẽ làm bạn ngạc nhiên. Và lại lần nữa, tool này xử lý ngay trên trình duyệt :v:
https://d2jta7o2zej4pf.cloudfront.net/

Tổng kết

WebAssembly đang có một tương lai hứa hẹn. Nó không chỉ giúp cải thiện nhược điểm lớn nhất của các web app - hiệu năng - mà còn mở ra một ứng dụng tuyệt vời khác đó là: nhiều ngôn ngữ lập trình khác sẽ hỗ trợ build ra Wasm, từ đó không chỉ C/C++ chạy được trên nền tảng web mà còn có Java, C#, Rust,...

Tuy WebAssembly chỉ mới bắt đầu ở giai đoạn sản phẩm tối thiểu (MVP) nhưng tìm hiểu thêm về nó cũng đáng đó chứ. Khi được thiết kế thành công thì WebAssembly sẽ là công nghệ hot trong tương lai.

Các tài nguyễn về WebAssembly:

  1. https://webassembly.org/
  2. https://developer.mozilla.org/en-US/docs/WebAssembly
  3. https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/