Problemy z wydajnością HTML5 Canvas w niektórych przeglądarkach mobilnych.

Witam mam Webapp, który powinien być w stanie uruchomić zarówno na smartphone i pulpit przeglądarki zarówno. Podczas gdy spodziewałem się ciekawego zachowania na małych urządzeniach, takich jak Iphone, byłem całkiem pewien, że będzie działał dobrze na Androidzie Galaxy Tab, który jest urządzeniem z Androidem, z którym mogę w tej chwili uruchamiać testy.

Teraz zainstalowałem kilka przeglądarek na Galaxy Tab do testowania rzeczy z:

  • Natywna Przeglądarka Androida
  • Chrome dla Android
  • Firefox dla Androida]}

Na pulpicie użyłem

  • Firefox
  • Google Chrome

I wreszcie mam Iphone ' a do przetestowania.

Strona korzysta z HTML5 canvas do rysowania opartego na pikselach i sprite bez fantazyjnych transformacji, filtrów lub efektów, głównie prostych ścieżek i wielokątów. Słucham zdarzeń dotykowych i używam requestAnimationFrame do poprawnego przerysowania.

Ogólnie aplikacja działa dobrze w przeglądarkach desktopowych, działa również świetne na iOS Safari (iPhone) i Firefox-on-Android. Jednak natywna przeglądarka androidów sprawia mi kłopoty. Skonfigurowałem go tak, aby ekran zaczerwienił się, gdy javascript nie reaguje, i prawie zawsze miga podczas dotykania ekranu.

Więc zastanawiam się, czy są jakieś znane problemy z Android Native App i HTML5. Ze względu na nieistniejącą nazwę natywnej przeglądarki dość trudno jest google informacji na ten temat. jakieś pomysły dla mnie, Gdzie mogę uzyskać więcej informacji? Jakieś pomysły, co może spowodować opóźnienie natywnej przeglądarki Android?

Jest kilka pomysłów na ten temat:

  • IOS nie obsługuje requestAnimationFrame, dlatego zastąpiłem go zamiennikiem opartym na limicie czasu. Jeśli używam tego zamiennika w natywnej przeglądarce Androida, problem nadal występuje.

  • Używam AJAX (google clojure xhrio) dość regularnie do pobierania danych z serwera. Czy to możliwe, że wywołania odzyskiwania danych blokują moje Zdarzenie rurociąg?

  • Są logami komunikatów konsoli (console.log) wiadomo, że spowalnia aplikacje? Czy mogą uruchomić przeglądarkę do ponownego uruchomienia przez drzewo DOM lub coś związanego?

Author: Gustavo Carvalho, 2013-04-24

2 answers

Zrobiłem wiele eksperymentów z canvas w wielu przeglądarkach. Niektóre problemy z wydajnością, które zauważyłem:

Po pierwsze, o zgadywaniu:

  • Gdy requestAnimationFrame jest obsługiwany przez przeglądarkę, rysowanie i sama aplikacja są bardziej responsywne. Użyj setTimeout lub setInterval jako awaryjnego są zawsze możliwe, ale trzeba uważać na czas. Ten solidny polyfill może trochę pomóc, ale nic w porównaniu do natywnego requestAnimationFrame.

  • Jeśli konsola.log jest nazywany każdą klatką (lub prawie), tak wydajność spada. Ponieważ natywna przeglądarka Android nie ma obiektu konsoli, za każdym razem, gdy zostanie wywołana, wygeneruje błąd, który również przyczynia się do spowolnienia aplikacji. Możesz to zrobić:

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

  • Dla intensywnych aplikacji w czasie rzeczywistym gniazda sieciowe są szybsze niż żądania http. Niestety ta funkcja nie jest obsługiwana przez stare natywne przeglądarki android. Jeśli nie jest możliwe korzystanie z sieci sockets, powinieneś zminimalizować żądania http.

Uwaga: Chrome dla Androida obsługuje większość cytowanych tutaj funkcji HTML5, w tym requestAnimationFrame i websockets.

Więcej informacji:

  • Rysowanie tekstu za pomocą kontekstu 2D fillText jest zbyt drogie, ale w niektórych przeglądarkach jest to jeszcze gorsze. Wstępnie Renderuj teksty w innym obszarze roboczym lub użyj czcionek bitmapowych. (W natywnej przeglądarce Android, po zastąpieniu filltext rysunku dla elementów pre-renderujących, wydajność wzrosła z 10-15 FPS do 30-45 FPS w niektórych grach, które zrobiłem).

  • Unikaj skalowania i obracania kontekstu, ponieważ powodują one również spadek wydajności. Jeśli chcesz przeskalować lub obrócić sprite tylko raz, użyj renderowania wstępnego.

  • Musisz zminimalizować rysunek w czasie rzeczywistym. Pre-Renderuj swoje rzeczy, kiedy tylko możesz. Przerysuj tylko rzeczy, które się zmieniły i wymagają aktualizacji.

  • Spróbuj napisać efektywny pamięciowo i przyjazny dla garbage collector kod.

Jest o wiele więcej rzeczy do zrobienia. Przytoczyłem tylko kilka.

Wskazówka: zrób kilka testów warunków skrajnych dla funkcji, które nie są pewne, czy są zabójcze dla wydajności i uchwyć wyniki testów.

W aplikacjach mobilnych, szczególnie aplikacjach czasu rzeczywistego, wszystkie optymalizacje są mile widziane, jeśli jest to tylko nadmierna optymalizacja lub trochę pamięci.

Więcej informacji pod linkami poniżej:

Szukaj również wydajności w postach i tutorialach.

EDIT
Ten fragment kodu jsfiddle pokazuje niektóre rzeczy omówione w tej odpowiedzi i zapewnia przybliżony licznik fps do benchmarku. Edytuj to skrzypce samodzielnie i sprawdź Wynocha.

 42
Author: Gustavo Carvalho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-20 01:06:59

W zależności od tego, co rysujesz, najczęstszą strategią poprawy wydajności w HTML5 canvas jest wykorzystanie warstw (tj. wielu płócien) i aktualizacja tylko tych warstw, które wymagają przerysowania, zamiast przerysowania całości na każdej klatce animacji. Możesz zrobić coś takiego samemu lub użyć czegoś w rodzaju http://www.concretejs.com / który jest lekkim frameworkiem Html5 canvas, który umożliwia detekcję uderzeń, tworzenie warstw, buforowanie, obsługa proporcji pikseli, pliki do pobrania itp. Zrobiłbyś coś takiego:

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
Author: Eric Rowell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-02 22:07:24