2009年 02月 05日

gerry++

久しぶりでいろいろヤバい…… なんか震えがとまらない

2009年 01月 30日

lowerCamelCase / snake_case

JS で、

  • 公開メソッドや広い範囲の変数には lowerCamelCase
  • 非公開メソッドや狭い範囲の変数には snake_case

する癖があることに気付いた。これがいいかどうかは保留

基本的に camelCase は嫌いなんだけど、JS は普通 lowerCamelCase 使うので、公開メソッドはこれにしないといけない。

2009年 01月 28日

fuzzyfinder.vim がスペース入ったディレクトリ内だとえらる

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

してみた。\ の数がすんごいことになってるよ!!!

2009年 01月 25日

JSDeferred を高速化する (試し中)

現状の 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 ぐらいで完了するようになった。

2009年 01月 24日

非決定性計算 on JSDeferred


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

2009年 01月 20日

はてブで NG にしたユーザはハイクとダイアリと人力でも非表示にする GM

2009年 01月 19日

C のおべんきょう

struct stat s;
stat(path, &s);

struct stat* s;
stat(path, s);

の違いがわからない。後者がうごかない (SEGV)。後者はポインタを宣言するだけでポインタのさす先はない、とかそういうこと?

2009年 01月 18日

jAutoPagerize ブログパーツのたいおう

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 除外にした

2009年 01月 15日

var a = ["a", "b", "c"];

for (var i = 0, len = a.length; i < len; i++) (function (item, index) {
	print([item, index])
})(a[i], i);
2009年 01月 13日

jAutoPagerize が一部ページでクソ重い現象の解消

fotolife の編集ページを jAutoPagerize させるとクソ重くてどうしようもないので、野生の勘で体感速度を向上させるハックを入れた。

http://coderepos.org/share/changeset/28350

L245 に追加した行をコメントアウトしたりインしたりして http://f.hatena.ne.jp/*/edit みたいなページをロードすると劇的に差を体感できる……

なんでこうなるかっていうのはいまいちよくわからないけど

  • 画像が読みこまれると周りの要素がつらつらと再フローされる (width/height がかいてないから?)
    • あとこのサムネイルに設定されてるセンタリングのための onload ハンドラが重い?
  • 画像が多いのでこれがめっちゃ走りまくる

なのかなぁと思ったので、それを解消できそうな感じのことをしてる。思惑通りにいってるかは微妙なんだけど、少なくとも早くなったことは確かなのでとりあえずよかった

Fx のスクロールはブラウザのパフォーマンスおちに敏感すぎる。flickr も早くなるかと思ったけどよくわからなかった