Microsoft の開発サイクルの重要な部分は、製品のパフォーマンスを調整することです。パフォーマンスのチューニングも、開発者が注意を払うべき重要な領域の 1 つです。 長年の開発を経て、業界は Win32 プログラムのパフォーマンスを最適化する方法について多くのことを学びました。
開発者が現在直面している問題の 1 つは、DTHML ページと HTML ページの実行が速いまたは遅い原因が何なのかをよく理解していないことです。もちろん、2MB の画像を使用しないなど、いくつかの簡単な解決策はあります。 DHTML ページのパフォーマンスを向上させるために、他にもいくつかの興味深いテクニックを使用しました。これらのテクニックが、皆さんのページのパフォーマンス向上に役立つことを願っています。
ここでは、テーブルを作成するプログラムの例を使用します。 document.createElement() メソッドと element.insertBefore() メソッドは、1000 行 (Row) を持つテーブルを作成するために使用されます。各行には 1 つの列 (セル) があります。セルに含まれる内容を「テキスト」と呼びます。このコードはどれほどひどいものでしょうか?このような小さなプログラムにはどれくらい調整の余地があるでしょうか?紹介文をご覧ください。
最初は、変数を明示的に定義しないことや、1 つのページで VBScript と JavaScript を同時に使用することなど、いくつかの低レベルの問題を回避しようとして、高速だと思われるプログラムを作成しました。プログラムは次のとおりです。
<html>
<本文>
<スクリプト>
var tbl、tbody、tr、td、テキスト、i、max;
最大 = 1000;
tbl = document.createElement("TABLE");
tbl.border = "1";
tbody = document.createElement("TBODY");
tbl.insertBefore(tbody, null);
document.body.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = document.createElement("TR");
td = document.createElement("TD");
text = document.createTextNode("テキスト");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
このプログラムは、PII233/64MB メモリ/NT4.0/IE5.0 マシン上で実行します。ページはこのマシンからロードされます。ページの読み込みを開始してからページが完全に静まる (すべてのイベントが実行され、画面表示が完了する) までの時間は 2328 ミリ秒で、これはこのテストのベースラインでもあります (これを Test1 と呼びます)。
このページでは、「ドキュメント」、「ボディ」、「ウィンドウ」などのグローバル オブジェクトを頻繁に参照するため、非常に時間のかかる操作が行われます。これらの類似したグローバル変数をすべて参照すると、1 つのローカル変数を参照するよりもはるかにコストが高くなります。
そこで私は最初の改善を試みました。 document.body をローカル変数 "theBody" にキャッシュ (キャッシュ) し、
次のコードを追加しました
。
次に、次の行を変更します。
document.body.insertBefore(tbl, null);
これを次のように変更します。
theBody.insertBefore(tbl, null);
2 番目のサンプルを参照してください。
この変更は全体の時間に大きな影響を与えず、3 ミリ秒だけ短縮されました。しかし、ループ内に document.body オブジェクトがあり、その参照が変更された場合、大きなメリットが得られることがわかっています。
その後、ドキュメント オブジェクトをキャッシュしました。テストでは、ドキュメント オブジェクトは合計 3002 回参照されました。変更されたコードは次のとおりです:
<html>
<本文>
<スクリプト>
var tbl、tbody、tr、td、テキスト、i、max;
最大 = 1000;
var theDoc = ドキュメント;
var theBody = theDoc.body
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("テキスト");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
</script>
</body>
</html>
3 番目のサンプルをご覧ください。
この実行時間はわずか 2100 ミリ秒であり、時間を約 10% 節約できます。ドキュメント オブジェクトを直接参照する代わりにローカル変数を使用すると、毎回平均 0.4 ミリ秒が節約されました。
パフォーマンスを最適化する一般的な方法は、スクリプトをすぐに実行する必要がない場合に、<SCRIPT> タグに「defer」属性を設定することです。 (即時スクリプトはファンクション ブロックに含まれていないため、読み込みプロセス中に実行されます。) 「defer」属性を設定した後、IE はスクリプトが読み込まれて実行されるのを待つ必要がありません。こうすることで、ページの読み込みが速くなります。一般に、これは、即時スクリプトが関数ブロックに配置され、ドキュメントまたは本文オブジェクトの onload ハンドラーで関数を処理するのが最適であることも意味します。このプロパティは、ボタンをクリックしたりマウスを特定の領域に移動したりするなど、ユーザーのアクションに基づいて実行する必要があるスクリプトがある場合に役立ちます。ただし、ページの読み込み中または読み込み後に実行する必要があるスクリプトがいくつかある場合、defer 属性を使用するメリットはあまり大きくありません。
以下は、defer 属性を使用したコードの修正バージョンです:
<html>
<body onload="init()">
<スクリプトの延期>
関数 init() {
var tbl、tbody、tr、td、テキスト、i、max;
最大 = 1000;
var theDoc = ドキュメント;
var theBody = theDoc.body
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("テキスト");
td.insertBefore(text, null);
tr.insertBefore(td, null);
tbody.insertBefore(tr, null);
}
}
</script>
</body>
</html>
4 番目のサンプルを表示します。
このテストの時間は 2043 ミリ秒です。これはベースライン テストと比較して 12% 増加し、前回のテストよりも 2.5% 増加しました。
以下で説明する改善方法は、もちろん非常に便利ですが、少し面倒です。要素を作成してツリー状の構造に挿入する必要がある場合は、最初に要素を大きなサブツリーに挿入してからその大きなサブツリーをトランクに挿入するよりも、要素をトランクに直接挿入する方が効率的です。たとえば、各行に 1 つの列があり、その列にテキストが含まれるテーブルを作成する場合、次の操作を行うことができます。
1. <TR> を作成する
2. <TD> を作成する
3. TextNode ノードを作成する
4. TextNode を <TD に挿入する>
5. <TR> に <TD> を挿入
6. TBODY に <TR> を挿入
以下の方法より遅い場合:
1. <TR> を作成
2. <TD> を作成
3. TextNode を作成
4. <TR > を挿入TBODY に挿入
5. <TR> に <TD> を挿入
6. <TD> に TextNode を挿入
上記 4 つのテストはすべて前者の方法を使用しています。 5 回目のテストでは後者の方法を使用しました。コードは次のとおりです:
<html>
<body onload="init()">
<スクリプトの延期>
関数 init() {
var tbl、tbody、tr、td、テキスト、i、max;
最大 = 1000;
var theDoc = ドキュメント;
var theBody = theDoc.body
tbl = theDoc.createElement("TABLE");
tbl.border = "1";
tbody = theDoc.createElement("TBODY");
tbl.insertBefore(tbody, null);
theBody.insertBefore(tbl, null);
for (i=0; i<max; i++) {
tr = theDoc.createElement("TR");
td = theDoc.createElement("TD");
text = theDoc.createTextNode("テキスト");
tbody.insertBefore(tr, null);
tr.insertBefore(td, null);
td.insertBefore(text, null);
}
}
</script>
</body>
</html>
5 番目のサンプルを表示すると、
Test5 には 1649 ミリ秒しかかかりません。これは、前回のテストより 25% 改善され、ベースラインよりもほぼ 30% 速くなりました。
その後の変更は、事前に作成されたスタイルシートを使用して行われました。事前に作成されたスタイル シートを使用するか、<COL> タグによって設定されるテーブルの列幅。<COL> タグがない場合、各列の幅は均等に分散されます。各列のサイズなどを再計算する必要がないため、特にテーブル内の列数が多い場合、スタイル シートを使用するとパフォーマンスが向上します。
スタイル シート (CSS) を追加するコードは、次のように非常に簡単です
。
6 番目のサンプルを表示します。
テストのテーブルには列が 1 つしかなかったので、この変更によりページのパフォーマンスが 1.6% 向上しただけです。列の数が増えると、パフォーマンスの向上はさらに大きくなります。
最後の 2 つのテストでは、テーブルにテキストを挿入する方法が変更されました。前のテストでは、最初に TextNode を作成し、それを TD に挿入しました。 Test7 では、代わりに、innerText を介して含まれるテキストを指定します。変更されたコードは次のとおりです。
td.innerText = "Text";
7 番目のサンプルをご覧ください。
驚くべきことに、この変更による違いは大きく、前回と比べてパフォーマンスが 9% 向上し、元のサンプルと比べて合計で 36% のパフォーマンスが向上しました。時間の範囲は最初の 2323 ミリ秒から最後の 1473 ミリ秒です。
element.innerHTML の使用が非常に遅いことはほとんどの人が知っています。それがどれほど遅いかを確認するために、最後のテストとして、innerText の代わりに innerHTML を使用してテキストを挿入しました。これにより、パフォーマンスが大幅に低下します。時間は 3375 ミリ秒に達し、前回のテストより 80%、ベースライン テストより 45% 遅くなりました。明らかに、innerHTML は非常に時間がかかります。
HTML ページのパフォーマンスのチューニングは、Win32 アプリケーションのパフォーマンスのチューニングと似ています。何が遅いのか、何が速いのかを知る必要があります。これらの方法がページのパフォーマンスの向上に役立つことを願っています。