web-dev-qa-db-fra.com

Problèmes de performances avec Toile dans certains navigateurs mobiles.

Bonjour, je possède une application Web qui devrait pouvoir fonctionner à la fois sur un smartphone et sur un navigateur de bureau. Alors que je m'attendais à avoir un comportement curieux sur de petits appareils tels que l'Iphone, j'étais assez confiant que cela fonctionnerait bien sur un Android Galaxy Tab qui est l'appareil Android avec lequel je peux exécuter des tests pour le moment.

Maintenant, j'ai installé un tas de navigateurs sur la Galaxy Tab pour tester des choses avec:

  • Navigateur natif Android
  • Chrome pour Android
  • Firefox pour Android

Sur le bureau, j'ai utilisé

  • Firefox
  • Google Chrome

et enfin j'ai un iPhone à tester avec.

Le site Web utilise des canevas HTML5 pour les dessins au pixel et sur Sprite sans transformation, filtres ou effets de fantaisie, principalement des chemins et des polygones simples. J'écoute les événements tactiles et utilise requestAnimationFrame pour le redessiner correctement.

Dans l'ensemble, l'application fonctionne bien sur les navigateurs de bureau, mais également sur iOS Safari (iPhone) et Firefox sur Android. Androids Native Browser me pose problème. Je l'ai configuré pour que l'écran vire au rouge lorsque le javascript n'est pas réactif et qu'il clignote presque toujours lorsque vous touchez l'écran.

Je me demande donc s'il existe des problèmes connus avec Android Native App et HTML5. En raison du nom inexistant du navigateur natif, il est assez difficile de rechercher des informations sur Google à ce sujet. Des idées pour moi où je peux obtenir plus d'informations? Des idées sur ce qui pourrait causer le retard du navigateur Android natif?

Il y a quelques idées sur le problème:

  • iOS ne supporte pas requestAnimationFrame, c'est pourquoi je l'ai remplacé par un remplacement basé sur le délai d'expiration. Si j'utilise ce remplacement sur le navigateur natif d'Android, le problème persiste.

  • J'utilise AJAX (google clojure xhrio) assez régulièrement pour récupérer des données du serveur. Serait-ce que les callbacks de récupération de données sont en train de boucher mon pipeline d’événements?

  • Les messages de la console de journal (console.log) sont-ils connus pour ralentir les applications? Pourraient-ils déclencher la réexécution du navigateur via l'arborescence DOM ou tout autre élément lié?

13
wirrbel

J'ai fait beaucoup d'expériences avec canvas dans de nombreux navigateurs. Quelques problèmes de performance que j'ai remarqués:

Premièrement, à propos de vos suppositions:

  • Lorsque requestAnimationFrame est pris en charge par un navigateur, les éléments de dessin et l'application elle-même sont plus réactifs. Utiliser setTimeout ou setInterval comme solution de secours est toujours possible, mais vous devez faire attention au timing. Ce robuste polyfill peut aider un peu, mais rien comparé à requestAnimationFrame natif.

  • Si console.log est appelé chaque image (ou presque), la performance diminue. Le navigateur Android natif n'ayant pas d'objet de console, chaque appel génère une erreur qui contribue également à ralentir votre application. Tu peux le faire:

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

  • Pour les applications en temps réel intenses les sockets Web sont plus rapides que les requêtes http. Malheureusement, cette fonctionnalité n'est pas prise en charge par les anciens navigateurs Android natifs. S'il n'est pas possible d'utiliser des sockets Web, vous devez minimiser les requêtes http.

Remarque: Chrome pour Android prend en charge la plupart des fonctionnalités HTML5 citées ici, y compris requestAnimationFrame et websockets.

Plus d'information:

  • Dessiner du texte en utilisant le contexte 2d fillText c'est trop cher, mais dans certains navigateurs, c'est encore pire. Effectuez un pré-rendu de vos textes dans un autre canevas ou utilisez des polices bitmap. (Dans le navigateur Android natif, après avoir remplacé le dessin filltext pour les éléments de pré-rendu, la performance est passée de 10-15 FPS à 30-45 FPS dans certains jeux que j'ai réalisés).

  • Évitez les contextes d'échelle et de rotation car ils entraînent également une baisse des performances. Si vous devez redimensionner ou faire pivoter un Sprite une seule fois, utilisez le pré-rendu non plus.

  • Vous devez minimiser le dessin en temps réel. Effectuez un pré-rendu de vos affaires chaque fois que vous le pouvez. Redessine uniquement les éléments qui ont changé et doivent être mis à jour.

  • Essayez d'écrire une mémoire efficace et un code convivial pour le ramasse-miettes.

Il y a beaucoup plus de choses à faire. Je viens de citer quelques-uns.

CONSEIL: effectuez des tests de résistance pour les fonctionnalités que vous ne connaissez pas vraiment et capturez les résultats de référence.

Dans les applications mobiles, spécialement les applications temps réel, toutes les optimisations sont les bienvenues, qu’il s’agisse d’une suroptimisation ou d’un gain de mémoire.

Pour plus d'informations, suivez les liens ci-dessous:

Recherchez également des performances dans Posts & Tutorials .

EDIT
Ce extrait de code jsfiddle présente des éléments abordés dans cette réponse et fournit un résumé approximatif en IPS par rapport au point de référence. Éditez ce violon par vous-même et vérifiez-le.

42
Gustavo Carvalho

En fonction de ce que vous dessinez, la stratégie d’amélioration des performances la plus courante avec le canevas Html5 consiste à utiliser des calques (c’est-à-dire plusieurs canevas) et à ne mettre à jour que les calques devant être redessinés, au lieu de tout redessiner sur chaque image animée. Vous pouvez lancer quelque chose comme ceci vous-même ou vous pouvez utiliser quelque chose comme http://www.concretejs.com/ , qui est un framework de toile Html5 léger qui permet des choses périphériques telles que la détection des hits, la superposition, la mise en cache, la prise en charge du rapport de pixels , téléchargements, etc. Vous feriez quelque chose comme ceci:

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