在初始试用阶段,Chrome 70 中已提供 WebAssembly 线程支持。
WebAssembly (Wasm) 支持对使用 C++ 和其他语言编写的代码进行编译 供您在网络上运行。原生应用的一项非常实用的功能是能够使用线程,线程是并行计算的基本功能。大多数 C C++开发者非常熟悉 pthreads, 用于在应用中进行线程管理的标准化 API。
WebAssembly 社区群组一直致力于将线程引入 Web 以实现真正的多线程应用。作为这项工作的一部分,V8 在 WebAssembly 引擎中实现了对线程的必要支持,可通过源试用版获得。源试用 让开发者可以在新的 Web 功能全面投入使用之前,对它们进行试验 标准化。这样一来,我们就可以从大胆的开发者那里收集真实反馈,这对验证和改进新功能至关重要。
Chrome 70 版本支持 WebAssembly 线程,我们建议 有兴趣的开发者开始使用这些功能,并向我们提供反馈。
线程?工人呢?
自 2012 年以来,浏览器在 Chrome 4 中一直支持通过 Web Worker 实现并行处理;在 “在主线程上”这样的词语是很正常的等。但是, 工作器不会在它们之间共享可变数据,而是依赖于 以及通过消息传递进行通讯事实上,Chrome 会为每个 isolate 分配一个新的 V8 引擎。隔离容器既不共享已编译的代码也不共享 JavaScript 对象,因此它们无法共享可变数据(如 pthread)。
另一方面,WebAssembly 线程是可以共享同一 Wasm 的线程 内存。共享内存的底层存储是通过 SharedArrayBuffer 实现的,这是一种 JavaScript 基元,允许在多个工作器之间同时共享单个 ArrayBuffer 的内容。每个 WebAssembly 线程都在 Web Worker 中运行,但由于它们共享 Wasm 内存,因此其工作方式与在原生平台上的工作方式非常相似。这意味着,使用 Wasm 线程的应用负责管理对共享内存的访问,就像在任何传统线程应用中一样。目前有很多使用 C 或 C++ 编写的代码库 使用 pthreads,这些线程可编译到 Wasm 并在 true 下运行 线程模式,让更多核心可以同时处理相同的数据。
一个简单示例
下面是一个简单的“C”示例使用线程的程序
#include <pthread.h>
#include <stdio.h>
// Calculate Fibonacci numbers shared function
int fibonacci(int iterations) {
int val = 1;
int last = 0;
if (iterations == 0) {
return 0;
}
for (int i = 1; i < iterations; i++) {
int seq;
seq = val + last;
last = val;
val = seq;
}
return val;
}
// Start function for the background thread
void *bg_func(void *arg) {
int *iter = (void *)arg;
*iter = fibonacci(*iter);
return arg;
}
// Foreground thread and main entry point
int main(int argc, char *argv[]) {
int fg_val = 54;
int bg_val = 42;
pthread_t bg_thread;
// Create the background thread
if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
perror("Thread create failed");
return 1;
}
// Calculate on the foreground thread
fg_val = fibonacci(fg_val);
// Wait for background thread to finish
if (pthread_join(bg_thread, NULL)) {
perror("Thread join failed");
return 2;
}
// Show the result from background and foreground threads
printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val);
return 0;
}
该代码以 main()
函数开头,该函数声明了 2 个变量 fg_val
和 bg_val
。还有一个函数称为
fibonacci()
:
线程。main()
函数使用 pthread_create()
创建一个后台线程,该线程的任务是计算与 bg_val
变量的值对应的斐波那契数序列值。与此同时,在前台线程中运行的 main()
函数会为 fg_val
变量计算该值。部署
后台线程已完成运行,系统会输出结果。
针对线程支持进行编译
首先,您应安装 emscripten SDK,最好是 1.38.11 或更高版本。要使用 已启用的线程 要在浏览器中运行,我们需要向 emscripten emcc 编译器。我们的命令行如下所示:
emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c
命令行参数“-s USE_PTHREADS=1
”开启线程支持
已编译的 WebAssembly 模块和参数“-s PTHREAD_POOL_SIZE=2
”
指示编译器生成由两 (2) 个线程组成的池。
运行程序时,程序会在后台加载 WebAssembly 模块,为线程池中的每个线程创建一个 Web Worker,并与每个 worker 共享该模块(在本例中为 2),每当调用 pthread_create()
时,这些 worker 都会被使用。每个 Worker 都会将
Wasm 模块,以便它们能够进行协作。V8 7.0 中的最新变更共享了在工作器之间传递的 Wasm 模块的已编译原生代码,这使得即使非常大型的应用也能扩展到许多工作器。请注意,请务必确保线程池大小等于应用所需的线程数量上限,否则线程创建可能会失败。同时,如果线程池大小过大,您将创建不必要的 Web Worker,这些 Worker 除了占用内存外,什么也不会做。
如何试用
如需快速测试我们的 WebAssembly 模块,最快的方法是在 Chrome 70 及更高版本中开启实验性 WebAssembly 线程支持。在浏览器中前往网址 about://flags
,如下所示:
接下来,找到实验性 WebAssembly 线程设置,该设置如下所示:
如下所示,将设置更改为已启用,然后重启浏览器。
浏览器重启后,我们可以尝试使用仅包含以下内容的最小 HTML 页面加载线程化 WebAssembly 模块:
<!DOCTYPE html>
<html>
<title>Threads test</title>
<body>
<script src="test.js"></script>
</body>
</html>
如需试用此页面,您需要运行某种形式的 Web 服务器,并从浏览器加载该服务器。这会使 WebAssembly 模块加载并运行。开场白 DevTools 会显示运行的输出,您应该会看到类似 控制台中显示的以下输出图片:
包含线程的 WebAssembly 程序已成功执行!我们建议 您可以按照上述步骤试用自己的线程式应用。
通过源试用在现场进行测试
在浏览器中启用实验性标记来试用线程是 但如果您想在测试环境中测试自己的应用 可以使用所谓的 源试用。
通过源试用,您可以 与您的网域绑定的测试令牌。然后,您可以部署应用,并希望它能在支持您要测试的功能的浏览器(在本例中为 Chrome 70 及更高版本)中正常运行。如需获取自己的令牌以运行来源试用,请使用此处的表单提交申请。
我们使用源试用令牌托管了上面的简单示例,因此您可以 亲自试用 而无需构建任何内容。
如果你想了解并行运行的 4 个线程对 ASCII 图谱有何用处,那么 你必须接受 请观看此演示!
向我们提供反馈
WebAssembly 线程是一项非常实用的新基元,可用于将应用移植到 Web 平台。现在,您可以在 WebAssembly 环境中运行需要 pthreads 支持的 C 和 C++ 应用和库。
我们正在向试用此功能的开发者寻求反馈,这有助于 为标准化过程提供信息,并验证其实用性。最佳 发送反馈的方式是 报告问题并/或获取 标准化 代码生成 WebAssembly 社区群组。