拜瀏覽器大戰所賜,主流瀏覽器的 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 跑得慢了,感興趣的同窗不妨參考筆者的這篇文章。
最後列出文中涉及的相關資源: