编程语言研究书库

为什么需要 WebAssembly — 从 JavaScript 的极限到浏览器里的原生性能

为什么需要 WebAssembly — 从 JavaScript 的极限到浏览器里的原生性能

1. 这一章讲什么

这一章回答全书第一个问题:浏览器里凭什么能跑接近原生速度的重型计算?

它先讲 JavaScript 为什么在视频编辑、科学模拟、3D 建模、游戏这类任务上力不从心, 再讲一次不成功的尝试(asm.js)如何证明了方向、暴露了短板,然后引出 WebAssembly 的诞生和它的 四个设计原则、三大组成件,最后讲它怎么和 JavaScript 搭班干活、怎么靠 WASI 走出浏览器。 后面十四章每一章都建立在「模块、线性内存、沙箱」这三件事上,这一章是全部的地基。1

2. 顶层全景

这一章的推理链是这样走的:

  JavaScript 在重型计算上太慢
      │(三条具体短板:解释执行、没有类型化内存、每次都要重新解析)
      ▼
  asm.js(2013, Mozilla):把 C/C++ 编译成 JavaScript 的一个严格子集
      │(证明了「编译到浏览器」可行;但文件大、还是要解析、各家浏览器优化不一致)
      ▼
  WebAssembly(2015,四大浏览器厂商联手):干脆别装成 JavaScript,定义一种全新的二进制格式
      │
      ▼
  三大组成件:模块(装代码) + 线性内存(装数据) + 执行环境(浏览器或运行时)
      │
      ▼
  与 JavaScript 分工:Wasm 管算,JavaScript 管界面;靠 WASI 再走出浏览器

图说:每一步都是被上一步的短板逼出来的,下一节逐段走这条链。

3. 核心原理

3.1 JavaScript 的三条短板,一条比一条致命

JavaScript 是网页唯一内置的编程语言,本来是为「给页面加一点交互」设计的轻量脚本语言, 后来被推去干视频剪辑、物理模拟、3D 渲染这些重活。书里列了它在重活面前的三条硬伤:2

短板具体意味着什么
解释执行的开销它不是先整体翻译成机器码再跑,而是(当年主流做法是)一边读一边执行,比 C/C++ 这类编译型语言天然多一层成本
没有类型化内存访问它不能直接、精确地按地址操作内存,做密集数值计算时效率上不去
解析与执行的开销人可读的文本源码每次加载都要重新解析、优化,拖慢启动

这三条里,前两条管「跑起来之后快不快」,第三条管「打开页面时快不快」。 WebAssembly 的设计就是把这三条逐一拆掉,后面会看到它的每一项特性都对应着其中一条。

3.2 asm.js:证明了路走得通,也证明了路有多窄

在 WebAssembly 之前,Mozilla 在 2013 年先做了一个中间产物,叫 asm.js。 它是 JavaScript 的一个严格子集:只准用类型化数组(typed array,一种「元素类型固定、 可以按下标直接读写」的数组)和少数几种运算,写法像汇编。 因为规矩死,浏览器引擎可以提前按「这一定是整数运算」来优化,速度接近原生。3

开发者可以用 Emscripten(一个把 C/C++ 翻译成 asm.js 的编译器)把现成的 C/C++ 程序搬进浏览器—— 这个工具链后来原封不动地成了 WebAssembly 时代的主力,书里后面章节会反复见到它。

但 asm.js 有三个迈不过去的坎:4

  • 体积:它本质还是文本,编译出来的文件很大,下载慢;
  • 解析:浏览器仍要在运行时把大段文本解析一遍才能执行,启动延迟躲不掉;
  • 非标准:它依赖各家浏览器各自的优化实现,效果参差,没有统一规范。

asm.js 的历史意义在于:它第一次证明了「把 C/C++ 编译进浏览器」这条路是通的,而且性能真的接近原生。 剩下的问题只是载体不对——不该假装成 JavaScript,该有一种自己的二进制格式。

3.3 2015 年,四个对头第一次联手

2015 年,Google、Mozilla、Microsoft、Apple——四家平常互相竞争的浏览器厂商—— 联手创建了 WebAssembly。四家各自的浏览器引擎(V8、SpiderMonkey、Chakra、JavaScriptCore) 同时实现对它的支持,标准化工作交给 W3C 下的 WebAssembly 社区组。5

一个能让四家竞争对手坐下来共用的标准,靠的是它承诺的四件事:6

  • 高效:目标是接近原生的性能,为计算密集型任务而生;
  • 语言无关:C、C++、Rust 等语言都能编译成它,不被任何一门语言绑架;
  • 跨平台可移植:一份模块编译一次,任何支持它的浏览器、操作系统、设备上都能跑;
  • 安全:运行在沙箱环境里,摸不着宿主系统。

沙箱这个词全书都会出现,先在这里说死: 沙箱是一个被圈起来的执行环境,里面的程序只能碰明确开放给它的东西——内存、函数、接口, 一样不多。Wasm 模块默认连文件系统、网络、屏幕都看不见,除非宿主(浏览器或运行时)主动提供。 这条「默认什么也碰不到,一切靠申请」的设计哲学,是后面 WASI 一章「能力安全」的源头。

3.4 三大组成件:模块、线性内存、执行环境

书里把 WebAssembly 的架构归纳为三块:7

组成件它是什么类比
模块(module)自包含的二进制文件,封装了代码和数据,是 Wasm 程序的基本单位一个「.exe 文件」,但跨平台
线性内存(linear memory)一整块连续的内存区域,模块按偏移量读写它一根长长的格子纸带,每个格子一个字节,程序说「第 1024 格」就能直接读写
执行环境(execution environment)宿主 Wasm 的地方:浏览器、Node.js,或独立运行时(如 Wasmtime、Wasmer)插座

三件套各自解决一件事:模块负责「代码到处能跑」,线性内存负责「数据读写又快又直接」, 执行环境负责「在具体的宿主上把它跑起来」。

围绕三件套,还有四个机制把它们缝起来:

  • 导入/导出(import/export):模块把函数标成 export,外界(通常是 JavaScript)就能直接调用; 反过来模块也可以声明 import,从宿主那里拿函数——浏览器 API 也好、WASI 提供的系统调用也好。8
  • JavaScript 当桥:浏览器里,JavaScript 是 Wasm 的控制器——负责加载模块、喂数据、调函数、把结果显示到页面上。9
  • 类型化数组共享数据:Wasm 的线性内存可以被 JavaScript 包一层「视图」(比如 Uint8Array,按字节看; Float32Array,按 4 字节浮点数看),两边读写的是同一块内存,不用复制。10
  • WASI 出浏览器:WebAssembly 系统接口(WASI,WebAssembly System Interface)给模块一套标准的系统调用 (文件读写、网络、随机数),让它能在非浏览器环境里干活——服务器、IoT 设备、命令行工具。11

3.5 二进制格式与栈式虚拟机:为什么它天生快

Wasm 的代码不是文本,是一种二进制格式——紧凑的字节序列,专为「解析快」设计。 浏览器下载到之后,几乎不需要「读懂一段文字」的过程,直接就能进入编译。12

执行模型是栈式虚拟机:Wasm 指令不直接操作硬件寄存器,而是操作一个抽象的「栈」—— 指令把数压进栈、从栈顶取数运算、把结果压回栈顶。这种模型对不同的真实 CPU 都是同一套语义, 所以一份模块到处能跑;同时语义简单,容易编译成高效的机器码。

模块在 WebAssembly 虚拟机里经历三个阶段:加载(读进来)、校验(检查格式和类型是否合法)、执行。 校验这道关也是安全的一部分——格式不对或类型对不上的模块根本不许运行。13

性能优势主要来自两处:14

  • AOT 式编译:Wasm 是提前编译好的二进制,浏览器拿到后只需很短的编译就能执行, 省掉了 JavaScript 那种运行时反复探测类型、再即时编译(JIT)的漫长预热(引擎要先跑一会儿才生成最快代码);
  • 没有垃圾回收停顿:JavaScript 的内存由垃圾回收器打理,回收时程序会暂停,造成卡顿; Wasm 的线性内存由模块自己管,不会有这种不可预测的停顿。

书里给的量级是:在图像处理、密码学、数值模拟这类任务上,Wasm 对 JavaScript 的 benchmark 优势是 2–10 倍。15

3.6 与 JavaScript 分工,而不是取代

这本书从头到尾的立场:Wasm 不是来替换 JavaScript 的,是来搭班的。16

分工原则一句话:算的活归 Wasm,界面和调度的活归 JavaScript。 Wasm 里没有 DOM(网页文档对象模型,浏览器把页面表示成一棵可操作的对象树)的概念, 想在页面上画东西,得靠 JavaScript 代劳;反过来,界面事件、网络请求这些异步操作(发出去不必干等,结果好了再回来), 也由 JavaScript 接着,算的时候调用 Wasm。17

搭班的具体接口就是 3.4 说的导入/导出加共享内存,各自的短板也写得很坦白:18

  • 调试难:跨 Wasm 和 JavaScript 两边断点,需要 source map(把编译后的二进制映回源代码位置的映射)才能看懂;
  • 数据搬运有成本:两边传大对象要序列化(先转成字节流才能过界),量大了会引入延迟;
  • 类型对不上:Wasm 只认四种数(32/64 位整数、32/64 位浮点),JavaScript 的字符串、对象都得先编码。

3.7 主线例子:一个 C 写的灰度滤镜,从源码到浏览器

把上面所有机制串在一个具体输入上走一遍。输入是一张 800×600 的彩色照片, C 函数把它每个像素点的颜色按公式 灰度 = 0.3×红 + 0.59×绿 + 0.11×蓝 算成灰度。 (这个走法是把本章机制拼起来的演示;原书本章没有逐字节展开一个模块,每一步旁边的数字标注了哪些是书里的、哪些是演示编的。)

第 1 步:编译。 C 源码经过 Emscripten 变成一个 .wasm 文件。这一步里, grayscale 函数被标成 export;Emscripten 还会自动生成一段胶水 JavaScript, 负责加载、铺内存这些杂事。(「Emscripten 生成胶水代码」这件事本身在书里有;具体文件名是演示编的。)

第 2 步:下载与实例化。 页面加载时,胶水 JavaScript 用浏览器提供的 WebAssembly API 把文件取下来, 浏览器做加载 → 校验 → 编译。因为文件是紧凑二进制,这一步比下载同功能的 JavaScript 文本快—— 书里说文本文件「large file sizes that were slow to download」「leading to delays」正是 asm.js 的死因, Wasm 的二进制格式就是为了去掉这一延迟。19

第 3 步:分配内存。 JavaScript 侧把 800×600×4 = 1 920 000 字节的照片数据写进 Wasm 的线性内存 (800 行 × 600 列,每个像素红绿蓝不透明各 1 字节,共 4 字节)。 写法是在共享内存上开一个 Uint8Array 视图,按格子逐字节写——两边看着同一块内存, Wasm 不用「接收」数据,数据本来就在它那根「格子纸带」上。(1 920 000 这个数是按 RGBA 四通道算的演示数。)

第 4 步:调用。 JavaScript 调 export 出来的 grayscale(偏移量, 像素个数)。 Wasm 模块在栈式虚拟机上执行:把像素字节从线性内存读出来、算 0.3×红+0.59×绿+0.11×蓝、 把结果写回内存。1 920 000 次纯整数与浮点运算,正是书里说的「计算密集型任务」—— 这种活 Wasm 对 JS 有 2–10 倍优势。20

第 5 步:取回与显示。 运算结束后,JavaScript 从同一个 Uint8Array 读出结果,交给 Canvas 画到页面上。 DOM 的事,Wasm 从头到尾没沾手——这一步是 JavaScript 做的,正好印证「DOM 委托给 JavaScript」的分工。21

第 6 步:安全收尾。 整个过程里,Wasm 模块看不见你的文件系统、发不了网络请求—— 它活在沙箱里,唯一的对外的手就是当初实例化时明确给它的那几个 import。 「模块只能访问明确暴露给它们的资源」是书里的原话。22

3.8 走出浏览器:同一份模块还能跑在哪

WASI 出现之后,同一份编译产物不止能进浏览器:23

  • 服务器:用 Wasmtime、Wasmer 这类独立运行时跑,隔离性好、启动快;
  • IoT 与嵌入式:模块轻、可移植,适合资源紧张的设备;
  • 桌面:Electron、Tauri 这类桌面应用框架开始集成 Wasm 来加速热点计算。

4. 作者的判断与证据

这一章是「背景与总览」章,判断多于实验,我们把书里给的证据等级分一下:

  • 有 benchmark 支撑的判断:「Wasm 在图像处理、密码学、数值模拟上比 JS 快 2–10 倍」—— 有数字,但本章没给测试条件、样本量和图表,只引用了结论,证据等级算「转述他人评测」。24
  • 史实类陈述:asm.js 2013 年由 Mozilla 提出、2015 年四家联手、W3C 社区组标准化—— 这些与公开历史一致,可信。
  • 立场性判断:「WebAssembly 代表 web 开发的范式转变」「是未来的基石」—— 这是作者的修辞,属于教科书式的定调,不是可检验的论断。

判断(我们的,不是书里的): 这一章把「为什么 Wasm 快」讲对了一半—— AOT、无二进制解析、无 GC 停顿这三条是硬的;但「快 2–10 倍」这种数字在 2026 年的今天要看前提: 现代 JavaScript 引擎的 JIT warmed-up 之后差距常常缩小到一两倍以内,Wasm 的稳定优势更多在 「启动即峰值」「内存布局可控」「可预测性」上,而不是峰值算力。 如果错,会错在: 如果拿 warmed-up 的 SIMD 优化 JS 与未开优化的 Wasm 比,结论可能反过来; 这一章的数字没有测试条件,无从复核,只能当方向性参考。

5. 边界与局限

  • 本章没有写一个真的模块:全章零代码,所有机制都是文字描述,动手内容从第 2 章才开始;
  • 「2–10 倍」没有出处细节:没有 benchmark 表格、没有测试环境,数字不可复核;
  • Component Model 只提了一句名字:这个后来改变「Wasm 与 JS 传数据」方式的规范, 本章只在「互操作的将来」里点了一下,要到第 14 章才展开;
  • asm.js 的史实略有简化:asm.js 2013 年发布时,Google 的 PNaCl 是另一条竞争路线, 本章没有提这场路线之争(属于补充,不在书里:PNaCl 是 Google 搞的「把 LLVM 字节码嵌进网页」的方案, 2017 年被社区放弃,精力转向 Wasm)。
  • 出版时效:本书 2026 年出版,数字与工具链版本以书为准;Wasm 生态一年一变,具体命令要以当下文档为准。

6. 可带走的

  1. Wasm 的定位一句话:把 C/C++/Rust 等语言编译成一种体积小、启动快、沙箱内运行的二进制格式,让重型计算能安全地跑进浏览器——它补的是 JavaScript 的短板,不是取代 JavaScript。
  2. 三件套记牢:模块(装代码)、线性内存(装数据)、执行环境(宿主)。后文所有章节都是这三件的展开。
  3. asm.js 是前身:记住「编译到浏览器走得通、但文本载体不行」这个教训,就理解了 Wasm 为什么必须是二进制。
  4. 快在哪:预编译(不用运行时摸索类型)、紧凑二进制(下载和解析快)、无 GC 停顿(不卡);别死记「2–10 倍」。
  5. 沙箱是默认拒绝:模块默认什么也碰不到,所有能力都来自宿主显式给它的 import——这是全书的安检模型。
  6. 分工口诀:算归 Wasm,界面归 JS;数据走共享线性内存 + 类型化数组视图,大对象要编码,跨边界有成本。
  7. Wasm 只有四种数:想传字符串、对象,先想清楚怎么编码。
  8. WASI 是出浏览器的那扇门:文件、网络、环境变量,全靠它标准化。
  9. 选工具链看语言:C/C++ 用 Emscripten,Rust 用 wasm-pack + wasm-bindgen,TypeScript 背景可以看 AssemblyScript——这一章给的总表,后面章节逐个展开。
  10. 性能实践从压缩和懒加载开始:.wasm 文件用 gzip/Brotli 压缩、按需加载、上 CDN——开销大头常常不在算,而在下载。

7. 原文地图

主题原书章原文位置
JavaScript 三条性能短板Introduction to WebAssemblytext/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:57(搜「Performance Constraints」) · text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:61(搜「Lack of Typed Memory Access」)
asm.js:2013、优点与三大局限同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:75(搜「introduced by Mozilla in 2013」) · text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:91(搜「Binary Size」)
2015 年四家联手与标准化同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:111(搜「joined forces in 2015」)
四大设计原则同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:117(搜「key innovations」)
三组成件:模块/线性内存/执行环境同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:189(搜「three main components」)
导入/导出与 JavaScript 桥同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:211(搜「Import/Export Mechanism」)
二进制格式、栈式虚拟机、校验同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:287(搜「stack-based execution model」)
2–10 倍性能结论同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:305(搜「2–10x」)
游戏/科学计算/流媒体用例同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:319(搜「ported Unity and Unreal Engine games」)
JS 分工、DOM 委托、互操作挑战同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:353(搜「Division of Responsibilities」) · text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:415(搜「delegates DOM-related tasks」)
WASI 与出浏览器场景同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:171(搜「Wasmtime and Wasmer」)
最佳实践总表同上text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:457(搜「Choose the Right Toolchain」)

Footnotes

  1. 出处:「Introduction to WebAssembly」第 13–19 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:15,搜「core components of Wasm」)。原书写这一章「delves into the architectural principles and ecosystem of WebAssembly」,并预告读者将理解 Wasm「not just a new tool but a transformative technology」。 ↩

  2. 出处:「Introduction to WebAssembly」第 57–67 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:57,搜「Performance Constraints」)。三条短板在原文中分别是 Performance Constraints、Lack of Typed Memory Access、Parsing and Execution Overhead 三小节标题下的内容。 ↩

  3. 出处:「Introduction to WebAssembly」第 75–81 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:75,搜「introduced by Mozilla in 2013」)。原文称 asm.js 是「a highly optimized, low-level subset of JavaScript designed to mimic the capabilities of assembly language」。 ↩

  4. 出处:「Introduction to WebAssembly」第 91–101 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:91,搜「Binary Size」)。原文列的三条局限是 Binary Size、Parsing Overhead、Non-standardized。 ↩

  5. 出处:「Introduction to WebAssembly」第 107–147 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:109,搜「Google, Mozilla, Microsoft, and Apple」)。四个引擎的名字见同章 text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:143(搜「Chakra」)。 ↩

  6. 出处:「Introduction to WebAssembly」第 119–133 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:119,搜「Efficient Execution」)。四个创新原文为 Efficient Execution、Language Agnosticism、Cross-Platform Portability、Enhanced Security。 ↩

  7. 出处:「Introduction to WebAssembly」第 189–201 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:189,搜「three main components」)。模块、线性内存、执行环境三件套的原文描述见 text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:193(搜「encapsulate code and data」)。 ↩

  8. 出处:「Introduction to WebAssembly」第 211–225 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:211,搜「Import/Export Mechanism」)。 ↩

  9. 出处:「Introduction to WebAssembly」第 237–243 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:241,搜「acting as the controller」)。原文:「with JavaScript acting as the controller for Wasm execution」。 ↩

  10. 出处:「Introduction to WebAssembly」第 387–403 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:391,搜「store and manipulate data」)。类型化数组的例子是 Uint8Array 和 Float32Array,见 text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:393(搜「Uint8Array」)。 ↩

  11. 出处:「Introduction to WebAssembly」第 257–263 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:257,搜「WebAssembly System Interface (WASI)」)。 ↩

  12. 出处:「Introduction to WebAssembly」第 285–291 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:285,搜「compact and efficient representation」)。 ↩

  13. 出处:「Introduction to WebAssembly」第 291–293 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:291,搜「loading, validation, and execution」)。 ↩

  14. 出处:「Introduction to WebAssembly」第 297–303 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:297,搜「Ahead-of-Time (AOT) compilation」)与同章 text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:303(搜「unpredictable pauses」)。 ↩

  15. 出处:「Introduction to WebAssembly」第 305 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:305,搜「2–10x」)。原文:「Benchmarks reveal that Wasm can outperform JavaScript in tasks such as image processing, cryptography, and numerical simulations by 2–10x.」 ↩

  16. 出处:「Introduction to WebAssembly」第 335–343 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:335,搜「complement JavaScript」)。 ↩

  17. 出处:「Introduction to WebAssembly」第 413–419 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:413,搜「DOM Manipulation」)。 ↩

  18. 出处:「Introduction to WebAssembly」第 425–435 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:425,搜「Debugging Complexity」)。三类挑战是 Debugging Complexity、Data Conversion Overhead、Type Mismatches。 ↩

  19. 出处:「Introduction to WebAssembly」第 93–97 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:93,搜「large file sizes that were slow to download」)。这是 asm.js 的死因,Wasm 的二进制格式正对着这个问题。 ↩

  20. 出处:「Introduction to WebAssembly」第 305 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:305,搜「numerical simulations」)。「2–10 倍」用于演示位置时指原书转述的 benchmark 结论,真实差距随任务与引擎而异。 ↩

  21. 出处:「Introduction to WebAssembly」第 413–415 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:415,搜「delegates DOM-related tasks」)。原文:「Wasm delegates DOM-related tasks to JavaScript.」 ↩

  22. 出处:「Introduction to WebAssembly」第 253–255 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:253,搜「only access memory and resources explicitly exposed」)。 ↩

  23. 出处:「Introduction to WebAssembly」第 169–179 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:169,搜「Server-Side Applications」)。IoT 与桌面见同章 text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:173(搜「IoT and Embedded Devices」)。 ↩

  24. 出处:「Introduction to WebAssembly」第 305 段(text/12-fm-ultimate-webassembly-for-high-performance-apps-b.txt:305,搜「Benchmarks reveal」)。本章通篇没有 benchmark 表格或测试条件,只有这一句结论。 ↩

On this page