Les performances de rendu
Jean-Pierre Vincent
Architecte itinérant
Consultant et Formateur Perfs ou JS
@theystolemynick
POURQUOI FAIRE ?
Pour faire plaisir à l’utilisateur (et ton
CA)
Temps de réponse :
• < 150 ms : instantané
– Le but de toute interface touc...
Pour faire plaisir à Dieu
Pour faire des interfaces très réactive
Pour des interactions plus riches
Avoir 60 Fps ou pas
Comment fluidifier ?
$(‘.el1’).animate(
{ left: ‘-=600’
},
{ duration: 350,
easing:
‘bounce’
}
);
$(‘.el2’).animate …
Les ordres de grandeur
60 Hz = 16 ms pour :
• JS
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– A...
Les manipulations DOM en JS
• el.offsetLeft …, el.clientLeft…, el.
getBoundingClientRect()…
• el.scrollTo(), el.scrollTop,...
Animation prédictible ? JS quasi inutile
• On trash jQuery.animate
• Pré-calcul des styles
• JS se limite à ajouter / supp...
Animation prédictible : transition CSS
.elements {
transition-property : left;
transition-timing-function: cubic-
bezier(0...
Transitions CSS
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– Appliquer la nouvelle posit...
Les propriétés qui coûtent cher
Elles déclenchent Layout + Paint + Composite
• top, left, width, height, float
• font-*, b...
Les propriétés qui vont bien
.move-left{
transform: translateX(-600px);
}
.enlarge-your p {
transform : scale(1.3, 0) ;
}
...
CSS transform / opacity
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– Appliquer la nouvel...
Bonus : forcer le GPU (parfois)
.move-left {
transform:translate3d(-600px, 0, 0);
}
.enlarge-your p {
transform:scale3d(1....
Transition + translation + GPU = <3
.elements {
transition-property : transform;
transition-timing-function: cubic-
bezier...
Transition + translation + GPU = <3
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– Appliqu...
60 FPS FTW
LES ANIMATIONS IMPRÉVISIBLES
Et pour les animations imprévisibles ?
• Parallax
• Drag
• Jeux vidéos
• …
Reprenons
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– Appliquer la nouvelle position
• ...
Récupérer la position : mise en cache
• Plutôt que
$(el).on(‘touchmove’, function move() {
// get + set du DOM en boucle :...
Reprenons
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position
– Appliquer la nouvelle position
• ...
Quand mettre à jour le DOM ?
// JAMAIS
setInterval( move, 16 );
// MIEUX, mais agressif et imprécis
(function boucle() {
s...
Alléger
var height = el.offsetHeight,
Y = 0;
$(el).on(‘touchmove’, function calculateDelta() {
… // Calcul séparé de Y (de...
Reprenons
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position <= dissocié
– Appliquer la nouvelle...
Calculs lourds ?
var IA = new Worker(‘game-ia.js’);
var positions;
IA.addEventListener(‘moves’,function(e){
positions = e....
Calculs lourds ?
La technique ancestrale du
setTimeout( fn, 0);
Universel, increvable, lisible avec le bon snippet
Reprenons
• JS :
– Récupérer la position de l’élément
– Calcul de la nouvelle position <= dissocié et optimisé
– Appliquer...
DOM : la taille compte
(et la manière dont on s’en sert)
DOM Monster yellowlab.tools
Touche pas (trop) à mon DOM
• Peu de requête DOM
– Mise en cache des résultats en dehors des boucles
• Appliquer en batchs...
Apprends à faire tes sélecteurs
• Natif quand tu peux :
$(document.getElementById(‘id’)) VS $(‘#id’)
document.querySelecto...
MAÎTRISER SES OUTILS
Assez de règles
Profilers — Android & Desktop
Profilers — Firefox & Firefox OS
Profilers — Windows
Profilers natifs — iOS & desktop
Les autres
• Opera : dragonfly
• IE8 : profiling JS
À l’instinct™ :
• iOS < 7
• Navigateur Android
• …
Librairies d’animation CSS 3
• Librairies CSS:
– animate.css,
– Effekt.css
• Librairies JS :
– D3.js,
– GSAP,
– TweenJS,
–...
Conclusion
• JS seul est performant, merci de demander
• Watch your DOM !
• Use the CSS 3 / HTML5 force Luke
Je testerais,...
MERCI
Jean-Pierre Vincent
@theystolemynick
Un audit ou une petite formation Perfs ? jp@braincracking.fr
Prochain SlideShare
Chargement dans…5
×

Les Performance de rendu sur mobile

1 488 vues

Publié le

Comment avoir un rendu performant même sur mobile ? Comment animer convenablement ses interfaces Web ? Quelques pistes et retours d'expérience.
Présenté en 2015 pour le JS Open days 1

Publié dans : Ingénierie
0 commentaire
1 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

Aucun téléchargement
Vues
Nombre de vues
1 488
Sur SlideShare
0
Issues des intégrations
0
Intégrations
108
Actions
Partages
0
Téléchargements
7
Commentaires
0
J’aime
1
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive
  • Plus rapide OK, mais à quel point ?
    Nvidia et sa plateforme GRID (jeu dans le cloud) : > 150 ms
    Facebook A/B testing sur la fréquence en Hertz en passant de en passant de 60 fps à 30 fps : scroll baisse de l’« engagement » (moins de post, moins d’ouverture de l’app …)
  • Rumeur et test de Google, mais cela montre l’idée de Google depuis toujours.
  • L’interface fait semblant de marcher même offline.
    En cas de détection offline, penser à rajouter un petit message bien technique : votre connexion est faible
    Ça passe par des transitions visuelles : si elles rament, c’est pire
    Ebay et Youtube utilisent la technique du loader discret
    Les applications utilisent la technique du faux layout
  • http://engineeringblog.yelp.com/2015/01/animating-the-mobile-web.html

  • Un peu de moins de FPS = moins d’engagement
    Comment amener notre milieu de gamme (Galaxy Note 1, 600€ il y a 3 ans) au niveau d’un haut de gamme
  • Carroussel : Left de 2 images
  • Get / set de position : demande au DOM, coûte cher.
    Layout : dimensions, position
    Paint : shadow, radius …
  • Le simple fait de demander va bypasser le cache des valeurs déjà set, et forcer un recalcul
    Une liste : https://gist.github.com/paulirish/5d52fb081b3570c81e3a
    Liste complémentaire en SVG : http://gent.ilcore.com/2011/03/how-not-to-trigger-layout-in-webkit.html
  • Manière plus compliquée : 1 classe pour tout le slider, mais il faut générer dynamiquement les styles
    De toute façon les navigateurs batchent les modifications du DOM
  • Durée des transitions : rester sous la demie seconde, sinon ça rame même quand c’est fluide
    Marche partout, sans préfixes
  • Modèle de boite : on touche un truc, tout se recalcule, parents compris
    En plus width et height font parfois des arrondis de pixels == bords flous
  • translateX et Y pour left / right, margin, padding
    Scale pour width / height
    rotate, skew(X|Y), matrix(3d) …
  • Moins de CPU, plus de RAM
    Certains mobiles ignorent l’option 3D pour se préserver
    D’autres mettent translate normal directement dans le GPU
  • Utilisation de will-change : trop tôt pour être sur de ce que ça fait
  • À réserver aux petites zones
  • On a mieux séparé nos responsabilités entre la vue et le modèle pour une animation simple
  • Yelp on va bouger les dimensions de la photo, son opacité, bouger le layout, le tout en suivant uniquement le doigt
  • Get / set de position : demande au DOM, coûte cher.
    Layout et Paint réglés grâce à transform + translate, scale, opacity
  • 1 : lecture + écriture : allers retours DOM trop fréquents
    Au passage, c’est le comportement par défaut de jQuery (logique pour une librairie car c’est le plus safe)
    X = delta du doigt depuis le dernier mouvement

    2 : et en plus le navigateur peut batcher les Set successifs (4 ms)
    Y = delta du doigt depuis le début
  • Récupération le moins possible
    Quand appliquer la nouvelle position ?
  • setInterval demande au navigateur de rappeler quoi qu’il arrive : si une action dure plus de 16 ms, les callbacks s’empilent jusqu’à ce que la callstack sature
    setTimeout laisse au navigateur le temps de souffler (avec de grands chiffres), mais des frames sont ratées alors qu’elles auraient pu être honorées. Avec des petites chiffres ( 5 ms), on surconsomme le CPU.
    RaF : Le navigateur te rappelle lorsqu’il se sent chaud. Note que le move() se fait APRÈS le RaF
  • Du coup on calcule la position du doigt pendant l’événement touch
    Mais on n’applique le style que lorsque c’est nécessaire
    Rajouter un petit check « if moving »
  • IA.postMessage();

    iOS, Android 4.4, IE 11 mobile, Fx (s’émule avec setTimeout 0 )
  • MS avait proposé setImmediate, Google a dit non : non merci on préfère optimiser setTimeout 0
  • Calculs : séparé de l’animation, au touch ou via Web Workers / setTimeout
    Nouvelle position : RaF
  • Yellow Lab tools
    DOM Monster
    5000 nœuds c’est beaucoup mais classique si on fait du RWD de bourrin
  • Les librairies de data-binding comme Knockout et Angular font de l’atomique, mais c’est patchable
    React tente le mix entre changements atomiques et batchs grâce à JSX
  • Si c’est pas ton quotidien : investis dans les outils
  • Se branche en USB sur la machine
    Connu car poussé par les évangélistes Google
    Tutoriels et post de blog sont vite obsolète
    Pas super clair
    Il ne fait que Chrome, pas le navigateur Android
  • http://blogs.msdn.com/b/visualstudioalm/archive/2014/04/04/diagnosing-mobile-website-issues-on-windows-phone-8-1-with-visual-studio.aspx
    Visual Studio 2013 + Windows Phone 8.1
    Tout aussi poussé, mais meilleure ergonomie que l’outil chrome devtools
  • USB / Wifi
    Mac OS obligatoire
    Depuis iOS 6
  • Les Performance de rendu sur mobile

    1. 1. Les performances de rendu Jean-Pierre Vincent Architecte itinérant Consultant et Formateur Perfs ou JS @theystolemynick
    2. 2. POURQUOI FAIRE ?
    3. 3. Pour faire plaisir à l’utilisateur (et ton CA) Temps de réponse : • < 150 ms : instantané – Le but de toute interface touch • 150 ms — 1 s : c’est la machine qui bosse – L’utilisateur stresse • > 10s : bye bye Animations : • 60 Fps : fluide et naturel • < 30 Fps : bye bye
    4. 4. Pour faire plaisir à Dieu
    5. 5. Pour faire des interfaces très réactive
    6. 6. Pour des interactions plus riches
    7. 7. Avoir 60 Fps ou pas
    8. 8. Comment fluidifier ? $(‘.el1’).animate( { left: ‘-=600’ }, { duration: 350, easing: ‘bounce’ } ); $(‘.el2’).animate …
    9. 9. Les ordres de grandeur 60 Hz = 16 ms pour : • JS – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    10. 10. Les manipulations DOM en JS • el.offsetLeft …, el.clientLeft…, el. getBoundingClientRect()… • el.scrollTo(), el.scrollTop, w.innerHeight • el.getComputedStyle() • evt.layerX, evt.offsetX • SVG.getCharNumAtPosition(), SVG.getNumberOfChars() jQuery.animate() utilise tout cela !
    11. 11. Animation prédictible ? JS quasi inutile • On trash jQuery.animate • Pré-calcul des styles • JS se limite à ajouter / supprimer des classes El1.addClass(‘disappear-to-left’) El2.addClass(‘appear-from-right’)
    12. 12. Animation prédictible : transition CSS .elements { transition-property : left; transition-timing-function: cubic- bezier(0,0,0.25,1); transition-duration : 350 ms; left: 600px; } .appear-from-right { left: 0; } .disappear-to-left { left: -600px; }
    13. 13. Transitions CSS • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    14. 14. Les propriétés qui coûtent cher Elles déclenchent Layout + Paint + Composite • top, left, width, height, float • font-*, border-*, padding-*, margin-* • display, visibility csstriggers.com
    15. 15. Les propriétés qui vont bien .move-left{ transform: translateX(-600px); } .enlarge-your p { transform : scale(1.3, 0) ; } • IE 8 : ms-filters, IE9 : prefix ms- • IE10, chrome, Fx, OS mobile : standard
    16. 16. CSS transform / opacity • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    17. 17. Bonus : forcer le GPU (parfois) .move-left { transform:translate3d(-600px, 0, 0); } .enlarge-your p { transform:scale3d(1.3, 0, 0); }
    18. 18. Transition + translation + GPU = <3 .elements { transition-property : transform; transition-timing-function: cubic- bezier(0,0,0.25,1); transition-duration : 350 ms; left: 600px; } .appear-from-right { transform: translate3d(-600px, 0px, 0px); } .disappear-to-left { transform: translate3d(-1200px, 0px, 0px); }
    19. 19. Transition + translation + GPU = <3 • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    20. 20. 60 FPS FTW
    21. 21. LES ANIMATIONS IMPRÉVISIBLES
    22. 22. Et pour les animations imprévisibles ? • Parallax • Drag • Jeux vidéos • …
    23. 23. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout <= optimisé en CSS – Paint des zones modifées <= optimisé en CSS – Pousser vers la carte graphique
    24. 24. Récupérer la position : mise en cache • Plutôt que $(el).on(‘touchmove’, function move() { // get + set du DOM en boucle : BOOM this.style.width = (this.offsetWidth + X); } • Préférer var width = el.offsetWidth; $(el).on(‘touchmove’, function move() { // un set, et même plusieurs d’affilé : SMOOTH this.style.width = ( width += Y ); }
    25. 25. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position – Appliquer la nouvelle position • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    26. 26. Quand mettre à jour le DOM ? // JAMAIS setInterval( move, 16 ); // MIEUX, mais agressif et imprécis (function boucle() { setTimeout( boucle, 16); move(); }()); // AU TOP (function boucle() { requestAnimationFrame( boucle); move(); }());
    27. 27. Alléger var height = el.offsetHeight, Y = 0; $(el).on(‘touchmove’, function calculateDelta() { … // Calcul séparé de Y (delta du doigt) }); requestAnimationFrame( function move() { … // check de la nécessité puis Raf(move) this.style.height = (height += Y); });
    28. 28. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position <= dissocié – Appliquer la nouvelle position <= optimisé • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    29. 29. Calculs lourds ? var IA = new Worker(‘game-ia.js’); var positions; IA.addEventListener(‘moves’,function(e){ positions = e.data; }); (function boucle() { requestAnimationFrame( boucle ); moveUnits( positions ); })();
    30. 30. Calculs lourds ? La technique ancestrale du setTimeout( fn, 0); Universel, increvable, lisible avec le bon snippet
    31. 31. Reprenons • JS : – Récupérer la position de l’élément – Calcul de la nouvelle position <= dissocié et optimisé – Appliquer la nouvelle position <= optimisé • Navigateur – Calculs de Layout – Paint des zones modifées – Pousser vers la carte graphique
    32. 32. DOM : la taille compte (et la manière dont on s’en sert) DOM Monster yellowlab.tools
    33. 33. Touche pas (trop) à mon DOM • Peu de requête DOM – Mise en cache des résultats en dehors des boucles • Appliquer en batchs – $el.addClass(‘error’) plutôt que $el.css – .innerHTML marche encore ! – Pas d’alternance get / set
    34. 34. Apprends à faire tes sélecteurs • Natif quand tu peux : $(document.getElementById(‘id’)) VS $(‘#id’) document.querySelector(‘.item’) VS $(‘.item’).first() • Limiter l’étendue de la recherche $container.find(‘.item’) $container.find(‘ > li.item’) • Déléguer $container.on( ‘click’, ‘li’, function(){} )
    35. 35. MAÎTRISER SES OUTILS Assez de règles
    36. 36. Profilers — Android & Desktop
    37. 37. Profilers — Firefox & Firefox OS
    38. 38. Profilers — Windows
    39. 39. Profilers natifs — iOS & desktop
    40. 40. Les autres • Opera : dragonfly • IE8 : profiling JS À l’instinct™ : • iOS < 7 • Navigateur Android • …
    41. 41. Librairies d’animation CSS 3 • Librairies CSS: – animate.css, – Effekt.css • Librairies JS : – D3.js, – GSAP, – TweenJS, – jQuery 4
    42. 42. Conclusion • JS seul est performant, merci de demander • Watch your DOM ! • Use the CSS 3 / HTML5 force Luke Je testerais, tu testeras, nous testerons …
    43. 43. MERCI Jean-Pierre Vincent @theystolemynick Un audit ou une petite formation Perfs ? jp@braincracking.fr

    ×