closure libraryのBrowserEventが微妙
以前closure libraryのdialogがリサイズできないと書きました。
しかたがないのでgoog.fx.Draggerを使ってExt.jsやjQuery UIのResizableクラスを作ってリサイズできるようにしました。
しかし動かしているとなんとなく元のダイアログより遅く感じます。
ちなみに元のダイアログはscript.aculo.usのdraggableで作ったアリエル製リサイズクラスを使ってます。
最初はドラッグ中にリアルタイムでリサイズしているせい(Ext.Resizablelのdynamic=trueやjQuery UIのghost=falseの状態)だと思い、ドロップ時だけリサイズするためのプロパティを追加したのですがそれでもまだ少しだけカクカクします。
私の環境ではほとんど気にならないレベルですが古いPCだとどうなるのかわかりません。
ちょっと怖いので、Fire BugでプロファイルをとってみるとBrowserEventのinitイベントがトップになります。
http://closure-library.googlecode.com/svn/trunk/closure/goog/docs/closure_goog_events_browserevent.js.source.html
goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {さらに調べるためこれを
//(中略)
this.offsetX = e.offsetX !== undefined ? e.offsetX : e.layerX;
this.offsetY = e.offsetY !== undefined ? e.offsetY : e.layerY;
this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
this.screenX = e.screenX || 0;
this.screenY = e.screenY || 0;
this.button = e.button;
this.keyCode = e.keyCode || 0;
this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
this.ctrlKey = e.ctrlKey;
this.altKey = e.altKey;
this.shiftKey = e.shiftKey;
this.metaKey = e.metaKey;
this.event_ = e;
delete this.returnValue_;
delete this.propagationStopped_;
};
goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {のように書き直して(関数内関数最高!)調べていくとどうも
//(中略)
function f1() {
this.offsetX = e.offsetX !== undefined ? e.offsetX : e.layerX;
this.offsetY = e.offsetY !== undefined ? e.offsetY : e.layerY;
}
function f2() {
this.clientX = e.clientX !== undefined ? e.clientX : e.pageX;
this.clientY = e.clientY !== undefined ? e.clientY : e.pageY;
}
function f3() {
this.screenX = e.screenX || 0;
this.screenY = e.screenY || 0;
}
f1.call(this);
f2.call(this);
f3.call(this);
this.button = e.button;
this.keyCode = e.keyCode || 0;
this.charCode = e.charCode || (type == 'keypress' ? e.keyCode : 0);
this.ctrlKey = e.ctrlKey;
this.altKey = e.altKey;
this.shiftKey = e.shiftKey;
this.metaKey = e.metaKey;
this.event_ = e;
delete this.returnValue_;
delete this.propagationStopped_;
};
this.screenX = e.screenX || 0;の2行が全体の80%くらい時間がかかっている事が判明しました。
this.screenY = e.screenY || 0;
script.aculo.us版ではscreenX、screenYは使っていなかったのでこれが遅さの原因でしょう。
話がずれますが、Fire Bug1.3から1.4になったときに
hoge: function() {だとスタックトレース時に無名関数扱いになったんですよね。デバッグし辛くなって困るんですが。
ところがプロファイル時は名前がちゃんと取れてました。ふっしぎー。
goog.events.BrowserEventは名前のとおりブラウザのイベントをラップするクラスなので、closure libraryのイベント管理を使ってブラウザのイベントを監視する場合必ず生成されるはずです。
IEではどうなのかわかりませんが、FireFoxだと動きを見る限りscreenX、screenYの評価を遅延することで速度をあげようとしています。
なのにclosure libraryのイベント管理を使うとscreenX、screenYを使うか使わないかに関わらず必ずscreenX、screenYが計算されてしまいます。
これって微妙じゃないですか?
ついでにFireFoxのソースも確認してみました。
http://hg.mozilla.org/tracemonkey/file/10dc623ee90f/content/events/src/nsDOMUIEvent.cpp
↑のGetScreenPointメソッドと
http://hg.mozilla.org/tracemonkey/file/10dc623ee90f/content/events/src/nsDOMMouseEvent.cpp
↑のGetScreenX、GetScreenYメソッドだと思います。
計算結果のキャッシュとかしてないのかな?
だとしたらGetScreenX、GetScreenYで全く同じ計算を2回やってることになりそうだけど。嫌だなあ。
せめてJavaScriptからGetScreenPointを直接叩けるといいんだけど。
- Category(s)
- JavaScript
- The URL to Trackback this entry is:
- http://dev.ariel-networks.com/Members/uchida/closure-library306ebrowserevent5fae5999/tbping
Re:closure libraryのBrowserEventが微妙
私も、最近 Closure Library を使っていて、同じようなことを思ったんですが、
きっと Closure Library って Closure Compiler とセットで使うことを主眼に置いてるんじゃないでしょうか。
Closure Compiler を使って強い最適化をすれば、おそらく「使わないプロパティへの値の設定」は省略されると思います。
まあ Closure Compiler を使わないとパフォーマンスが出ないっていうのも微妙だとは思いますが。
Re:closure libraryのBrowserEventが微妙
いつもブログの方拝見させてもらっています。
> Closure Compiler を使って強い最適化をすれば、おそらく「使わないプロパティへの値の設定」は省略されると思います。
goog.ui.datepickerを使おうと思ったらgoog.i18n.datetimesymbols.js(約150kB)がインクルードされて泣きました。
SIMPLE_OPTIMIZATIONSだと半分位のファイルサイズにしかなりませんし、その他文字コード絡みで色々と苦労させられたファイルでした。
確かにADVANCED_OPTIMIZATIONSが使えるとよいのですが、制約が強くて使えていません。