2017-02-08 2 views
0

Я хотел сравнить производительность JS EventEmitter и RxJS. Я написал следующий эталонный сценарий, чтобы сделать это:EventEmitter vs RxJS vs Kefir

Performance Test

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) Вы не сравниваете одни и те же операции между библиотеками, вы добавили 'do' для RxJS и используете' scan' для Kefir. 3) Что именно вы пытаетесь оценить? Тривиальные тесты, подобные этому, на самом деле ничего не говорят о поведении библиотеки в любом значительном масштабе. – paulpdaniels

+0

Я хотел сравнить производительность между EventEmitters и Reactive Framework. Какой из них будет более результативным. Я хотел узнать причины этих различий в производительности. Поскольку я новичок в области реактивного программирования, мне не известны все функции. Я просто использовал первое, что мог найти для суммирования значений в массиве. Было бы здорово, если бы вы могли рекомендовать лучшую методику бенчмаркинга. благодаря – pntripathi9417

ответ

1

Я знаю, что вы задали этот вопрос некоторое время назад, но я думаю, что было бы полезно дать будущим читателям представление о некоторых проблемах, которые я заметил при просмотре контрольных показателей.

Во-первых, count не является номером в Кефире, это поток. Попробуйте выполнить регистрацию count после того, как вы позвоните scan. И что важно, кажется, что поток Kefir 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 в тесте Кефира! Вы можете смягчить это, ожидая завершения тестов Кефира и Rx в эталонном тесте; создавать меньше мусора путем повторного использования общего массива глобальных тестов между эталонами; и использовать очень, очень большой массив, чтобы быть уверенным, что итерация доминирует над временем, проведенным в тестах.

Наконец, для асинхронных тестов (Kefir и Rx) вы должны быть уверены, что тесты обрабатывают события одинаково по отношению к циклу событий. Я уверен, что пример Кефира обрабатывает каждое событие в РАЗЛИЧНОМ тике цикла событий, и ему придется дождаться любого другого действия браузера (рендеринга/рисования, других обратных вызовов/тайм-аутов и т. Д.) Для завершения каждого шага в поток. Рассмотрим вывод следующего кода:

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

Этот код всегда будет печатать a, c, b с небольшим, отличной от нуля задержки в печати окончательный b.

Я считаю, что вы можете получить Кефир для обработки массива в том же тике с чем-то вроде Kefir.constant([1,2,3...10]).flatten().Тем не менее, я не думаю, что очень полезно сравнивать две потоковые структуры в синхронном бенчмарке, потому что это не их намеченные цели.

Наконец, scan операции семантически отличается от forEach/do в других рамках, поскольку он производит значение для выходного потока на каждый шаг для любых потенциальных слушателей в то время как другие имеют только для запуска, что один блок кода.

Бенчмарки очень трудно получить, но я надеюсь, что это поможет.

Смежные вопросы