Thinking
当 Web Worker 的多核并行遇上 WebAssembly SIMD 的单指令多数据加速——一路 1080P H265 的解码开销被压到原来的三分之一,16 路同屏也能流畅无卡顿。
浏览器里做视频软解码,性能一直是道难题。NodePlayer.js 这些年陆续给开发者提供了两条独立的加速路线:
也就是说,过去你得在「单核跑得快」和「多核一起跑」之间做取舍:要 SIMD 就只能在主线程或单 Worker 里享受,要多核并发就只能放弃 SIMD。
现在,这两条路线终于合流了。
从 v1.4.2 起,NodePlayer.js 把 SIMD 加速解码器搬进了 Worker。每一路播放都跑在独立的工作线程里,而每一个工作线程内部的解码器又启用了 SIMD 指令。
| 维度 | 传统 Worker 软解 | Worker × SIMD |
|---|---|---|
| 核心利用 | 多核并行 | 多核并行 |
| 单核效率 | 标量解码 | SIMD 单指令多数据 |
| 综合效果 | 多路但每路偏慢 | 多路且每路都快 |
| 实际感受 | 中高负载 | 低负载 |
对开发者来说几乎零成本——加载 SIMD 版本的播放器文件,调用开启 Worker 的那一行,剩下的播放器自己搞定:它会自动加载与之配套的 SIMD 版工作线程,无需手动指定、无需改业务代码。
我们在 Apple M2 Max 上做了一次极限压测:同时播放 16 路 1080P H265 直播流。
| 模式 | 整机 CPU 占用 | 画面表现 |
|---|---|---|
| Worker 普通软解 | 约 1051% | 流畅 |
| Worker × SIMD 软解 | 约 406% | 流畅,无卡顿 |
CPU 占用从 1051% 一路压到 406%——等于每个核心都额外腾出了三分之二的算力。这部分算力可以用来撑更多路数、跑更复杂的业务逻辑、或者单纯地让设备更凉快、风扇更安静。
测试环境:处理器 Apple M2 Max,浏览器为最新版 Chrome。数据为典型量级参考,实际表现因设备、码率、浏览器版本而异。
SIMD 全称 Single Instruction Multiple Data,单指令多数据流。一条指令进来,CPU 不再只处理一个像素,而是同时处理一整组像素。
举个直观的例子——做加法:
视频解码里到处都是这种”对大量数据做同样的运算”的环节:反变换、运动补偿、色彩空间转换、插值滤波……每一个环节开 SIMD 都能拿到接近线性的加速比。这就是为什么同样一路 1080P 流,SIMD 版本的 CPU 占用能降到原来的三分之一左右。
而把它装进 Worker 之后,每个工作线程都享受到这份加速——多核并发是横向放大,SIMD 是纵向加速,两者叠加是乘法关系。
有读者会问:既然有 GPU 硬件解码方案,为什么还要做 SIMD 软解?
答案是互补,而不是替代。
| 方案 | 解码载体 | 优势 | 局限 |
|---|---|---|---|
| Worker × WebCodecs | GPU 硬解 | CPU 占用最低、能效比最高 | 依赖系统/浏览器开放硬解、部分编码格式受限 |
| Worker × SIMD | CPU 软解(SIMD 加速) | 兼容性广、不挑硬件、格式支持全 | CPU 占用高于硬解 |
实际部署里,把 SIMD 软解作为兜底主力、WebCodecs 硬解作为高配加速,是当下 Web 视频播放最稳妥的组合拳。NodePlayer.js 对这两条路线都做了完整支持,业务层 API 完全一致,按需开启即可。
WebAssembly SIMD 已经普及得相当成熟:
在主流桌面和移动浏览器上,SIMD 版本基本可以放心使用。在不支持的旧环境里,回退到普通版本加 Worker 多线程即可——业务代码无须改动。
只需要两步改动:
仅此而已。没有新的 API 要学,没有复杂的开关要配,事件回调、播放控制、缓冲策略全部和原来保持一致。在线 Demo 可以直接体验多路同屏效果。
useWorker() × SIMD 是 NodePlayer.js 软解路线的一次重要进化。它没有引入任何新的使用心智,却把过去”二选一”的两条加速路线真正合二为一:
一行代码都不用改,把软解性能榨到极限——这就是 Worker × SIMD 带来的改变。