上一篇文章我展示了這個最高性能庫的實現方法。下面我介紹一下這個性能提升的祕密。
首先,爲了弄清楚Most庫究竟爲何如此快,我必須藉助其他工具。比如chrome 的devtools性能分析,剛開始我運行node --inspect來啓動性能測試代碼,然後打開chrome瀏覽器,在chrome://inspect裏面打開nodejs調試工具,不過每次這樣操作比較繁瑣,後來直接用Nodejs提供的inspector模塊來生成cpuprofile文件。
const inspector = require('inspector');
const fs = require('fs');
const session = new inspector.Session();
session.connect();
function logStart() {
console.log(this.name);
console.log('-----------------------------------------------');
session.post('Profiler.enable', () => {
session.post('Profiler.start', () => {
// invoke business logic under measurement here...
});
});
}
function logComplete() {
console.log('-----------------------------------------------');
// some time later...
session.post('Profiler.stop', (err, {
profile
}) => {
// write profile to disk, upload, etc.
if (!err) {
fs.writeFileSync('./profile.cpuprofile', JSON.stringify(profile));
}
});
}
我們可以看到每一種庫佔用的CPU的情況,下面我們先來看一下Most庫的情況:
Most庫裏面有一個時間軸,然後把任務分配到時間軸上運行,所以我們會看到很多task的關鍵詞,當然現在的性能測試並沒有發揮時間軸的作用,我們看到這一次性能採集運行了57.3ms,下面的操作符函數佔用cpu的情況如圖。
接下來我們看一下rx4rx-lite,我們的最小代碼庫的執行情況:
執行了88ms
我們看到了大量的函數調用,這些都是因爲創建了很多閉包的箭頭函數。
以上只是說介紹瞭如何去看性能的方法,實際探索過程中,伴隨的是大量的模仿和嘗試,最後總結出以下幾點:
- 調用匿名函數比調用原型鏈中的函數要慢
- 匿名函數調用會產生垃圾回收,GC佔用CPU
- super關鍵字調用很慢很慢
- 讀寫臨時變量比讀寫對象屬性要慢
- 覆蓋原型的方法,比直接訪問原型的方法要慢
- 注意構造函數裏面的賦值順序
產生以上原因主要就是V8引擎在底層的處理有關,比如快速對象(C++類),還有就是儘量避免GC,全局變量和類定義(一回事)不會被輕易GC
最後我們看一下rx4rx-fast 我們的最高性能庫的表現:
達到了43.3ms,雖然函數調用較深,但所佔CPU極少了。
(未完待續)