HTML5 アプリのパフォーマンスを改善する

はじめに

HTML5 には、ウェブ アプリケーションの外観を強化するための優れたツールが用意されています。これは特にアニメーションに当てはまります。しかし、この新しい力には新しい課題も伴います。実は、こうした課題はさほど新しいものではなく、隣のデスクの Flash プログラマに、過去に同様の課題をどのように克服したかを尋ねてみるのもよいでしょう。

アニメーションを扱う場合は、ユーザーがアニメーションをスムーズに認識することが非常に重要になります。認識のしきい値を超えてフレームレートを増やすだけでは、アニメーションの滑らかさを実現することはできません。残念ながら、人間の脳はそれほど単純ではありません。30 フレーム/秒(fps)のアニメーションが真に 30 フレームであるほうが、途中で数フレームがドロップされる 60 fps よりもはるかに優れていることがわかります。ギザギザは嫌われる。

この記事では、独自のアプリケーションのエクスペリエンスを改善するためのツールと手法について説明します。

戦略

Google は、HTML5 で魅力的で視覚的に優れたアプリを作成することを決して否定するものではありません。

パフォーマンスをもう少し改善できると思われる場合は、このページに戻って、アプリの要素を改善する方法を確認してください。もちろん、最初から正しいことを行ううえで役立ちますが、生産性を損なう原因にならないようにしてください。

HTML5 による視覚的忠実度++

ハードウェア アクセラレーション

ハードウェア アクセラレーションは、ブラウザの全体的なレンダリング パフォーマンスにとって重要なマイルストーンです。一般的なスキームでは、メイン CPU によって計算されるタスクを、コンピュータのグラフィック アダプター内のグラフィック プロセッシング ユニット(GPU)にオフロードします。これにより、パフォーマンスが大幅に向上し、モバイル デバイスのリソース消費も削減できます。

ドキュメントのこれらの部分は GPU によって高速化できます。

  • 一般的なレイアウトの合成
  • CSS3 トランジション
  • CSS3 3D 変換
  • キャンバス描画
  • WebGL 3D 描画

キャンバスと WebGL の高速化は特殊な目的の機能であり、特定のアプリケーションには適用されない可能性がありますが、最初の 3 つの要素はほとんどすべてのアプリの高速化に役立ちます。

何を加速できるか

GPU アクセラレーションは、明確に定義された特定のタスクを専用ハードウェアにオフロードすることで機能します。一般的なスキームでは、ドキュメントが複数の「レイヤ」に分割され、ページの高速化対象の部分とは独立しています。これらのレイヤは、従来のレンダリング パイプラインを使用してレンダリングされます。その後、GPU を使用して、レイヤを 1 つのページに合成し、その場で高速化できる「効果」を適用します。たとえば、画面上でアニメーション化されるオブジェクトに対して、アニメーションの実行中にページの「再レイアウト」を 1 回も行わなくても済むようになります。

レンダリング エンジンが GPU アクセラレーションを適用できるタイミングを簡単に特定できるようにする必要があります。たとえば次のようになります。

ただし、ブラウザは、人間がスムーズなアニメーションと認識する動作をユーザーが行っていることを認識していません。代わりに CSS3 遷移を使用して同じ視覚効果を実現した場合、どうなるかを考えてみましょう。

ブラウザがこのアニメーションを実装する方法は、デベロッパーには完全に非公開です。つまり、ブラウザは GPU アクセラレーションなどの手法を適用して、定義された目標を達成できます。

GPU アクセラレーションのデバッグに役立つ Chrome のコマンドライン フラグは 2 つあります。

  1. --show-composited-layer-borders は、GPU レベルで操作されている要素の周囲に赤い枠線を表示します。GPU レイヤ内で操作が行われていることを確認するのに適しています。
  2. --show-paint-rects GPU 以外のすべての変更がペイントされ、再描画されたすべての領域の周囲に明るいボーダーが描画されます。ブラウザがペイント領域を最適化する様子を確認できます。

Safari には、こちらに記載されている同様のランタイム フラグがあります。

CSS3 トランジション

CSS 遷移を使用すると、誰でも簡単にスタイル アニメーションを作成できますが、パフォーマンスに優れた機能でもあります。CSS 遷移はブラウザによって管理されるため、アニメーションの忠実度を大幅に向上させることができ、多くの場合ハードウェア アクセラレーションを利用できます。現在、WebKit(Chrome、Safari、iOS)ではハードウェア アクセラレーションによる CSS 変換が使用されていますが、他のブラウザやプラットフォームにもまもなく対応する予定です。

transitionEnd イベントを使用して、これを強力な組み合わせにスクリプト化できますが、現時点では、サポートされているすべての遷移終了イベントをキャプチャするには webkitTransitionEnd transitionend oTransitionEnd を監視する必要があります。

多くのライブラリで、アニメーション API が導入されています。この API は、遷移が存在する場合は遷移を活用し、存在しない場合は標準の DOM スタイルのアニメーションにフォールバックします。scripty2YUI transitionjQuery animate enhanced など。

CSS3 変換

ページ上の要素の x/y 位置をアニメーション化したことは、これまでにもあると思います。インライン スタイルの left プロパティと top プロパティを操作した可能性があります。2D 変換では、translate() 機能を使用してこの動作を再現できます。

これを DOM アニメーションと組み合わせて、可能な限り最適なものを使用できます。

<div style="position:relative; height:120px;" class="hwaccel">

  <div style="padding:5px; width:100px; height:100px; background:papayaWhip;
              position:absolute;" id="box">
  </div>
</div>

<script>
document.querySelector('#box').addEventListener('click', moveIt, false);

function moveIt(evt) {
  var elem = evt.target;

  if (Modernizr.csstransforms && Modernizr.csstransitions) {
    // vendor prefixes omitted here for brevity
    elem.style.transition = 'all 3s ease-out';
    elem.style.transform = 'translateX(600px)';

  } else {
    // if an older browser, fall back to jQuery animate
    jQuery(elem).animate({ 'left': '600px'}, 3000);
  }
}
</script>

Modernizr を使用して CSS 2D 変換と CSS 遷移の機能テストを行い、対応している場合は translate を使用して位置を移動します。これが遷移を使用してアニメーション化されている場合、ブラウザでハードウェア アクセラレーションが使用される可能性があります。ブラウザを正しい方向にプッシュするために、上記の「魔法の CSS ブルート」を使用します。

ブラウザの機能が低い場合は、jQuery にフォールバックして要素を移動します。Louis-Remi Babe の jQuery Transform ポリフィル プラグインを使用すると、この処理をすべて自動化できます。

window.requestAnimationFrame

requestAnimationFrame は Mozilla によって導入され、アニメーションの実行にネイティブ API を提供することを目的として WebKit によって反復処理されました。アニメーションは、DOM/CSS ベースでも、<canvas> または WebGL でも実行できます。ブラウザは、同時実行アニメーションを 1 つの再フロー / 再描画サイクルにまとめて最適化できるため、忠実度の高いアニメーションを実現できます。たとえば、CSS 遷移や SVG SMIL と同期された JS ベースのアニメーションなどです。また、表示されていないタブでアニメーション ループを実行している場合、ブラウザはアニメーション ループを実行し続けません。これにより、CPU、GPU、メモリの使用量が削減され、バッテリー駆動時間が大幅に長くなります。

requestAnimationFrame の使用方法と使用理由について詳しくは、Paul Irish の記事「requestAnimationFrame によるスマートなアニメーション」をご覧ください。

プロファイリング

アプリケーションの速度を改善できることがわかったら、プロファイリングを詳しく調べて、最適化によって最大の効果が得られる部分を探します。最適化は、ソースコードの保守性に悪影響を及ぼすことが多いため、必要な場合にのみ適用する必要があります。プロファイリングでは、パフォーマンスを改善すると最も大きなメリットが得られるコード部分を特定できます。

JavaScript プロファイリング

JavaScript プロファイラは、各関数の開始から終了までの実行時間を測定して、JavaScript 関数レベルでアプリケーションのパフォーマンスの概要を把握します。

関数の総実行時間は、関数を上から下に実行するのにかかる全体的な時間です。正味の実行時間は、総実行時間から、関数から呼び出された関数の実行に要した時間を差し引いたものです。

関数によっては、呼び出される頻度が他の関数よりも高くなります。通常、プロファイラは、すべての呼び出しの実行に要した時間と、平均、最小、最大の実行時間を示します。

詳しくは、プロファイリングに関する Chrome DevTools のドキュメントをご覧ください。

DOM

JavaScript のパフォーマンスは、アプリケーションの流動性と応答性に大きな影響を与えます。JavaScript プロファイラは JavaScript の実行時間を測定しますが、DOM オペレーションに費やされた時間も間接的に測定します。多くの場合、パフォーマンスの問題の原因はこれらの DOM オペレーションにあります。

function drawArray(array) {
  for(var i = 0; i < array.length; i++) {
    document.getElementById('test').innerHTML += array[i]; // No good :(
  }
}

たとえば、上記のコードでは、実際の JavaScript の実行にほとんど時間がかかりません。ただし、drawArray 関数は DOM を非常に無駄な方法で操作しているため、プロファイルに表示される可能性は非常に高いです。

ヒントとアドバイス

匿名関数

匿名関数は、プロファイラに表示される名前がないため、プロファイリングが容易ではありません。これを回避するには、2 とおりの方法があります。

$('.stuff').each(function() { ... });

次のように書き換えます。

$('.stuff').each(function workOnStuff() { ... });

JavaScript で関数式に名前を付けられることは、あまり知られていません。これにより、プロファイラに正確に表示されます。この解決策には 1 つの問題があります。名前付き式は、実際に関数名を現在のレキシカル スコープに配置します。これにより他のシンボルが破壊される可能性があるため、注意してください。

長い関数のプロファイリング

長い関数があり、その一部がパフォーマンスの問題の原因となっている可能性があるとします。問題の部分を特定するには、次の 2 つの方法があります。

  1. 正しい方法: 長い関数を含まないようにコードをリファクタリングします。
  2. 悪魔的な「仕事をする」方法: 名前付き自己呼び出し関数の形式でステートメントをコードに追加します。注意深く行えば、セマンティクスは変更されず、関数の一部がプロファイラで個別の関数として表示されます。 js function myLongFunction() { ... (function doAPartOfTheWork() { ... })(); ... } プロファイリングが完了したら、これらの余分な関数を削除してください。また、コードをリファクタリングする出発点として使用することもできます。

DOM プロファイリング

最新の Chrome ウェブ インスペクタのデベロッパー ツールには、ブラウザによって実行された低レベル アクションのタイムラインを表示する新しい [タイムライン ビュー] が含まれています。この情報を使用して、DOM オペレーションを最適化できます。コードの実行中にブラウザが実行する必要がある「アクション」の数を減らすことを目標にする必要があります。

タイムライン ビューでは、膨大な量の情報が作成される可能性があります。そのため、個別に実行できる最小限のテストケースを作成する必要があります。

DOM プロファイリング

上の画像は、非常にシンプルなスクリプトのタイムライン ビューの出力を示しています。左側のパネルには、ブラウザによって実行されたオペレーションが時系列で表示されます。右側のパネルのタイムラインには、個々のオペレーションで実際に消費された時間が示されます。

タイムライン ビューの詳細Internet Explorer でのプロファイリングに使用できる別のツールとして、DynaTrace Ajax Edition があります。

プロファイリング戦略

アスペクトを特定する

アプリケーションをプロファイリングする際は、遅延の原因となる可能性のある機能の部分をできるだけ特定してください。次に、アプリケーションのこれらの側面に関連するコード部分のみを実行するプロファイル実行を試みます。これにより、実際の問題に関係のないコードパスとプロファイリング データが混在しなくなるため、プロファイリング データを解釈しやすくなります。アプリケーションの個々の側面の例としては、次のものがあります。

  1. 起動時間(プロファイラを有効にして、アプリを再読み込みし、初期化が完了するまで待ってから、プロファイラを停止します)。
  2. ボタンをクリックして、その後のアニメーション(プロファイラを開始、ボタンをクリック、アニメーションが完了するまで待機、プロファイラを停止)を実行します。
GUI プロファイリング

アプリケーションの適切な部分のみを実行することは、3D エンジンのレイト トレーサーを最適化するときよりも、GUI プログラムで難しい場合があります。たとえば、ボタンをクリックしたときに発生する処理をプロファイリングする場合、関連のないマウスオーバー イベントがトリガーされ、結果の信頼性が低下する可能性があります。このようなことがないようにしてください。

プログラマティック インターフェース

デバッガを有効にするプログラム インターフェースもあります。これにより、プロファイリングの開始と終了を正確に制御できます。

次のコマンドでプロファイリングを開始します。

console.profile()

プロファイリングを停止するには:

console.profileEnd()

反復性

プロファイリングを行う際は、結果を実際に再現できることを確認してください。最適化が実際に効果があったかどうかを判断できるのは、この段階になってからです。また、関数レベルのプロファイリングは、コンピュータ全体のコンテキストで行われます。科学的に厳密な手法ではありません。個々のプロファイルの実行は、パソコンで発生する他の多くの要因の影響を受ける可能性があります。

  1. 他の測定中に発生する、独自のアプリ内の無関係なタイマー。
  2. ガベージ コレクタが処理を行っている様子。
  3. ブラウザの別のタブが、同じオペレーティング スレッドで負荷の高い処理を行っている。
  4. パソコン上の別のプログラムが CPU を消費しているため、アプリケーションの動作が遅くなっています。
  5. 地球の重力場の急激な変化。

1 つのプロファイリング セッションで同じコードパスを複数回実行することも理にかなっています。これにより、上記の要因の影響が軽減され、遅い部分がよりはっきりと目立つようになります。

測定、改善、測定

プログラムの遅い部分を特定したら、実行動作を改善する方法を検討します。コードを変更したら、もう一度プロファイリングします。結果に満足したら、次のステップに進みます。改善が見られない場合、変更をロールバックし、「害はない」という理由でそのままにしておかないでください。

最適化戦略

DOM の操作を最小限に抑える

ウェブ クライアント アプリケーションの速度を改善するための一般的なテーマは、DOM の操作を最小限に抑えることです。JavaScript エンジンの速度は飛躍的に向上しましたが、DOM へのアクセス速度は同じペースで向上していません。また、非常に現実的な理由から、これは決して起こりません(画面上のレイアウトや描画には時間がかかります)。

DOM ノードをキャッシュに保存する

DOM からノードまたはノードのリストを取得するときは、後続の計算(または次のループの反復処理)で再利用できるかどうかを検討してください。関連する領域でノードを実際に追加または削除しない限り、これは多くの場合当てはまります。

プログラム開始前:

function getElements() {
  return $('.my-class');
}

申し込みの後:

var cachedElements;
function getElements() {
  if (cachedElements) {
    return cachedElements;
  }
  cachedElements = $('.my-class');
  return cachedElements;
}

属性値をキャッシュに保存する

DOM ノードをキャッシュに保存する方法と同様に、属性の値もキャッシュに保存できます。ノードのスタイルの属性をアニメーション化しているとします。その属性にアクセスするのは自分だけだとわかっている場合は、反復処理のたびに最後の値をキャッシュに保存して、繰り返し読み取る必要がなくなります。

プログラム開始前:

setInterval(function() {
  var ele = $('#element');
  var left = parseInt(ele.css('left'), 10);
  ele.css('left', (left + 5) + 'px');
}, 1000 / 30);

変更後: js var ele = $('#element'); var left = parseInt(ele.css('left'), 10); setInterval(function() { left += 5; ele.css('left', left + 'px'); }, 1000 / 30);

DOM 操作をループから移動する

ループは多くの場合、最適化のホットスポットです。実際の数値処理と DOM の操作を分離する方法を検討してください。多くの場合、計算を実行してから、計算が完了した後に、すべての結果を一度に適用できます。

プログラム開始前:

document.getElementById('target').innerHTML = '';
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  document.getElementById('target').innerHTML += val;
}

申し込みの後:

var stringBuilder = [];
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  stringBuilder.push(val);
}
document.getElementById('target').innerHTML = stringBuilder.join('');

再描画と再フロー

前述のように、DOM へのアクセスは比較的遅くなります。コードが DOM 内の関連する何かを最近変更したため、再計算が必要な値をコードが読み取っている場合、非常に遅くなります。したがって、DOM への読み取りアクセスと書き込みアクセスを混在させないようにする必要があります。理想的には、コードは常に次の 2 つのフェーズにグループ化する必要があります。

  • フェーズ 1: コードに必要な DOM 値を読み取る
  • フェーズ 2: DOM を変更する

次のようなパターンはプログラミングしないでください。

  • フェーズ 1: DOM 値を読み取る
  • フェーズ 2: DOM を変更する
  • フェーズ 3: 詳細を確認する
  • フェーズ 4: 別の場所で DOM を変更する。

プログラム開始前:

function paintSlow() {
  var left1 = $('#thing1').css('left');
  $('#otherThing1').css('left', left);
  var left2 = $('#thing2').css('left');
  $('#otherThing2').css('left', left);
}

申し込みの後:

function paintFast() {
  var left1 = $('#thing1').css('left');
  var left2 = $('#thing2').css('left');
  $('#otherThing1').css('left', left);
  $('#otherThing2').css('left', left);
}

このアドバイスは、1 つの JavaScript 実行コンテキスト内で発生するアクションについて検討する必要があります。(イベント ハンドラ内、インターバル ハンドラ内、ajax レスポンスの処理時など)。

上記の paintSlow() 関数を実行すると、次の画像が作成されます。

paintSlow()

高速な実装に切り替えると、次の画像が生成されます。

実装の高速化

これらの画像は、コードが DOM にアクセスする方法の順序を変更することで、レンダリング パフォーマンスを大幅に向上できることを示しています。この場合、元のコードは同じ結果を作成するために、スタイルの再計算とページのレイアウトを 2 回行う必要があります。同様の最適化は、基本的にすべての「現実世界」のコードに適用でき、非常に劇的な結果をもたらします。

詳細: レンダリング: 再描画、再フロー/再レイアウト、再スタイル(Stoyan Stefanov 著)

再描画とイベントループ

ブラウザでの JavaScript の実行は「イベントループ」モデルに従います。デフォルトでは、ブラウザは「アイドル」状態です。この状態は、ユーザー操作によるイベント、JavaScript タイマーや Ajax コールバックなどのイベントによって中断されることがあります。このような中断ポイントで JavaScript が実行されると、通常、ブラウザは画面の再描画までその完了を待機します(ただし、非常に長時間実行される JavaScript や、JavaScript の実行を効果的に中断するアラート ボックスなどの例外もあります)。

影響

  1. JavaScript アニメーション サイクルの実行に 1/30 秒を超える時間がかかると、JS の実行中にブラウザが再描画されないため、スムーズなアニメーションを作成できません。ユーザー イベントも処理する場合は、さらに高速にする必要があります。
  2. 一部の JavaScript アクションを少し遅らせると便利な場合があります。たとえば setTimeout(function() { ... }, 0) は、イベントループが再びアイドル状態になったらすぐにコールバックを実行するようにブラウザに指示します(一部のブラウザでは、少なくとも 10 ミリ秒待機します)。これにより、時間的に非常に近い 2 つの JavaScript 実行サイクルが作成されることに注意が必要です。どちらの場合も、画面の再ペイントがトリガーされ、ペイントにかかる全体的な時間が 2 倍になる可能性があります。実際に 2 回のペイントがトリガーされるかどうかは、ブラウザのヒューリスティクスによって異なります。

通常バージョン:

function paintFast() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  $('#otherThing2').css('height', '20px');
}
再描画とイベントループ

遅延を追加しましょう。

function paintALittleLater() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  setTimeout(function() {
    $('#otherThing2').css('height', '20px');
  }, 10)
}
遅延

遅延バージョンでは、ページの 2 つの変更が 100 分の 1 秒しか離れていないにもかかわらず、ブラウザが 2 回ペイントしていることがわかります。

遅延初期化

ユーザーは、読み込みが速く、応答性の高いウェブアプリを求めています。ただし、ユーザーが遅いと感じる時間は、ユーザーが行っている操作によって異なります。たとえば、マウスオーバー イベントで大量の計算を行うことは、ユーザーがマウスを動かし続けている間に悪いユーザー エクスペリエンスを生む可能性があるため、避けるべきです。ただし、ユーザーはボタンをクリックした後に少しの遅延を許容することに慣れています。

そのため、初期化コードをできるだけ遅く実行するように移動することをおすすめします(たとえば、ユーザーがアプリの特定のコンポーネントを有効にするボタンをクリックしたときなど)。

変更前: js var things = $('.ele > .other * div.className'); $('#button').click(function() { things.show() });

変更後: js $('#button').click(function() { $('.ele > .other * div.className').show() });

イベント委任

イベント ハンドラをページ全体に分散すると、比較的時間がかかり、要素が動的に置き換えられたときにイベント ハンドラを新しい要素に再びアタッチする必要があるため、手間もかかります。

この場合の解決策は、イベント委任という手法を使用することです。個々のイベント ハンドラを要素に接続するのではなく、多くのブラウザ イベントのバブルリング特性を使用して、イベント ハンドラを親ノードに接続し、イベントのターゲット ノードをチェックして、イベントが対象かどうかを確認します。

jQuery では、次のように簡単に記述できます。

$('#parentNode').delegate('.button', 'click', function() { ... });

イベント委任を使用すべきでない場合

イベント委任を使用しているにもかかわらず、パフォーマンスの問題が発生している場合もあります。基本的に、イベント委任により、複雑さが変わらない初期化時間を実現できます。ただし、イベントが興味深いものかどうかを確認する費用は、そのイベントの呼び出しごとに支払う必要があります。特に「mouseover」や「mousemove」など、頻繁に発生するイベントでは、費用が高くなる可能性があります。

一般的な問題と解決策

$(document).ready で行う操作に時間がかかります

Malte の個人的なアドバイス: $(document).ready で何もしないでください。最終的な形でドキュメントを提出してください。イベント リスナーを登録することはできますが、id セレクタまたはイベント委任を使用してのみ登録できます。「mousemove」などの負荷の高いイベントの場合は、必要になるまで(関連する要素の mouseover イベント)登録を遅らせます。

実際のデータを取得するために Ajax リクエストを行うなど、本当に何かを行う必要がある場合は、アニメーションを表示します。アニメーション GIF などの場合は、アニメーションをデータ URI として含める必要があります。

ページに Flash ムービーを追加してから、動作が非常に遅くなりました

ページに Flash を追加すると、ブラウザと Flash プラグイン間でウィンドウの最終的なレイアウトを「ネゴシエート」する必要があるため、レンダリングが常に少し遅くなります。ページに Flash を配置しないように完全にはできない場合は、Flash パラメータ「wmode」を「window」(デフォルト)に設定してください。これにより、HTML 要素と Flash 要素の合成が無効になります(Flash ムービーの上に重なる HTML 要素は表示されず、Flash ムービーを透明にすることもできません)。ご不便をおかけしますが、これによりパフォーマンスが大幅に向上します。たとえば、youtube.com では、メインの映画プレーヤーの上にレイヤを配置しないように注意しています。

localStorage にデータを保存すると、アプリケーションが途切れる

localStorage への書き込みは、ハードディスクの起動を伴う同期オペレーションです。アニメーションの実行中に「長時間実行」の同期オペレーションを行うことは避けてください。localStorage へのアクセスを、ユーザーがアイドル状態にあり、アニメーションが実行されていないことを確認できるコードの場所に移動します。

プロファイリングで、jQuery セレクタの処理速度が非常に遅いことがわかった

まず、セレクタを document.querySelectorAll で実行できることを確認します。これは JavaScript コンソールでテストできます。例外がある場合は、JavaScript フレームワークの特別な拡張機能を使用しないようにセレクタを書き換えます。これにより、最新のブラウザでセレクタの速度が大幅に向上します。

それでも問題が解決しない場合や、最新のブラウザでも高速化したい場合は、次のガイドラインに沿って対応してください。

  • セレクタの右側はできる限り具体的に記入してください。
  • 右端のセレクタ部分には、あまり使用しないタグ名を使用します。
  • 上記の方法で問題が解決しない場合は、id セレクタを使用できるように書き換えることを検討してください。

これらの DOM 操作はすべて時間がかかります。

DOM ノードの挿入、削除、更新を大量に行うと、非常に遅くなる可能性があります。通常、これは、大きな HTML 文字列を生成し、domNode.innerHTML = newHTML を使用して古いコンテンツを置き換えることで最適化できます。ただし、これはメンテナンス性に悪影響を及ぼし、IE でメモリリンクを作成してしまう可能性があるため、注意が必要です。

初期化コードで大量の HTML が作成されるという問題もよく発生します。たとえば、UX のベスト プラクティスを無視して、デザイン担当者が望んだため、選択ボックスを多数の div に変換する jQuery プラグインなどです。ページの速度を本当に重視する場合は、絶対にそうしないでください。代わりに、すべてのマークアップをサーバーサイドから最終的な形式で配信します。これにも多くの問題があるため、速度がトレードオフに値するかどうかをよく検討してください。

ツール

  1. JSPerf - JavaScript の小さなスニペットをベンチマークする
  2. Firebug - Firefox でのプロファイリング用
  3. Google Chrome デベロッパー ツール(Safari では WebInspector として利用可能)
  4. DOM Monster - DOM のパフォーマンスを最適化
  5. DynaTrace Ajax Edition - Internet Explorer のプロファイリングとペイントの最適化用

関連情報

  1. Google Speed
  2. Paul Irish による jQuery のパフォーマンスに関する記事
  3. Extreme JavaScript Performance(スライド資料)