拜浏览器大战所赐,主流浏览器的 JS 引擎已经引入了各类优化技术,不时出现的某某浏览器性能大幅提高的新闻也让前端同窗们信心倍增。那么 JS 这门语言自己是否已经达到了接近原生的水平呢?html
咱们知道,即使引入了 JIT 等更高阶的编译技术,当今的 JavaScript 本质上也是一门脚本语言。不要说对比 C / C++ 这样能编译到原生机器码的语言,即使和使用了字节码的 Java 比起来,JavaScript 的运行时在原理上也没有优点。那么问题来了,怎么样量化地得出 JS 速度和原生语言的差距呢?前端
前端框架领域里有不少 Todo MVC 的 benchmark,它们的对比方式能够简单地理解为对比基于不一样框架实现一样功能的性能。这当然是可行且易于量化的,但不一样的编码实现和构建技巧可能显著地改变跑分数据(如是否打开 React 的优化插件等),而且 Todo MVC 的场景也基本局限于数据的增查改删,还不是真实场景下的复杂应用。git
注意到在今天,许多编程语言已经可以编译到 JavaScript,咱们选择了另外一条方式:对比真实世界应用原生版和 JavaScript 版的性能。而且,在 Web Assembly 已经成为标准的背景下,咱们还有机会对比原生代码、WASM 和 JS 的性能,这看起来就更有趣了。github
怎么样选择所测试的应用呢?咱们须要计算密集型的场景来压榨出运行时的性能,这方面的场景中最多见的就是游戏和多媒体处理了。咱们选择了视频编码领域很是老牌的 FFmpeg,经过将它构建到 WASM 和 JavaScript 的方式,测试其不一样版本编码视频的速度,以此获得原生、WASM 和 JS 的一个性能对比参考。web
咱们但愿对比三种 FFmpeg 构建版使用默认配置编码视频时的速度:算法
测试的输入文件是 JS 版 FFmpeg(即 videoconverter.js 库)附带的 Demo 视频,测试平台是 2015 款乞丐版 MacBook Pro。编程
使用 Homebrew 安装的版本:浏览器
time ffmpeg -i bigbuckbunny.webm output.mp4
复制代码
转码所需时长在 6s 左右。bash
videoconverter.js 附带了一个开箱即用的静态 Demo 页,能够在其中转码视频。选择 Video to .MP4
输出便可。转码所需时长在 140s 左右。前端框架
WASM 版 FFmpeg 没有社区的稳定 release,这里参考了这篇专栏的构建方式,在安装 Emscripten 后从源码编译 FFmpeg 到 WASM,将得到的 ffmpeg.wasm 用于转码。
将一个 C 应用编译到 WASM 后,咱们能够选择在 Web Worker 中使用它。只需将本来的命令行参数换一种格式传递便可:
ffmpeg({
arguments: [
'-i', '/input/demo.mp4',
'out.mp4'
],
files
}, function (results) {
self.postMessage(results[0].data)
})
复制代码
测得所需的时长在 24s 左右。
咱们观察到了比较显著的性能差别:
在这个计算密集型的场景下,JavaScript 的性能在原生的 1/20 左右,而 WASM 的性能能够达到原生的 1/4 左右(强调一遍,只是针对这个场景的结论,不是普适性的)。
但这个数据只能供参考之用,理由是整个链路中还有不少隐式的坑。列举几个:
尽管有上面这些干扰因素存在,咱们基本能肯定的是,JavaScript 与原生之间的性能差距仍然能够是数量级的。只不过在目前常见的中后台、活动页、Hybrid 等场景下,咱们不多须要用 JavaScript 处理计算密集型的任务,这时它不容易成为整个应用的瓶颈。
但愿这个简单的测试对于了解【JS 到底有多慢】能有一些帮助。不过咱们的好消息是,从另外一个角度来看,移动端的 JS 已经不比 PC 端的 JS 跑得慢了,感兴趣的同窗不妨参考笔者的这篇文章。
最后列出文中涉及的相关资源: