2017-02-08 39 views
0

我想比較JS EventEmitter和RxJS的性能。我寫了下面的基準腳本來做到這一點:EventEmitter vs RxJS vs Kefir

性能測試

import Rx from 'rxjs/Rx'; 
import Kefir from 'kefir'; 

import { EventEmitter } from "events"; 

let Benchmark = require ("benchmark"); 
let suite = new Benchmark.Suite; 

suite 
.add('for',() => { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let count = 0; 
    for (let i = 0; i<numArray.length; i++) 
    count += numArray[i]; 
}) 
.add('forEach',() => { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let count = 0; 
    numArray.forEach((num) => { count += num; }); 
}) 
.add('eventEmitter',() => { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let count = 0; 
    let myEmitter = new EventEmitter(); 
    myEmitter.on('number', (num) => { count += num; }); 
    numArray.forEach((num) => { myEmitter.emit('number', num); }); 
}) 
.add('rxjs',() => { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let count = 0; 
    let source = Rx.Observable.from(numArray) 
    .do((x) => { count += x }, (error) => {},() => {}); 
    source.subscribe((x) => {}, (error) => {},() => {}); 
}) 
.add('kefir',() => { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let count = 0; 
    let stream = Kefir.sequentially(0, numArray); 
    count = stream.scan(sum => sum + 1, 0); 
}) 
.on('cycle', function (event) { 
    console.log(String(event.target)); 
}) 
.on('complete', function() { 
    console.log('Slowest is ' + this.filter('slowest').map('name')); 
}) 
.run({'async': true}); 

性能結果

for x 47,595,916 ops/sec ±1.58% (87 runs sampled) 
forEach x 4,428,485 ops/sec ±0.75% (86 runs sampled) 
eventEmitter x 1,478,876 ops/sec ±0.61% (86 runs sampled) 
rxjs x 547,732 ops/sec ±0.66% (86 runs sampled) 
kefir x 496,709 ops/sec ±5.15% (50 runs sampled) 
Slowest is kefir 

正如你們所看到酸牛奶竟然是最慢違背要求在這link

  1. 我在編寫測試中做錯了什麼?
  2. 如果有人能解釋爲什麼 發生,那將是非常好的。特別是當你將它與javascript event-emitter進行比較時。
+1

1)該鏈接是RxJS 4,最新版本是v5,這是我認爲你正在使用的。 v5從頭開始重建,重點在於性能。 2)你沒有比較庫之間的相同操作,你爲RxJS添加了'do',並且正在使用'scan'來開發Kefir。 3)你究竟在想什麼?像這樣的微不足道的基準測試並沒有真正告訴你任何關於庫的行爲的任何可觀的規模。 – paulpdaniels

+0

我想比較EventEmitters和Reactive Programming Frameworks之間的性能。哪一個會更高效。我想知道這些性能差異背後的原因。由於我是反應式編程的新手,我不知道所有的功能。我只是用我能找到的第一件事來總結數組中的值。如果你能推薦更好的基準測試技術,那將是非常好的。謝謝 – pntripathi9417

回答

1

我知道你前一段時間問過這個問題,但我認爲給未來的讀者一些關於我在基準測試時注意到的問題可能會有幫助。

首先,count不是Kefir中的一個數字,它是一個流。撥打scan後,嘗試記錄count。而且重要的是,似乎開菲爾count流從來沒有被激活,計算永遠不會運行!這需要先解決。我懷疑Rx基準測試也是如此,但是您必須查看文檔以查看從ES可觀察性創建流是否會阻塞。

我相信你可以實現與類似(未測試的代碼)的東西,庫異步測試:

suite.add('My async test', function(deferred) { 
    let numArray = [1,2,3,4,5,6,7,8,9,10]; 
    let stream = Kefir.sequentially(0, numArray); 
    let countStream = stream.scan(sum => sum + 1, 0); 
    countStream.onEnd(() => deferred.resolve()); 
}, {'defer': true}) 

考慮到這一點,這是很奇怪的酸牛奶的基準是最慢的,因爲它確實沒有工作。我懷疑測試陣列太小,計算得太快而無法獲得有價值的基準。測試可能實際上是測量流的構建時間,或者是運行時運行時運行時收集的最多垃圾收集/處理的基準測試。事實上,如果Rx基準測試不會等待測試完成,那麼它將進行處理/垃圾清理DURRING Kefir測試!您可以通過等待Kefir和Rx測試在基準測試中完成來減輕這一點;通過在基準之間重新使用通用的全局測試數組來創建更少的垃圾;並使用一個非常非常大的數組來確保迭代是測試基準測試時間的主要因素。

最後,異步基準(酸牛奶和Rx),你需要確保的基準測試處理事件對於事件循環的方式相同。我確定Kefir示例在事件循環的不同tick中處理每個事件,並且必須等待瀏覽器的其他任何活動(渲染/繪畫,其他回調/超時等)在每個步驟之間完成流。請看下面的代碼的輸出:

console.log('a') 
setTimeout(function() { 
    console.log('b') 
}, 0); 
console.log('c') 

此代碼將始終打印acb在打印最終b未成年人,非零延遲。

我相信你可以得到酸牛奶處理與像Kefir.constant([1,2,3...10]).flatten()一樣滴答的陣列。但是,我認爲比較同步基準測試中的兩個流式框架並不是很有用,因爲這不是它們的預期目的。

最後,scan操作比在其他框架一個forEach/do語義上不同,因爲它在任何潛在聽衆每個步驟產生用於輸出流的值,而其它僅具有要運行的代碼的一個塊。

基準很難得到正確的結果,但我希望這有助於。

相關問題