最近、HTML5 Canvasでポストテストブラウザーのパフォーマンスを見ました。 その結果、IE9は350+ fpsというおかしな数字を見せ始めました。
これはもちろん良いことですが、何らかの理由で、他のjavascriptおよびcanvasテストでパフォーマンスが低下することはありませんでした。このテストでは、Windowsでの起動を条件として、何度も(時には数十回)低fpsを示しましたプラットフォームですが、それについては後で説明します)。
猫の下で、テストでHTML5-Canvasの速度がまったく表示されない理由を示します。最後に、PhotoshopなしでFF4の470 fpsの画面が表示されます。まず、このテストの正確な問題を分析します。
まず、200 fpsがどの程度かを見てみましょう。 これは毎秒200枚の図面です。 つまり 描画イベントは約5ミリ秒ごとに発生するはずです。 テストコードを見ると、実際には次の行があります。
setInterval(moveIt,1);
実際、「moveIt」は、仕様( WhatWG 、 W3C )から判断して1msごとに実行する必要があります。 ただし、ハンドラーを呼び出す必要がある最小時間などはありません。
そして、ブラウザのイベントキューの実装機能が有効になります。 setTimeoutの最小精度を示すはずの興味深いテストがあります。 Chromeでは4ミリ秒でしたが、FF4では明らかに10ミリ秒でした。 おそらくこれは、Windowsシステム用のタイマーを使用する場合の粒度が高いためです(高性能カウンターやマルチメディア拡張機能を使用しない)(最後に結果のサインがあります)。
したがって、このトピックの目的は、setTimeout実装の機能について説明することではなく、特定の操作のパフォーマンスを実際に測定する方法を説明することです。 これまで見てきたように、setTimeoutは適切ではありません(「まだ適切でない」場合がありますか?)-任意のタスクでブラウザを完全にロードすることはできません。
ユーザーには何も表示されないため、タイムアウトなしで(つまり、ループで操作を実行するだけでは)不可能です。操作の結果を表示する時間をブラウザに与える必要があります。
この問題の可能な解決策はDavin Baronによって公開されました :window.postMessage( WhatWG 、 W3C 、 MSDN )を使用します。 setTimeoutの類似物を実装しているが、遅延は最小限(できればゼロ)であるコード(setIntervalの類似物を追加してDavidのコードを修正しました(fn.applyが必要な場合は修正してください)):
// Only add setZeroTimeout to the window object, and hide everything // else in a closure. (function() { var timeouts = []; var messageName = "zero-timeout-message"; // Like setTimeout, but only takes a function argument. There's // no time argument (always zero) and no arguments (you have to // use a closure). function setZeroTimeout(fn) { timeouts.push(fn); window.postMessage(messageName, "*"); } function intervalHelper(fn) { var h = function() { fn(); setZeroTimeout(h); }; return h; } function setZeroInterval(fn) { setZeroTimeout(intervalHelper(fn)); } function handleMessage(event) { if (event.source == window && event.data == messageName) { event.stopPropagation(); if (timeouts.length> 0) { var fn = timeouts.shift(); fn(); } } } window.addEventListener("message", handleMessage, true); // Add the one thing we want added to the window object. window.setZeroTimeout = setZeroTimeout; window.setZeroInterval = setZeroInterval; })();
違いは非常に大きい( demo ):
100 iterations of setZeroTimeout took 19 milliseconds. 100 iterations of setTimeout(0) took 393 milliseconds.
この最小限の変更により、Firefox4およびDirect2D / DirectWriteが有効になっている場合のヘッダーにスクリーンショットが表示されます( 約:supportで確認できます)。
次に、変更が適用されたHTML5-Canvasの「テスト」タイプを示します。
Google Chromeについて一言:Windows以外のプラットフォームでは、あまり強くないマシンでも、このテストで200 fpsを超えることがよくあります(ハードウェア出力アクセラレーションが有効になっている場合)。 Windowsでは、60 fpsのVSync制限に基づいています。 それについての問題があり、星を付けることで投票できます。
フラグを確認することを忘れないでください-GPU Accelerated Compositing / GPU Accelerated Canvas 2Dがあります。
おわりに
テスト/ベンチマークを作成するときに、あるブラウザーが不可解なほど大きな違いを示した場合、このブラウザーがメガスーパー最適化されていると誤って考え始めないでください。 おそらく、テストは見た目ではなくテストです。 たとえば、理論上はHTML5-Canvasの速度を示すはずのテストでは、実際にsetTimeoutの実装機能を示し、VSyncを有効/無効にします。
PPS このテストの完全な曲率を表示するには、パッチでFF4のテストを開き、別のタブにタブを移動して(ほぼすぐに)、15〜20秒後に戻ります。約400 fpsでゆっくり倒れました。 証明
一般に、テストを公開する前に、テストが適切に行われるかどうか、また、数字で美しい絵を描くだけでなく、適切なテストを行うかどうかを確認します。
最小setTimeout遅延
コメントを収集した後、 テスト結果の表を作成しました。
Opera 11(Win) | 2 |
Chrome 10-11(Win) | 4 |
Firefox(Win) | 10 |
Safari、OS X 10.6.6 | 10 |
iPhone | 10 |
IE 8 | 15.6 |
コメントが利用可能になり次第、補充します。
この点に関して、WhatWG / W3CからのHTML5の推奨によると、setTimeout / setIntervalは次のように機能することに注意してください。
setInterval()メソッドは、次の手順を実行する必要があります。
5.タイムアウトが10未満の場合、タイムアウトを10に増やします
setTimeout()メソッドは、次の手順を実行する必要があります。
5.現在実行中のタスクがsetTimeout()メソッドによって作成されたタスクであり、タイムアウトが4未満の場合、タイムアウトを4に増やします。
つまり setTimeoutの場合は4ミリ秒未満、setIntervalの場合は10ミリ秒未満である必要があります。 これは、「オリジナル」テストが100 fpsを超えるブラウザーで明確なエラーを示しています(setIntervalを使用しているため)。 250 fps-setTimeoutを使用する場合の最大値。
更新:
テストのコピーを作成しました。このテストでは、ポリゴンの数を増やしました(球体では最大72セグメントと文字を30回)。
これで結果が得られました(Windows7 SP1 x64、nVidia gtx 260、Core Quad 2.4ghz):
Chrome 12.0.703.0 Canary Build | 33 fps |
IE 9.0.8112.16421 | 26 fps |
Firefox 4.0 | 58 fps |
「シャープ」などはなし しませんでした(setZeroTimeoutを除くと、IE9の元の「テスト」の速度も向上します)。 元のテストのようなその巨大な違いは、私にはわかりません。
結果として、私は一つのことを言います:曲がったテストは、結果を数十回または数百回「装飾する」ことができます。