IT戦記 このページをアンテナに追加 RSSフィード Twitter

2007-10-10

一行で IE の JavaScript を高速化する方法

以下の一行をすべての JavaScript の前に読み込む

/*@cc_on _d=document;eval('var document=_d')@*/

この一行を読み込むことによって IE での document へのアクセスが 5 倍速くなります。

たとえば

以下のように、読み込む前と読み込んだ後を比較してみます。

// Before
var date = new Date;
for (var i = 0; i < 100000; i++) document; 

alert(new Date - date); // 643

/*@cc_on _d=document;eval('var document=_d')@*/

// After
date = new Date;
for (var i = 0; i < 100000; i++) document; 

alert(new Date - date); // 145

速くなってますね!

解説

まず、 IE では document にそのままアクセスすると window オブジェクトの内部メソッドが実行されてしまいます。これが非常に重いのです。

そこで、以下のようにすると速くすることができます。

var doc = document;

document; // こっちより
doc;      // こっちのが速い

これだけでも、大丈夫なのですが、今まで document を使って書いてきたコードをすべて書き換えるのはめんどくさいですよね。

ですので

var doc = document;
var document = doc;

のようなことを出来れば一番いいのですが。。。

これもまた、 JavaScript では変数はスコープの先頭で生成されるため、 document は空の変数となり undefined になってしまいます。

そこでさらに以下のようにします。

var doc = document;
eval('var document = doc');

evalvar 宣言することでスコープ途中から変数を生成することができるのです。

これで、以降の document は内部メソッドを呼ばれずに変数としてアクセスできます。

最後に、 IE でしか効果ないので条件付きコメントで囲っておきましょう

/*@cc_on 
var doc = document;
eval('var document = doc');
@*/

はい。完成。わーわーぱちぱちぱち

まとめ

これは便利!使ってください!

追記:

なんか、すごい勢いでブクマされてるのでびっくりしつつ追記。

以下のようにすると document 以外のグローバル変数にも使えます。そして、それぞれに同じ効果があります。

/*@cc_on
eval((function(props) {
  var code = [];
  for (var i = 0 l = props.length;i<l;i++){
    var prop = props[i];
    window['_'+prop]=window[prop];
    code.push(prop+'=_'+prop)
  }
  return 'var '+code.join(',');
})('document self top parent alert setInterval clearInterval setTimeout clearTimeout'.split(' ')));
@*/

追記2:

さらにの反響に驚愕しつつ追記><

この方法は document と書かれた部分を 5 倍以上(ループのコストを引くとたぶん 10 倍以上?)速くすることができるのですが、その数倍というのは「プロパティアクセス」と「関数呼び出し」の差です(関数呼び出しを減らしていると考えてください)。

ですので、ほとんどのウェブサイトでは効果はあまり感じられないかもしれません

ただ、僕の作ってるものですごい効果があったので、焦ってブログに書いてしまいました。もうちょっと注意深くエントリを書くべきだったかもしれないですね><

参照:

一行で IE の JavaScript を高速化する方法 - #生存戦略 、それは - subtech

Twitter / mala: amachangのあれ、すごいブクマされてるけど10 ...

しかし、この方法は document だけに適用できる方法ではありません。ありとあらゆる DOM アクセスに対して同様のテクニック、考え方を応用することができます。応用すれば、多くのサイトで JS の高速化が出来るのではないかと思います。

そこら辺の内容はそのうち書きます。

お騒がせしました><

masamasa 2007/10/10 19:35 かなり早くなってますね。使わせていただきます!

daidai 2007/10/10 23:26 いつも、javascriptが全く解らないですが、最近勉強したいと思い、私のレベルでは参考のsaにもなりませんが、なんだかamachangさんのテンションが好きでいつも見に来てしまいますw

さて、初心者過ぎて、申し訳ないご質問ですが、ぜひ今回のIEの対応したいのですが、いったいどこをどうすれば、いいのでしょうか?

インターネットオプションを開けるのか・・・それとも、どこかのフォルダから・・・全く持って初心者のご質問で申し訳ないですが、もし、万が一、テンションの隙間があるのならば、

教えていただけると嬉しいです!

griffin-stewiegriffin-stewie 2007/10/10 23:31 トラバ先のコメントでsecondlifeさんの「IEで高速なXPath/CSS 3 selector 実装(だと予想)」という発言を読んで、もしこの予想が本当だとすると願わくばSleipnirのUserJs(SeaHorse)でも使えるような感じだと非常にうれしいです(>_<)

dankogaidankogai 2007/10/11 00:11 英語で紹介してきました。

http://dankogai.vox.com/library/post/one-liner-that-accelerates-javascript-on-ie.html

でも、これってほんまかいな、という感じがします。IEのSymbol Tableの実装って爛れてる?

o.k.o.k. 2007/10/11 04:40 これはひどい!私事で恐縮なんですが、ここの所カゼと寝不足で疲れが溜まっていたんです。
それなのに、変な時間に目が醒めてしまい、少しWeb見てひと寝入りしようと思ってココを開いたのが間違い!
ガツンとやられて眠れなくなった!謝罪と賠償(ry
理屈は理解できたけど、ここまで効果があるとは思わなかったし、これだけ効果があると解っても、
こういう実現の仕方は思いつけなかったであろう自分に悔しさがこみあげてきた!
(実際ブクマでvbやってる人には云々なんて負け惜しみがついてるけどw)

ところで、グッとガッツポーズしただけで5エントリポストでおなじみのdankogaiによって海の向うに紹介されたみたいですが、
CSSのホーリーハックのような定着をしそうな予感がします。
amachangさんが、この技というか現象というか記述に名前をつけるとしたら何てつけますか?
(地球のどこかでは知っていたと言う人がいるかもしれませんが)事実上の1stエントリ者として、
命名してしまっていいし権利があるように思います。

なんて、書きながらも、副作用検証とか効果測定とかやってないので[あとでためす]状態だったりして。
もっとも、仮に深刻な副作用があって禁じ手になっても、[これはすごい]に変わりありませんね。

brazilbrazil 2007/10/11 08:46 ループコストを引いて計算すると、もっと速くなってるかも。

trshugutrshugu 2007/10/11 09:34

toteritoteri 2007/10/11 10:16 おおー。さすがです!

orzcccorzccc 2007/10/11 10:28 本題から逸れますが、「すべての JavaScript」って表現が奇妙に感じました。

通りすがり通りすがり 2007/10/11 13:08 document = document;
で良いのでは。

CraftworksCraftworks 2007/10/11 14:36 for (var i = 0, l = props.length; i < l; i++) {
カンマが抜けてました。

翼 2007/10/11 15:32 amachangさん、ちょっとわかんないんだけど、”document”オブジェクトにアクセス回数が少ないときはあっまり効果がないんだよね。

”document”を含めてグローバル変数は全部で何個ある?

taka.BRKtaka.BRK 2007/10/11 20:13 これは面白い発想ですね(^_^)。自分のサイトはIE7では結構重たい処理をさせていたから、この方法を使わせてもらったら、Firefox2で表示した時と同等以上に速く処理出来るようになりました。

kyorozaburokyorozaburo 2007/10/11 22:44 すげー。これはすげー。感動しました。

GreeGree 2007/10/12 03:09 こんにちは。どうすれば自分のパソコンで試せるのでしょうか?
初心者ですいません。

taslamtaslam 2007/10/12 10:16 ↑初心者は免罪符にはなりませんよ。
もっと勉強してきましょう。


WEB+DBPRESSの連載も読んでます。次回も楽しみにしてます。

ebiebi 2007/10/13 21:39 今度やってみます

mashikimashiki 2007/10/16 01:06 ちょっとびっくり

<script><!--
// Before
var date = new Date;
for (var i = 0; i < 100000; i++) document.getElementById;

alert(new Date - date); // 1187

/*@cc_on _d=document;eval(’var document=_d; var getEl=_d.getElementById;’);@*/

// After
date = new Date;
for (var i = 0; i < 100000; i++) getEl;

alert(new Date - date); // 46

//--></script>

wowsewowse 2008/03/05 17:45 /*@cc_on var document=eval(’document’);@*/
でもできました

wowsewowse 2008/03/05 17:56 すみません、上のやつ色々試してみたところ
document自体にはアクセスできてdocument.writeとかが使えなかったっぽい^^;

manaplusmanaplus 2011/01/21 10:20 IE9モードだと動かない・・・?
ベータ板だしそのうち直るかなぁ?

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/amachang/20071010/1192012056