Hatena::ブログ(Diary)

yukobaのブログ このページをアンテナに追加 RSSフィード Twitter

2010年01月30日

[]JavaScript配列は<canvas>のImageDataを使った方が高速

JavaScriptはJITが載り、高速化したのですが、配列操作が遅いです。連想配列とArrayがごちゃ混ぜになっているのが原因だと思います。

<canvas>が2009年夏頃に、テキスト描画とピクセル操作の機能が追加になり、Firefox, Google Chrome, Safari には実装されています。そして、ピクセル操作を使うと、int32型の配列が作れます。

var ctx = canvas.getContext('2d');
var imageData = ctx.createImageData(1024, 1);
var ary = imageData.data;

この配列は、int32専用で、Arrayとは違って、任意の型が入るわけではありません。その分だけ、ほんのちょっとだけ高速化しています。

挿入ソートで、ベンチマークを取った実行時間の結果。長さ1024の配列を100回挿入ソートしています。単位ms

ブラウザcanvasのImageDataArray高速化
IE 8 43400
Firefox 3.6536954451%高速
Chrome 42350266413%高速
Safari 4727475264%高速
Opera 10.50 3392

IE8に限り、3/100に実行回数を減らして、結果を100/3倍しています。

まぁ、ぶっちゃけ、ほとんど差がないです。しかしながら、ブラウザごとの差は大きいですね。載せていませんが、Javaとの差もかなり大きかったです。配列のコピーなどはcanvasの命令を使えるので、ArrayよりもImageDataを使った方が高速だと思います。

<canvas>で3Dが使えるようになるWebGLの実装が、まもなく正式公開になりますが、OpenGL経由でCUDAみたいなことができるようになるのでしょうか?

追記

ふと気づいたのですが、Array間のコピーって、こういうやり方があるんですね。たぶん、forループで回すよりも速いと思いますが、ary2に対するunshiftやspliceの部分が気になりますね。

ary2→ary1へのコピー@index = 1〜3

var ary1 = [1,2,3,4,5];
var ary2 = [12,13,14];
ary2.unshift(1, ary2.length);
ary1.splice.apply(ary1, ary2);
ary2.splice(0, 2);

unshiftを使わないと、以下の通り。こっちの方がいいかも。

var ary1 = [1,2,3,4,5];
var ary2 = [12,13,14];
ary1.splice.apply(ary1, [1, ary2.length].concat(ary2));
トラックバック - http://d.hatena.ne.jp/yukoba/20100130/p1