gerry++
久しぶりでいろいろヤバい…… なんか震えがとまらない
久しぶりでいろいろヤバい…… なんか震えがとまらない
JS で、
する癖があることに気付いた。これがいいかどうかは保留
基本的に camelCase は嫌いなんだけど、JS は普通 lowerCamelCase 使うので、公開メソッドはこれにしないといけない。
Index: fuzzyfinder.vim
===================================================================
--- fuzzyfinder.vim (revision 29158)
+++ fuzzyfinder.vim (working copy)
@@ -1543,7 +1543,7 @@
function! s:SetLocalOptionsForFuzzyfinder(cwd, complete_func)
" countermeasure for auto-cd script
- execute ':lcd ' . a:cwd
+ execute ':lcd ' . substitute(a:cwd, " ", "\\\\ ", "g")
setlocal filetype=fuzzyfinder
setlocal bufhidden=delete
setlocal buftype=nofileしてみた。\ の数がすんごいことになってるよ!!!
現状の JSDeferred で何が遅いかっていうと、Deferred.next の setTimeout が遅いのです。setTimeout は interval を 0 に設定しても最低でも 10msec はかかってしまうため、next() や、それを使っている call(), loop() を何度も呼びまくるケースでは ブラウザが全くアイドルであっても 10msec * next() の回数分はかかってしまいます。
実際のところ、setTimeout を使っている理由は「現在の処理が終わったあとに、指定した処理を実行する」という用途なので、それと同じように使える location.href = "javascript:" を試してみたら、とりあえず Fx3.1 ではかなり高速になりました。
コメントをいろいろ頂きまして、最終的に (new Image).onerror (Gecko, WebKit, Opera) による非同期化と ランダム script.onreadystatechange (IE) によるものになりました。
location.href = "javascript:"; は Fx 以外だと同期するっぽくてダメでした (そもそも最初思いついたときはテスト用のページを作るのが面倒だったので GM のコンテキストでやっていて、他のブラウザのことをシカトってました)
「現在の処理が終わったあとに、指定した処理を実行する」と書いたのですが、正確には「「現在の処理が終わったあとに、指定した処理を実行する (ただし UI をブロックしない)」みたいな感じです。
Deferred.next = function (fun) {
var d = new Deferred();
var me = Deferred.next;
switch (true) {
case (me._enable_faster_way && me._enable_faster_way_Image) : {
var img = new Image();
var handler = function () {
d.canceller();
d.call();
};
img.addEventListener("load", handler, false);
img.addEventListener("error", handler, false);
d.canceller = function () {
img.removeEventListener("load", handler, false);
img.removeEventListener("error", handler, false);
};
img.src = "data:,/ _ / X";
break;
}
case (me._enable_faster_way && me._enable_faster_way_readystatechange && (Math.random() < 0.875)) : {
var cancel = false;
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "javascript:";
script.onreadystatechange = function () {
if (!cancel) {
d.canceller();
d.call();
}
};
d.canceller = function () {
if (!cancel) {
cancel = true;
script.onreadystatechange = null;
document.body.removeChild(script);
}
};
document.body.appendChild(script);
break;
}
default : {
var id = setTimeout(function () { clearTimeout(id); d.call() }, 0);
d.canceller = function () { try { clearTimeout(id) } catch (e) {} };
}
}
if (fun) d.callback.ok = fun;
return d;
};
Deferred.next._enable_faster_way = true;
Deferred.next._enable_faster_way_Image = (/\b(?:Gecko\/|AppleWebKit\/|Opera\/)/.test(navigator.userAgent));
Deferred.next._enable_faster_way_readystatechange = (/\bMSIE\b/.test(navigator.userAgent));これで主要ブラウザは数倍早く動くように。
Opera は異様に早くコールバックがきます。
参考までに同じスクリプトをそれぞれのブラウザで動かしたときのどのぐらいかかるか表にしときます。結構ばらつくのと、環境が違うのであんまりアテにならないです。
| 環境 | setTimeout | faster_way | % |
|---|---|---|---|
| Opera 9.5 (Mac) | 80sec | 1.7sec | 4706% |
| Internet Explorer (Win), calc time | 120sec | 6sec | 2000% |
| Safari 3.1 (Mac) | 80sec | 6sec | 1300% |
| Google Chrome (Win) | 31sec | 2.4sec | 1200% |
| Firefox 3.1b2 (Mac) | 83sec | 10sec | 830% |
| Internet Explorer (Win) | 120sec | 17sec | 700% |
ちなみに setTimeout のコールバック最小時間は、IE は 15-16msec で、Chrome は 4-5msec 他のブラウザは 10-12msec です。( http://gist.github.com/51564 ) setTimeout 版では思いっきりそれの差が出てます。
http://subtech.g.hatena.ne.jp/cho45/20090124/1232782523 のスクリプト (1471 step かかる) を普通に Fx3.1 で実行すると、100sec ほどかかるのが、以下のような Deferred.next にすると 50sec ぐらいまで縮みました。(ちなみに Gauche で同じことすると一瞬)
Deferred.next = function (fun) {
var d = new Deferred();
var Global = typeof(unsafeWindow) == "undefined" ? (function () { return this })() : unsafeWindow;
var cbname;
do {
cbname = "callback" + String(Math.random()).slice(2);
} while (typeof(Global[cbname]) != "undefined");
Global[cbname] = function () {
delete Global[cbname];
d.call();
};
d.canceller = function () {
Global[cbname] = function () {
delete Global[cbname];
};
};
if (fun) d.callback.ok = fun;
location.href = "javascript:" + cbname + "()";
return d;
};が、IE だととりあえずこのままだと動かない\(^o^)/
[あとで続き書く]
とりあえず delete Global[cbname]; が IE だとエラーなので try catch すればうごくはず。もうねる
残念ながらこの方法は Firefox 以外だと動かないみたいだ。Firefox 以外では location.href に代入した瞬間に実行されてしまう。うんこですね。ぬか喜びですね。
http://coderepos.org/share/changeset/29001
Image オブジェクトの error イベントを掴まえてくるようにしてみた。Fx, Safari, Opera ではテスト通ってくれるので判定いれてみてる。他になんかいい方法ないかなぁ
なぜか location.href 代入よりさらに早くなって 21sec ぐらいで完了するようになった。
http://subtech.g.hatena.ne.jp/cho45/20080809/1218213154 の続き (いつのだよ)
JSDefrred で callcc を書いたりしてやっと実装できた。クソ遅くて意味ないけど満足した。ポイントは amb が Scheme の amb そのままであるところ (見比べてそのまんまだというのがわかるはず……)
JSDeferred の書きかたがわかりにくい。amb 1つずつを分けて実行させないと (それぞれについて継続を生成して管理する) いけないので、JSDeferred の場合コメントアウトされている部分のような形になってしまう。
これだと問題を書くのが面倒なので amb1 っていう関数使って処理の列を一括生成してる。
http://svn.coderepos.org/share/lang/javascript/jsdeferred/trunk/sample.html#amb
struct stat s;
stat(path, &s);と
struct stat* s;
stat(path, s);の違いがわからない。後者がうごかない (SEGV)。後者はポインタを宣言するだけでポインタのさす先はない、とかそういうこと?
gist の貼り付けコードとかが見えなくなるのがうざいので手をいれた
http://coderepos.org/share/changeset/28585
document.write だけ想定してるのでダメなときはすごくダメかもしれない……
document.write の書きかえを同期的に局所化できないので、必ず一箇所ずつ読みこんでロードするように loop と Deferred つかってる。
mixi 日記がふっとぶ……
なんか alert いれるとふっとばないんだよなぁ…… 観測者問題かよ……
iframe が分割して出力されるせい? っぽかった http://coderepos.org/share/changeset/28627
ちがうなぁ。まだふっとぶ。なんか真っ白になるんよね。広告の iframe でふっとぶのは確実なんだけど、意味がわからない
Hatena Star Everywhere と併用するとダメってことがわかった。でもなんでダメかわからない。iframe 内で GM 動いててなんかうんこになるっぽいけど
めんどいので Hatena Star Everywhere は mixi 除外にした
var a = ["a", "b", "c"];
for (var i = 0, len = a.length; i < len; i++) (function (item, index) {
print([item, index])
})(a[i], i);
fotolife の編集ページを jAutoPagerize させるとクソ重くてどうしようもないので、野生の勘で体感速度を向上させるハックを入れた。
http://coderepos.org/share/changeset/28350
L245 に追加した行をコメントアウトしたりインしたりして http://f.hatena.ne.jp/*/edit みたいなページをロードすると劇的に差を体感できる……
なんでこうなるかっていうのはいまいちよくわからないけど
なのかなぁと思ったので、それを解消できそうな感じのことをしてる。思惑通りにいってるかは微妙なんだけど、少なくとも早くなったことは確かなのでとりあえずよかった
Fx のスクロールはブラウザのパフォーマンスおちに敏感すぎる。flickr も早くなるかと思ったけどよくわからなかった