使用Benchmark.js和jsPerf分析代碼性能
前言
前端開發中,掌握好瀏覽器的特性進行有針對性的性能調優是一項基本工作,同時,比較不同代碼的執行速度也是一項關鍵的工作。
比如,當我們想比較RegExp的test方法和String對象的indexOf方法查找字符串誰的速度更快的話,js代碼在不同的瀏覽器,不同的操作系統環境運行的效率可能是不一樣的,這就是為什么我們需要對其進行基準測試,在做基準測試方面,我們可以使用Benchmark.js和使用jsPerf(一個基于JSLitmus的基準測試庫)。我們可以使用jsPerf來分享你的基準測試。
Benchmark.js 的使用
github 地址: https://github.com/bestiejs/benchmark.js
我們在很多github開源項目中,往往都能看到benchmark文件夾,比如下面這個:
于是Google之,發現這是用來做基準測試的。于是乎:
首先我們在系統根目錄下,通過npm intsall benchmark來安裝benchmark。該模塊會被寫入node_modules文件夾中,我們在test.js文件中通過require方法引入該模塊。
將如下代碼寫入test.js文件,該文件置于系統根目錄下:
var Benchmark = require('benchmark'); var suite = new Benchmark.Suite; // 添加測試 suite.add('RegExp#test', function() { /o/.test('Hello World!'); }) .add('String#indexOf', function() { 'Hello World!'.indexOf('o') > -1; }) // add listeners .on('cycle', function(event) { console.log(String(event.target)); }) .on('complete', function() { console.log('Fastest is ' + this.filter('fastest').pluck('name')); }) // run async .run({ 'async': true });
然后在終端執行node test.js可見輸出結果如下:
? ~ git:(master) ? node test.js RegExp#test x 9,847,928 ops/sec ±1.47% (83 runs sampled) String#indexOf x 23,366,017 ops/sec ±0.91% (96 runs sampled) Fastest is String#indexOf
結果最快的就是String對象的indexOf方法,其中,Ops/sec測試結果以每秒鐘執行測試代碼的次數(Ops/sec)顯示,這個數值越大越好。除了這個結果外,同時會顯示測試過程中的統計誤差,以及相對最好的慢了多少(%)
call和apply的比較
var Benchmark = require('benchmark'); var suite = new Benchmark.Suite; var arr1 = function (str) { return [].slice.apply(str); }; var str2 = function (str) { return [].slice.call(str); }; // 添加測試 suite.add('arr1', function() { arr1('test'); }) .add('str2', function() { str2('test'); }) // add listeners .on('cycle', function(event) { console.log(String(event.target)); }) .on('complete', function() { console.log('Fastest is ' + this.filter('fastest').pluck('name')); }) // run async .run({ 'async': true });
輸出如下內容:
arr1 x 596,505 ops/sec ±1.14% (95 runs sampled) str2 x 627,822 ops/sec ±1.27% (92 runs sampled) Fastest is str2
jsPerf 的使用
jsPerf提供了一個簡便的方式來創建和共享測試用例,并可以比較不同JavaScript代碼段的性能。jsPerf也是基于Benchmark來運行的。
打開jsPerf站點: http://jsperf.com/ ,先將必填的項目填了。其中,slug是短名稱,會生成一個網址,因此不可與別人的重復。然后在Code snippets to compare區域填入title和用于測試的code。最后點擊save test case完成驗證即可。瀏覽器會自動跳轉到測試頁面
Async選項框是用來測試一些異步調用的性能的,我們的代碼沒有使用異步方法,所以不必勾選。
運行測試
點擊“Run tests”按鈕開始測試兩種算法的性能。建議在運行性能測試之前,關閉無關的瀏覽器頁面,關閉其他程序,退出不必要的后臺進程,以保證結果不受其他環境的影響。你也可以通過點擊個別測試用例的名字單獨運行這個例子
點擊該鏈接查看性能比較: http://jsperf.com/huang
jsPerf還會統計所有運行過這個測試用例的瀏覽器的比較結果,顯示在下方的Browserscope區域,可以通過它直觀地看出各個版本瀏覽器的性能橫向和縱向比較情況。
可以看到Firefox下的執行速度明顯高于Chrome
查看別人的測試用例
我們可以通過 http://jsperf.com/browse 瀏覽最新提交的250項最新測試用例。我們也可以使用底部的Revisions來查看不同的版本,也就是不同瀏覽器的測試用例情況。
總結
John Resig在其博文 JavaScript 基準測試的質量 中提到,應該盡量考慮到每個測試結果的誤差并去減小它。擴大測試的樣本值,健全的測試執行,都能夠起到減少誤差的作用。