IE6からもっと高速化してみました

さて、今日はパズルアップしていないのですが、
スリザーリンクのやつをアップしたという話と、
そのついででIE6/IE7から結構処理が高速化できたという話です。
# とりあえずpencilboxにあるのはこれでやめておきます。
 
そういや色分け時の色もランダムにするようにしました。(前は固定の20色から選んでいた)
と、言っても完全ランダムじゃなくてHLS変換して色相を違うようにしたりとか彩度高いのだけ選んだりとか、
YCbCr変換して輝度の中間っぽいのを選んだりとかトリッキー?なことはやってます。
 
で、高速化というとどんなもんよ、というと速いマシンならIE6でも25×15のスリリン、
ちょっとまったり遅めながらも解けるようになりました。前の5〜6倍は速くなってるかも。
詳しいことは続きを読んでください。
 
スリザーリンクを作るにあたって、線の色分け処理を入れようと思いました。
この処理自体は前から作っていたので、フラグを立てるだけだったのですが
入れてみたらIE6があまりに重くて、「これベンチマークできるレベルじゃね」と思って
いろいろなブラウザで100回〜1000000回(IEは10回)ループを入れて測定してみたのです。
 
盤面10×10のスリザーリンクの、線を引けるところ全てに線を引いてある状態を作り出して、
「色分けし直す」ボタンを押して測定しました。
項目は色分け処理の各部分とトータルを、1回辺りかかった時間の平均で出しています。
 ・setNull        始めに全部の線の色を初期化する
 ・NewColGen     それぞれの線の色をランダムに選ぶ
 ・ChangeColors   繋がっている線の色を全部同じにする
 ・RepaintCanvas  盤面全体の再描画
 ・Total         上記を含んだ関数全体の処理時間
 
最初何もしないでそのまま測定してみたところ、
               IE6   Firefox3.0.4 Safari3.2.1 GoogleChrome1.0
 setNull         3.8msec  0.07msec  0.12msec  0.006msec
 NewColGen      42msec  0.54msec  0.94msec   0.12msec
 ChangeColors   1234msec   54msec   49msec   21msec
 RepaintCanvas   739msec   18msec   18msec   10msec
 Total         1897msec   72msec   64msec   31msec
 
GoogleChromeはテスト前、バージョンを確認しようと思ったらたまたま正式版にバージョンアップできました。
まぁ、それはいいのですが、、Canvasexcanvasの差はあるにせよ、こりゃ確かにIE6遅すぎです。

ただ、よく考えると、・ChangeColorsの中で線ごとに色を再描画しているため、
動作が重複していました。その部分を最適化したのが次の測定結果です。
               IE6   Firefox3.0.4 Safari3.2.1 GoogleChrome1.0
 setNull         3.4msec  0.08msec  0.12msec  0.006msec
 NewColGen      37msec   0.4msec   0.9msec   0.12msec
 ChangeColors    82msec   11msec   12msec    4msec
 RepaintCanvas   756msec   18msec   18msec    4msec
 Total         793msec   26msec   26msec   8.5msec
 
全部速くなったわーい、っていうか全部スピード2倍以上になってますね。。
っていうかGoogleChrome速すぎ。。ループで時間水増ししている関係もあるかもしれませんが。
(GoogleChromeはループ処理が得意)
 
さて。肝心のIE6ですが、まだ速さ的には実用的じゃないです。
これを減らすには、色の再描画処理を見直さなければいけません。
 

      • -

JavaScriptの描画処理って、HTML5Canvasタグっていうのが追加されていて、
Firefox, Safari, Opera, GoogleChromeあたりは対応してます。
盤面に線などをどんどん引いたり出来るタグです。(ただし、現時点では文字描画はできない)
 
でも、IEってこのCanvasタグってのに対応してないんです。(IE8ですら対応しない)
そこで、同じJavaScriptコードでそれっぽい動作をするexcanvas.jsってのをGoogleの人が作ったわけです。
このexcanvasっていうのは、VMLっていう「線のパーツ」「四角形のパーツ」等を表示するタグを利用して、
これを追加していくことによって線などを引いているように見せかける便利スクリプトです。
 
でも、Canvasタグだとどんどん書いてもメモリ上は1つの盤面なのに対して
excanvasはパーツがどんどんどんどん増えてしまうので、とっても重くなります。
 
前に軽くしたよーって言ったのは、excanvas.jsに手を入れて個々のVMLにidをつけることによって
パーツを「表示する」「表示しない」「色を変える」という動作を追加して
無造作にパーツ数が増えるのを阻止したのです。これで「ほぼハング」状態からはだいぶマシになったのですが。
 
で、ここまで見て一つの方向性が思い浮かんだわけです。それは、idをつけた後、
そのパーツを参照するのに$("id")って参照していたのですが、
それだと毎回"id"を持つパーツを検索しに行ってしまうので、重くなるんじゃないかと。
毎回数十回検索するし、パーツ数増えれば増えるほど検索に時間かかるようになるし。
それで、あらかじめ検索結果(element)を配列に保持しておくようにしたわけです。
そうした後の結果が以下のような感じ。(IEしか関係ないのでIE6の結果だけ)
               IE6
 setNull         1.5msec
 NewColGen      2.5msec
 ChangeColors    40msec
 RepaintCanvas   114msec
 Total         159msec
 
数日前の1897msecと比べて12倍くらいの高速化に成功しました。
しかも、後半は通常の描画処理にも効いてくるので、なんか普通の場合も速くなったよ、というわけです。
まぁ、これでも描画処理が他ブラウザの10〜30倍遅いですが、もうしょうがないっぽいです。
 
これで、エラー表示時に全画面再描画する時も相当な高速化になってます。
しかし、盤面のリサイズ時など、サイズ自体が変わる時はパーツを全部破棄して置き直すので
素の実力が見えてしまいます。すっごい重いよ!
 
さて、$("")でいろいろいじくるのって、DOM処理っていうやつなのですが、
以下のページにそのDOM処理のブラウザごとの処理速度があってIE6ってめちゃくちゃ遅いんですよね。。
IE8で4倍くらいは速くなるのでやっぱそれなりに速くなるのかも、、っても4倍だとまだまだかなぁー。
Canvasタグのネイティブ対応もしなさそうだし、当分はだましだましですかねぇ。
 
続・速度で選ぶ次世代ブラウザー Firefox 3正式版対応 [2/4ページ]
http://ascii.jp/elem/000/000/144/144794/index-2.html