LoginSignup
0
0

More than 5 years have passed since last update.

EventEmitterのemitを高速化してみた

Posted at

作ったものでテストしたら、遅いケースでは2倍以上、元々ノーマルでも遅くないケースでも1.1倍程度は速くなっています。

(npmにも登録していないし、英語が苦手なのでEventEmitterにマージしてもらうためのPullRequestも送っていない・・・。)

元々の処理

events.js
    len = arguments.length;
    args = new Array(len - 1);
    for (i = 1; i < len; i++)
      args[i - 1] = arguments[i];

    listeners = handler.slice();
    len = listeners.length;
    for (i = 0; i < len; i++)
      listeners[i].apply(this, args);

まずxxx.emit("foo", 1, 2);というようにemitされると、リスナには1と2を渡す必要が有るため、[1, 2]という配列を作成しています。

その後リスナの配列をクローンしています。onceでリスンしている場合、リスナの要素数が変わるためです。

最後にリスナに対してapplyを呼び出しています。

どう改善すればよいか

最終的には、以下のコードが実行されるのが最速です。リスナのクローンも変数に退避しているため不要ですし、引数のコピーも要りません。仮に引数が3つ、リスナが2つあるとすると以下のようになります。

events.js
var l0 = handler[0],
var l1 = handler[1],
var a1 = arguments[1],
var a2 = arguments[2],
var a3 = arguments[3];
l0.call(this, a1, a2, a3);
l1.call(this, a1, a2, a3);

これをどう動的に実行させるか

引数の数とリスナの数に合わせて、上記のコードを生成して、new Functionを行います。Functionの動的生成はコストが高いですがキャッシュしておけば一度だけしか作られません。

他の細かい改善

arguments[1]は仮引数で予めarg1を受け取ると高速になります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0