Bonjour
ce week-end, j'ai commencé à regarder les vidéos 2011 de la WWDC. J'ai trouvé des sujets très intéressants sur iOS. Mes favoris portaient sur les performances et les graphismes, mais j'en ai trouvé deux apparemment en contradiction. Bien sûr, il y a quelque chose que je n'ai pas compris. Les sessions dont je parle sont Comprendre le rendu UIKit -121 et Polir votre application -105.
Malheureusement, l'exemple de code de 2011 n'est toujours pas téléchargeable, il est donc assez difficile d'avoir une vue d'ensemble. Dans une session, ils expliquent que la plupart du temps, le rendu hors écran doit être évité lors de la visualisation dans scrollview etc. Ils corrigent les problèmes de performances dans l'exemple de code en dessinant presque tout dans la méthode -drawRect. Dans l'autre session, le problème de performances (sur une vue de table) semble être dû à trop de code dans la méthode -drawRect des cellules du tableau.
.
Deuxièmement, je ne sais pas si j'ai bien compris, mais il semble que lorsqu'il n'y a pas de rendu hors écran, l'ajout de couches ou de vues est la solution. J'espère que quelqu'un pourra faire la lumière à ce sujet ..
Merci,
Andrea
Je ne pense pas qu'il y ait de règle écrite nulle part, mais j'espère que cela aidera:
Tout d'abord, clarifions quelques définitions. Je pense que le rendu hors écran vs à l'écran n'est pas la préoccupation majeure la plupart du temps, car le rendu hors écran peut être aussi rapide qu'à l'écran. Le problème principal est de savoir si le rendu est effectué en matériel ou en logiciel.
Il y a également très peu de différence pratique entre l'utilisation de calques et de vues. Les vues ne sont qu'une mince enveloppe autour de CALayer et n'introduisent pas de pénalité de performance significative la plupart du temps. Vous pouvez remplacer le type de calque utilisé par une vue à l'aide de la méthode + layerClass si vous souhaitez avoir une vue soutenue par un CAShapeLayer ou CATileLayer, etc.
Généralement, sur iOS, les effets de pixels et les dessins graphiques Quartz/Core ne sont pas accélérés par le matériel, et la plupart des autres choses le sont.
Les choses suivantes ne sont pas accélérées par le matériel, ce qui signifie qu'elles doivent être effectuées par logiciel (hors écran):
Tout ce qui est fait dans un drawRect. Si votre vue a un drawRect, même vide, le dessin n'est pas fait dans le matériel et il y a une pénalité de performance.
Tout calque dont la propriété shouldRasterize est définie sur YES.
Tout calque avec un masque ou une ombre portée.
Texte (tout type, y compris UILabels, CATextLayers, Core Text, etc.).
Tout dessin que vous faites vous-même (à l'écran ou hors écran) à l'aide d'un CGContext.
La plupart des autres choses sont accélérées par le matériel, elles sont donc beaucoup plus rapides. Cependant, cela peut ne pas signifier ce que vous pensez que cela fait.
Tous les types de dessin ci-dessus sont lents par rapport au dessin accéléré par le matériel, mais ils ne ralentissent pas nécessairement votre application car ils n'ont pas besoin de se produire à chaque image. Par exemple, dessiner une ombre portée sur une vue est lent la première fois, mais une fois dessinée, elle est mise en cache et n'est redessinée que si la vue change de taille ou de forme.
Il en va de même pour les vues pixellisées ou les vues avec un drawRect personnalisé: la vue n'est généralement pas redessinée à chaque image, elle est dessinée une fois puis mise en cache, de sorte que les performances après la première configuration de la vue ne sont pas pires, sauf si les limites changent ou vous appelez setNeedsDisplay dessus.
Pour de bonnes performances, l'astuce consiste à éviter d'utiliser des dessins logiciels pour des vues qui changent chaque image. Par exemple, si vous avez besoin d'une forme vectorielle animée, vous obtiendrez de meilleures performances en utilisant CAShapeLayer ou OpenGL que drawRect et Core Graphics. Mais si vous dessinez une forme une fois et que vous n'avez pas besoin de la changer, cela ne fera pas beaucoup de différence.
De même, ne mettez pas d'ombre portée sur une vue animée car cela ralentira votre fréquence d'images. Mais une ombre sur une vue qui ne change pas d'un cadre à l'autre n'aura pas beaucoup d'impact négatif.
Une autre chose à surveiller est le ralentissement du temps de configuration de la vue. Par exemple, supposons que vous ayez une page de texte avec des ombres portées sur tout le texte; cela prendra très longtemps à dessiner au départ car le texte et les ombres doivent tous être rendus dans le logiciel, mais une fois dessiné, ce sera rapide. Vous souhaiterez donc configurer cette vue à l'avance lors du chargement de votre application et en conserver une copie en mémoire afin que l'utilisateur n'ait pas à attendre longtemps que la vue s'affiche lors de sa première apparition à l'écran.
C'est probablement la raison de l'apparente contradiction dans les vidéos de la WWDC. Pour les vues volumineuses et complexes qui ne changent pas chaque image, les dessiner une fois dans le logiciel (après quoi elles sont mises en cache et n'ont pas besoin d'être redessinées) donneront de meilleures performances que d'avoir le matériel les recomposant à chaque image, même si il sera plus lent à dessiner la première fois.
Mais pour les vues qui doivent être constamment redessinées, comme les cellules d'un tableau (les cellules sont recyclées, elles doivent donc être redessinées à chaque fois qu'une cellule défile hors écran et est réutilisée lorsqu'elle revient de l'autre côté sur une ligne différente), le dessin du logiciel peut ralentir beaucoup les choses.
Le rendu hors écran est aujourd'hui l'un des pires sujets définis dans le rendu iOS. Lorsque les ingénieurs UIKit d'Apple font référence au rendu hors écran, cela a une signification très spécifique, et une tonne de blogs de développeurs iOS tiers se trompent.
Lorsque vous remplacez "drawRect:", vous dessinez via le CPU et crachez un bitmap. Le bitmap est empaqueté et envoyé à un processus distinct qui vit dans iOS, le serveur de rendu. Idéalement, le serveur de rendu affiche simplement les données à l'écran.
Si vous jouez avec des propriétés sur CALayer, comme activer des ombres portées, le GPU effectuera un dessin supplémentaire. Ce travail supplémentaire est ce que les ingénieurs UIKit veulent dire quand ils disent "rendu hors écran". Ceci est toujours effectué avec du matériel.
Le problème avec le dessin hors écran n'est pas nécessairement le dessin. La passe hors écran nécessite un changement de contexte, car le GPU change de destination de dessin. Pendant ce changement, le GPU est inactif.
Bien que je ne connaisse pas une liste complète des propriétés qui déclenchent une passe hors écran, vous pouvez diagnostiquer cela avec la bascule "Calque rendu hors écran" de l'instrument d'animation de base. Je suppose que toute propriété autre que alpha est effectuée via une passe hors écran.
Avec les premiers matériels iOS, il était raisonnable de dire "tout faire dans drawRect". De nos jours, les GPU sont meilleurs et UIKit a des fonctionnalités comme shouldRasterize. Aujourd'hui, c'est un équilibre entre le temps passé dans drawRect, le nombre de passes hors écran et la quantité de mélange. Pour plus de détails, regardez la session 419 de la WWDC 2014, "Graphiques et animations avancés pour les applications iOS".
Cela dit, il est bon de comprendre ce qui se passe dans les coulisses et de le garder derrière la tête afin de ne rien faire de fou, mais vous devriez partir de la solution la plus simple. Ensuite, testez-le sur le matériel le plus lent que vous prenez en charge. Si vous ne frappez pas 60FPS, utilisez des instruments pour mesurer les choses et le comprendre. Il existe quelques goulots d'étranglement possibles, et si vous n'utilisez pas de données pour diagnostiquer des choses, vous ne faites que deviner.
Le plus gros goulot d'étranglement des performances graphiques est le rendu et le mélange hors écran - ils peuvent se produire pour chaque image de l'animation et provoquer un défilement saccadé.
Le rendu hors écran (rendu logiciel) se produit lorsqu'il est nécessaire de faire le dessin dans le logiciel (hors écran) avant de pouvoir le remettre au GPU. Le matériel ne gère pas le rendu de texte et les compositions avancées avec masques et ombres.
Les éléments suivants déclencheront le rendu hors écran:
Tout calque avec un masque (layer.mask
)
Tout calque avec layer.masksToBounds
/view.clipsToBounds
être vrai
Tout calque avec layer.allowsGroupOpacity
réglé sur OUI et layer.opacity
est inférieur à 1,0
Quand une vue (ou un calque) nécessite-t-elle un rendu hors écran?
Tout calque avec une ombre portée (layer.shadow*
).
Conseils sur la façon de corriger: https://markpospesel.wordpress.com/tag/performance/
Tout calque avec layer.shouldRasterize
être vrai
Tout calque avec layer.cornerRadius
, layer.edgeAntialiasingMask
, layer.allowsEdgeAntialiasing
Tout calque avec layer.borderWith
et layer.borderColor
?
Référence/preuve manquante
Texte (tout type, y compris UILabel
, CATextLayer
, Core Text
, etc).
La plupart des dessins que vous faites avec CGContext
dans drawRect:
. Même une implémentation vide sera rendue hors écran.
Cet article traite du mélange et d'autres choses affectant les performances: Qu'est-ce qui déclenche le rendu, le mélange et les présentations de l'écran hors écran dans iOS?