13

こんにちは私はスマートフォンとデスクトップブラウザの両方で実行できるWebappを持っています。私はiPhoneのような小さなデバイスで好奇心をそそる行動を期待していましたが、私は現時点でテストを実行できるAndroidデバイスであるAndroid Galaxy Tabでうまくいくと自信がありました。今、私は物事をテストするためにギャラクシータブ上でブラウザの束をインストールしている一部のモバイルブラウザではHTML5 Canvasのパフォーマンスに問題があります。

  • Androidのネイティブブラウザ
  • アンドロイド
  • のFirefoxのAndroid
  • ため

用クローム私が使ったデスクトップ

  • Firefoxの
  • Google Chromeの

、最終的に私がしてテストするためのiPhoneを持っています。

ウェブサイトでは、ピクセルやスプライトをベースにした描画にHTML5キャンバスが使用されています。ファンシー変換、フィルタやエフェクトはほとんどなく、単純なパスやポリゴンです。タッチイベントを聞いて、適切に再描画するには​​を使用します。

全体的に、このアプリケーションはデスクトップブラウザ上でうまく動作し、iOS Safari(iPhone)やAndroid搭載のFirefoxでも大きく動作します。しかし、アンドロイドネイティブブラウザは私にトラブルを与えています。私は、javascriptが応答しないときに画面が赤くなるように設定しています。画面に触れるとほぼ常にフラッシュします。

Android Native AppとHTML5の既知の問題があるかどうかは疑問です。ネイティブブラウザの存在しない名前のため、これに関するGoogleの情報にはかなり難しい。 私に詳しいアイデアはどこにありますか?ネイティブAndroidブラウザの遅れを引き起こす可能性のあるアイデアはありますか?

問題についていくつかのアイデアがあります

  • のiOSは、したがって、私は、タイムアウトベースの代替に置き換え、requestAnimationFrameのをサポートしていません。 Androidのネイティブブラウザでその置換を使用すると、問題は解決しません。

  • 私はかなり定期的にAJAX(google clojure xhrio)を使用してサーバーからデータを取得します。データ取得のコールバックがイベントパイプラインを詰まらせることがありますか?

  • アプリケーションの速度を低下させるログコンソールメッセージ(console.log)はありますか? DOMツリーや何か関連するものを通してブラウザを再起動させることができますか?

+2

私はあなたの実際の質問に答えることはできませんが、コンソールを使用すると、使用方法によってはかなりの量のメモリを消費する可能性があります。特に大きなオブジェクトをロギングしたり、非常に頻繁にロギングしている場合は特にそうです。 – idbehold

答えて

42

私は多くのブラウザでキャンバスを使用して多くの実験を行いました。

まず、あなたの推測について:私は気づいたいくつかのパフォーマンスの問題

  • を​​は、ブラウザでサポートされている場合は、描画のものとアプリ自体は、より応答性です。フォールバックとしてsetTimeoutまたはsetIntervalを使用することは常に可能ですが、タイミングについて注意する必要があります。このrobust polyfillはほんの少し役に立ちますが、ネイティブのrequestAnimationFrameと比べて何も役に立ちません。

  • console.logがすべてのフレーム(またはほとんど)で呼び出された場合、パフォーマンスは低下します。 ネイティブAndroidブラウザにはコンソールオブジェクトがないため、呼び出されるたびにエラーが生成され、アプリケーションの速度が低下します。あなたはこれを行うことができます。

    if(typeof console === "undefined"){ console = {}; }強烈なリアルタイムアプリケーションweb socketsについては

  • は、より高速なHTTPリクエスト、その後です。残念ながら、この機能は古いアンドロイドブラウザではサポートされていません。 Webソケットを使用できない場合は、http要求を最小限に抑える必要があります。

注:アンドロイドのサポートのためのChrome HTML5の機能のほとんどは​​とwebsocketsを含め、ここに引用しました。

詳細情報:それはあまりにも高価だが、一部のブラウザでは、これはさらに悪くなるfillText 2Dコンテキストを使用してテキストを描画

  • 。テキストを別のキャンバスに事前レンダリングするか、ビットマップフォントを使用します。 (ネイティブのAndroidブラウザでは、プレレンダリング用のfilltext図面を置き換えた後、私が作ったいくつかのゲームでは、パフォーマンスは10-15FPSから30-45FPSに増加しました)。

  • パフォーマンスが低下する原因となるため、スケールと回転を避けてください。スプライトを1回だけスケールまたは回転する必要がある場合は、事前レンダリングも使用します。

  • リアルタイム描画を最小限に抑える必要があります。あなたができる限りいつでもあなたのものをプレレンダリングしてください。変更されたものだけを再描画し、更新する必要があります。

  • memory efficientとガベージコレクタフレンドリなコードを記述してください。

さらに多くのことがあります。私はちょうどいくつかを引用した。

ヒント:パフォーマンスキラーであるかどうかわからない機能のストレステストを実施し、ベンチマーク結果をキャプチャします。

モバイルアプリケーションでは、特にリアルタイムのアプリケーションでは、最適化を超えてメモリを増やすだけであれば、すべての最適化は歓迎されません。

詳細については以下のリンクに従ってください。

はまたPosts & Tutorialsのパフォーマンスを検索します。このjsfiddle code snippet

EDIT
は、いくつかのものは、この答えで覆われ、ベンチマークにラフfpsのカウンタを提供示しています。このフィドルをあなた自身で編集してチェックしてください。

+4

本当に有益で洞察力のある答えです。非常に高く評価されました;) – wirrbel

+0

プレレンダリングに追加のキャンバス画像を使用する場合、その内容がクリップされていないことを確認してください。テキストを回転させるときこの場合、プレレンダーキャンバスのコンテンツを翻訳し、drawImageを使用してキャンバスを使用して戻すことができます。 'preRenderCtx.translate(100、100); preRenderCtx.rotate(rotation); preRenderCtx.fillText(char、0、0); context.drawImage(preRenderCanvas、x-100、y-100); ' –

0

Html5キャンバスで最も一般的なパフォーマンス向上戦略は、レイヤー(つまり複数のキャンバス)を使用して、各アニメーションフレームで全体を再描画するのではなく、再描画が必要なレイヤーのみを更新することです。あなた自身がこのようなものを巻くことができます。あるいは、ヒット検知、レイヤリング、キャッシュ、ピクセル比率サポート、ダウンロードなどの周辺機能を可能にする軽量のHtml5キャンバスフレームワークであるなどを使用できます。

var wrapper = new Concrete.Wrapper({ 
    width: 500, 
    height: 300, 
    container: el 
}); 

var layer1 = new Concrete.Layer(); 
var layer2 = new Concrete.Layer(); 

wrapper.add(layer1).add(layer2); 

// something happens which requires you to redraw layer2, but not layer1... 
layer2.sceneCanvas.context.fillStyle = 'red'; 
layer2.sceneCanvas.context.fillRect(0, 0, 200, 100); 
関連する問題