速度テストまたはテストを作成しない方法について



最近、HTML5 Canvasでポストテストブラウザーのパフォーマンスを見ました。 その結果、IE9は350+ fpsというおかしな数字を見せ始めました。



これはもちろん良いことですが、何らかの理由で、他のjavascriptおよびcanvasテストでパフォーマンスが低下することはありませんでした。このテストでは、Windowsでの起動を条件として、何度も(時には数十回)低fpsを示しましたプラットフォームですが、それについては後で説明します)。



猫の下で、テストでHTML5-Canvasの速度がまったく表示されない理由を示します。最後に、PhotoshopなしでFF4の470 fpsの画面が表示されます。まず、このテストの正確な問題を分析します。





まず、200 fpsがどの程度かを見てみましょう。 これは毎秒200枚の図面です。 つまり 描画イベントは約5ミリ秒ごとに発生するはずです。 テストコードを見ると、実際には次の行があります。

setInterval(moveIt,1);
      
      





実際、「moveIt」は、仕様( WhatWGW3C )から判断して1msごとに実行する必要があります。 ただし、ハンドラーを呼び出す必要がある最小時間などはありません。



そして、ブラウザのイベントキューの実装機能が有効になります。 setTimeoutの最小精度を示すはずの興味深いテストがあります。 Chromeでは4ミリ秒でしたが、FF4では明らかに10ミリ秒でした。 おそらくこれは、Windowsシステム用のタイマーを使用する場合の粒度が高いためです(高性能カウンターやマルチメディア拡張機能を使用しない)(最後に結果のサインがあります)。



したがって、このトピックの目的は、setTimeout実装の機能について説明することではなく、特定の操作のパフォーマンスを実際に測定する方法を説明することです。 これまで見てきたように、setTimeoutは適切ではありません(「まだ適切でない」場合がありますか?)-任意のタスクでブラウザを完全にロードすることはできません。



ユーザーには何も表示されないため、タイムアウトなしで(つまり、ループで操作を実行するだけでは)不可能です。操作の結果を表示する時間をブラウザに与える必要があります。



この問題の可能な解決策はDavin Baronによって公開されました :window.postMessage( WhatWGW3CMSDN )を使用します。 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の元の「テスト」の速度も向上します)。 元のテストのようなその巨大な違いは、私にはわかりません。



結果として、私は一つのことを言います:曲がったテストは、結果を数十回または数百回「装飾する」ことができます。



All Articles