it-swarm.com.de

Leistungsprobleme mit HTML5 Canvas in einigen mobilen Browsern.

Hallo, ich habe eine Webapp, die sowohl auf Smartphone- als auch auf Desktop-Browsern ausgeführt werden kann. Während ich erwartet hatte, auf kleinen Geräten wie dem iPhone merkwürdiges Verhalten zu zeigen, war ich ziemlich zuversichtlich, dass es auf einem Android Galaxy Tab, dem Android-Gerät, mit dem ich momentan Tests durchführen kann, gut laufen würde.

Jetzt habe ich eine Reihe von Browsern auf dem Galaxy Tab installiert, um Dinge zu testen mit:

  • Nativer Android-Browser
  • Chrome für Android
  • Firefox für Android

Auf dem Desktop habe ich benutzt

  • Feuerfuchs
  • Google Chrome

und endlich habe ich ein iphone zum testen.

Die Website verwendet HTML5-Canvas für pixel- und spritebasierte Zeichnungen, ohne ausgefallene Transformationen, Filter oder Effekte, meist einfache Pfade und Polygone. Ich höre auf Berührungsereignisse und verwende requestAnimationFrame für das richtige Neuzeichnen.

Insgesamt läuft die Anwendung gut auf Desktop-Browsern, aber auch auf iOS Safari (iPhone) und Firefox-on-Android. Trotzdem macht mir Androids Native Browser Probleme. Ich habe es so eingestellt, dass der Bildschirm rot wird, wenn das Javascript nicht reagiert, und er blinkt fast immer, wenn Sie den Bildschirm berühren.

Daher frage ich mich, ob es bekannte Probleme mit Android Native App und HTML5 gibt. Aufgrund des nicht existierenden Namens des nativen Browsers ist es ziemlich schwierig, Informationen darüber zu googeln. Irgendwelche Ideen für mich, wo ich mehr Informationen bekommen kann? Irgendwelche Ideen, was die Verzögerung des nativen Android-Browsers verursachen könnte?

Es gibt ein paar Ideen zu diesem Thema:

  • iOS unterstützt requestAnimationFrame nicht, daher habe ich es durch ein Timeout-basiertes Ersatzprogramm ersetzt. Wenn ich diesen Ersatz im nativen Browser von Android verwende, bleibt das Problem bestehen.

  • Ich benutze AJAX (google clojure xhrio) ziemlich regelmäßig, um Daten vom Server abzurufen. Könnte es sein, dass Datenabruf-Rückrufe meine Ereignis-Pipeline verstopfen?

  • Ist bekannt, dass Protokollkonsolenmeldungen (console.log) Anwendungen verlangsamen? Könnten sie dazu führen, dass der Browser den DOM-Baum erneut durchläuft, oder ähnliches?

13
wirrbel

Ich habe in vielen Browsern viele Experimente mit Canvas durchgeführt. Einige Leistungsprobleme, die mir aufgefallen sind:

Zunächst zu Ihrer Vermutung:

  • Wenn requestAnimationFrame von einem Browser unterstützt wird, reagieren das Zeichenmaterial und die App selbst schneller. Verwenden Sie setTimeout oder setInterval, da ein Fallback immer möglich ist, aber Sie müssen vorsichtig mit dem Timing umgehen. Diese robuste Polyfill kann ein wenig helfen, aber nichts im Vergleich zu nativen requestAnimationFrame.

  • Wenn console.log für jeden Frame (oder fast) aufgerufen wird, sinkt die Leistung. Da der native Android-Browser kein Konsolenobjekt hat, wird bei jedem Aufruf ein Fehler generiert, der auch zur Verlangsamung Ihrer Anwendung beiträgt. Du kannst das:

    if(typeof console === "undefined"){ console = {}; }

  • Bei intensiven Echtzeitanwendungen sind Web-Sockets schneller als http-Anforderungen. Leider wird diese Funktion von alten nativen Android-Browsern nicht unterstützt. Wenn es nicht möglich ist, Web-Sockets zu verwenden, sollten Sie die HTTP-Anforderungen minimieren.

Hinweis: Chrome für Android unterstützt die meisten der hier genannten HTML5-Funktionen, einschließlich requestAnimationFrame und websockets.

Mehr Informationen:

  • Zeichnen von Text mit dem Kontext 2d fillText ist zu teuer, aber in einigen Browsern ist dies noch schlimmer. Rendern Sie Ihre Texte in einer anderen Zeichenfläche oder verwenden Sie Bitmap-Schriftarten. (Im nativen Android-Browser stieg die Leistung in einigen von mir erstellten Spielen von 10-15 FPS auf 30-45 FPS, nachdem filltext Zeichnung für Pre-Rendering-Inhalte ersetzt wurde.).

  • Vermeiden Sie es, den Kontext zu skalieren und zu drehen, da dies ebenfalls zu Leistungseinbußen führt. Wenn Sie ein Sprite nur einmal skalieren oder drehen müssen, verwenden Sie entweder Vorrendern.

  • Sie müssen das Zeichnen in Echtzeit minimieren. Rendern Sie Ihre Inhalte vor, wann immer Sie können. Zeichne nur Dinge neu, die geändert wurden und aktualisiert werden müssen.

  • Versuchen Sie speichereffizient und Garbage Collector Friendly Code zu schreiben.

Es gibt noch viel mehr zu tun. Ich habe nur einige angeführt.

TIPP: Führen Sie einige Stresstests für Funktionen durch, bei denen Sie sich nicht sicher sind, ob sie die Leistung beeinträchtigen, und erfassen Sie die Benchmarkergebnisse.

In mobilen Anwendungen, insbesondere in Echtzeit-Apps, sind alle Optimierungen willkommen, egal ob es sich nur um eine Überoptimierung oder ein bisschen Speichergewinn handelt.

Für weitere Informationen folgen Sie den Links unten:

Suchen Sie auch in Posts & Tutorials nach Leistung.

EDIT
Dieses jsfiddle code snippet zeigt einige Dinge, die in dieser Antwort behandelt werden, und liefert einen groben fps-Zähler zum Benchmark. Bearbeiten Sie diese Geige selbst und probieren Sie es aus.

42

Je nachdem, was Sie zeichnen, besteht die häufigste Strategie zur Leistungsverbesserung bei HTML5-Zeichenflächen darin, Ebenen (d. H. Mehrere Leinwände) zu verwenden und nur die Ebenen zu aktualisieren, die neu gezeichnet werden müssen, anstatt das Ganze in jedem Animationsrahmen neu zu zeichnen. Sie können so etwas selbst rollen oder Sie könnten so etwas wie http://www.concretejs.com/ verwenden, ein leichtes Html5-Canvas-Framework, das periphere Dinge wie Treffererkennung, Layering, Caching und Pixel-Ratio-Unterstützung ermöglicht , Downloads usw. Sie würden so etwas tun:

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);
0
Eric Rowell