36 votes

Modèles d'optimisation des performances bitmap

J'ai trouvé plusieurs modèles pour l'optimisation des Bitmaps de manutention en WPF. Je n'ai pas, cependant, de comprendre quand utiliser chacun des modèles. Comme je pense que c'est un problème commun, j'ai résumé ce que je comprends et ce que j'imagine et je demande votre aide. Si vous pouvez ajouter des motifs, expliquer en quoi ils diffèrent, expliquer s'ils utilisent le CPU ou le GPU, et enseigner quand utiliser et comment les combiner, ce serait d'une grande aide!

Contexte – les Images de "Grille" Scénario:

Mon application doit afficher de nombreuses images bitmap. Les images sont affichées sur l'écran, les lignes et les colonnes de la grille comme organisation (pas nécessairement la Grille ou UniformGrid classes, pense le Lecteur Window Media, Album de vue). Les Images peuvent se déplacer entre les différentes cellules de la grille. Quelques images de manière arbitraire, les cellules peuvent être remplacés par d'autres. Les Images doivent être cliquables, devrait fournir un menu contextuel, doivent être sélectionnables, glisser en mesure etc. En d'autres termes, "de combiner les bougres peu en un grand bitmap" n'est pas applicable, à moins de ne pas naïvement.

Modèle 0: Le Hack

Combinez les bougres peu en une image bitmap (comment? contexte de dessin?), et de l'utiliser comme arrière-plan. La superposition de ce avec des images avec un contenu vide qui va gérer les hits, les menus contextuels, événements, etc.

L'avantage est que nous ne sommes que de parler de deux images ici: L'un et celui qui doit le remplacer. Ce doit être vraiment rapide. Cependant, mes années d'expérience à lever le drapeau rouge de danger. Vos commentaires?

Modèle 1: Réduire La Taille De L'Image

C'est un no-brainer, quand vous connaissez à l'avance la taille de l'image pour la redimensionner, et lorsque vous êtes prêt à perdre les détails (couleur) pour la performance:

  1. Réduire la taille du bitmap à l'aide de BitmapImage.DecodePixelWidth
  2. Réduire la couleur de l'information à l'aide de FormatConvertedBitmap.DestinationFormat
  3. Définir le contrôle de mise à l'échelle de comportement de réglage de l'Image.S'étirer pour s'Étirer.Aucun
  4. Définir la SetBitmapScalingMode pour que l'image LowQuality.
  5. Geler le bougre

Voir le code ici.

Modèle 2: Contexte de pré-extraction de

Ce modèle est applicable lorsque vous pensez que vous pouvez profiter de l'utilisateur en regardant les images sur l'écran, et de préparer à l'avance les prochaines images à afficher. Les inconvénients pour votre projet, en plus de la surcharge de la mémoire, c'est qu'il a à soutenir le .Net Framework 4 cible et pas seulement le profil du client, de sorte qu'elle pourrait encourir une installation sur le client. Vous aurez vous-même avoir à souffrir de la programmation asynchrone de la douleur.

Dans ce modèle vous créer exactement le nombre de contrôles d'Image. Lorsque les bitmaps doivent être ajoutés, déplacés ou supprimés, vous ne modifier que le contrôle de l'Image' BitmapSource(s). Un BackgroundWorker tâche est responsable de la pré-extraction de la BitmapSource(s) (éventuellement à l'aide de la "Réduire la Taille de l'Image" schéma ci-dessus) et de les insérer dans MemoryCache.

Pour que cela fonctionne, vous devez définir la BitmapImage de CacheOption à OnLoad, afin que le travail de déchargement à l'arrière-plan travailleur.

Modèle 3: Contexte De Dessin

Ceci a été suggéré par Sheldon Ziao de Support de Microsoft sur la MSDN WPF forum ici. Voir la page 494, Chapitre 15 "2D Graphiques" en Adam Nathan WPF 4 Unleashed pour une description de DrawingContext. Je ne peux pas dire que je le comprends. Selon la réponse ici, je suppose que cela permettrait d'améliorer la manipulation de la Géométrie des dessins, pas des bitmaps. Ensuite, je ne pense pas que ce sera de soutenir l'accent et les événements exigences pour les images (mon mauvais pour ne pas expliquer le mieux les exigences lors du forum) de Plus, je suis inquiet par le livre le résumé de la phrase: "Notez que l'utilisation de DrawingContext ne change pas le fait que vous êtes d'exploitation au sein d'une retenue en mode système. La spécifié de dessin ne se produit pas immédiatement; les commandes sont conservées par WPF jusqu'à ce qu'ils sont nécessaires." Cela signifie qu'une fois notre même gestionnaire re nous ne pouvons pas tirer parti du parallélisme comme dans "arrière-plan pré-extraction".

Schéma 4: Écriture Des Bitmaps

La documentation MSDN ici décrit comme un double système de tampon: Votre thread de l'INTERFACE utilisateur des mises à jour de la mémoire tampon; le WPF thread de rendu se déplace ce mémoire vidéo.

L'utilisation prévue (voir ici) est pour les bitmaps que changer beaucoup de choses dans un film vidéo sur l'écran. Je ne suis pas sûr, mais c'est possible que cela pourrait être piraté et combiné avec l'arrière-plan de Pré-extraction de motif et utilisée dans la grille scénario.

Modèle 5: Mise En Cache Des Bitmap

Pas beaucoup d'infos sur le site web MSDN (ici). Sur le WPF archives du forum (ici), il est expliqué que "La BitmapCache API est conçu pour le cache de votre contenu (lors du rendu dans le matériel) dans la mémoire vidéo, le sens qu'il reste résident sur votre GPU. Cela vous permet d'économiser le coût de re-rendu que le contenu lorsque vous dessinez à l'écran." Cela semble être une bonne idée. Je ne suis pas sûr, cependant, ce sont les pièges et comment les utiliser.

Schéma 6: RenderTargetBitmap

Le RenderTargetBitmap convertit un Visuel d'une image bitmap. Je ne sais pas si c'est pertinent ici. Voir ici.

Edit: en ce qui Concerne Paul Hoenecke question: j'ai écrit que "Ma demande a afficher de nombreux bitmap iages". Je ne mentionne que j'ai besoin d'afficher environ 800 images simultanément.

On peut lire à propos de la performance lors de mes questions WPF Bitmap de la performance et Comment puis-je faire de l'affichage d'images sur WPF plus "accrocheur"?

J'ai modifié la description de l'exemple 1 pour mettre en surbrillance le concept que le contrôle de l'image ne sont pas créés ou supprimés (sauf si on veut afficher un plus grand ou plus petit de la grille). Seulement leurs Sources sont définies à différents, nouveaux ou null BitmapSources.

Edit: Cette question publié sur le WPF forum de support, avec quelques réponses à partir de MS personnel.

19voto

Dr. ABT Points 8119

Je suis incapable de trouver une question spécifique dans votre post, autres que de demander des observations sur les approches ci-dessous. Je ne prétends pas tout savoir dessus, mais je vais vous dire ce que je sais, pour avoir travaillé pendant un certain temps le développement de la haute performance de l'Isu à l'aide de WPF et Silverlight.

Modèle 0: Le Hack. En combinant toutes ces données dans une image

J'aimerais éviter si possible. Il semble que vous voulez afficher un grand wrap-panneau de milliers de petites images. Chaque image est donc une vignette (comme vous ne pouvez pas afficher 1000s de grandes images à la fois). En conséquence, je serais avocat de la mise en cache ou le redimensionnement de plus de la combinaison.

Modèle 1: Réduire La Taille De L'Image

Si vous êtes en affichage 1 000 images sur l'écran à la fois, pensez à la disposition de l'écran de l'immobilier. La moyenne du moniteur 1280 x 1024 pixels, soit un peu plus de 1.3 MPixels. 1000 images suggère, vous obtiendrez une taille maximale de 1300 pixels par image, ou 36*36. Disons que vos images sont de 32*32 en taille. Vous devez certainement être en train de créer une miniature de la taille de l'image pour le rendu à l'écran, puis cliquez sur (ou autres) afficher l'image en taille réelle.

Également tenir compte non seulement de la rendre généraux de redimensionnement d'une image de grande taille, mais l'envoi d'une image de grande taille dans le GPU pour les redimensionner. Que des données nécessite une bande passante pour envoyer. Une grande image peut être de plusieurs méga-octets alors qu'une vignette de taille 32*32 peut être de quelques kilo-octets.

Si vous avez besoin de redimensionnement dynamique, très bien, mais vous aurez besoin d'expérimenter avec la création de plusieurs vignettes ou les générer à la volée.

Modèle 2: Contexte de pré-extraction de

C'est une technique que je n'ai pas entendu parler de, mais il semble plausible. Qu'est-ce que le temps de votre demande? est-ce la mise à jour de l'Image.Propriété de la Source ou de la création d'une nouvelle Image, le pavage, l'exécution de Mise en page et l'envoi de l'information pour la rendre pour le GPU?

Tous les ci-dessus se produisent sur le CPU, sauf pour le rendu final. En réduisant la surcharge sur le côté CPU et de la mise à jour de la source que vous pourriez être à quelque chose. Combinez cela avec WriteableBitmap comme source et vous pourriez gain supplémentaire d'amélioration de la performance (voir ci-dessous).

Modèle 3: Contexte De Dessin

Ok, tout cela n'est de vous permettre de file d'attente de conserver le mode de dessin des appels à l'aide d'un "OnPaint" la syntaxe de style qui n'est rien comme les vieux GDI OnPaint. Dans mon expérience, OnRender n'améliore pas les performances, mais il ne permet pas pour précision, de souplesse au cours de ce qui est dessiné et quand. OnRender vous fournit un contexte qui a une fonction DrawImage, permettant une BitmapSource être attirée sur le pipeline de rendu sans la nécessité d'un contrôle de l'Image. C'est bon comme ça enlève une partie des frais généraux, cependant introduit des problèmes similaires à ceux observés dans Pattern0 (vous perdrez la mise en page et à calculer la position de toutes vos images). Si vous faites cela, vous pourriez aussi bien invoquer de Motif de 0, ce qui je l'ai conseillé contre.

Schéma 4: Écriture Des Bitmaps

WriteableBitmaps sont un peu utilisés et extraordinairement puissant sous-système au sein de WPF. - Je les utiliser pour beaucoup d'effet pour créer un composant graphique capable de rendre de grandes quantités de données en temps réel. Je suggère de vérifier la WriteableBitmapEx codeplex projet de Divulgation, j'ai contribué à cette fois et de voir si vous pouvez les combiner avec d'autres modèles. Plus précisément, le Blit fonction qui vous permettent d'écrire un bitmap mis en cache sous forme de bitmap source sur une image.

Par exemple, une bonne technique pourrait être d'un Modèle 1 + 2 + 4.

Vous pourriez avoir une grille de N de contrôles d'Image sur l'écran à définir les emplacements dans une grille de contrôle. Chacun de ces est statique et ne pas obtenir un défilement de vue, donc il n'y a pas de créations/suppressions de passe. Maintenant, sur le dessus de cette, redimensionner votre image et à écrire à un WriteableBitmap qui est définie comme la propriété de la Source de chaque image. Lorsque vous faites défiler, la prochaine/précédente vignettes et de mettre à jour les sources à l'aide de WriteableBitmapEx.Blit. Pow! virtualisé, la mise en cache, multi-thread de l'imagerie de la bonté.

Modèle 5: Mise En Cache Des Bitmap

C'est une tentative de microsoft pour faire 1+2+4 comme je l'ai expliqué ci-dessus. Ce qu'il essaie de faire est après sa mise en page (CPU côté), de pavage (CPU Côté), l'envoi conservé le mode de rendu des instructions pour le GPU (PROCESSEUR) et le rendu GPU, le côté), il met en cache une image raster de l'élément affiché qui est de nouveau sur la prochaine passe de rendu. Oui un fait peu connu sur WPF est merveilleux le GPU alimenté le moteur est terriblement lent comme il le fait la plupart de ses travaux sur le CPU :P

Je voudrais expérimenter avec BitmapCache et de voir comment il se comporte. Il y a des avertissements, et ils sont que lorsque vous mettez à jour votre UIElement il a pour recréer le cache de sorte éléments statiques va effectuer beaucoup mieux que dynamique. Aussi, je n'ai pas vu une amélioration significative des performances de l'utilisation de ce considérant que WriteableBitmap techniques de style peut donner un ordre de grandeur de l'amélioration.

Schéma 6: RenderTargetBitmap

Cette dernière technique permet de rendre un UIElement un bitmap - vous le savez - mais ce qui est intéressant, c'est que ça peut effectuer une mauvaise mans miniature générateur (ou redimensionner). Par exemple, placer une Image avec BitmapSource de votre image en pleine taille. Maintenant de définir la taille de l'Image de contrôle à 32*32 et le rendu de l'image bitmap. Voila! Vous avez votre BitmapSource miniature à utiliser en conjonction avec certains de permutation (Modèle 2) et/ou l'écriture des bitmaps.

Ok enfin, je voulais juste dire la condition que vous avez pousser à WPF de ses limites, cependant, il ya des façons d'obtenir de l'exécuter. Comme je l'ai dit, j'ai de construire des systèmes qui l'a rendu des milliers ou des millions d'éléments à l'écran à la fois en utilisant la merveilleuse solution de contournement qui est WriteableBitmap. La descente de la norme WPF route s'entraîner dans la performance de l'enfer, de sorte que vous aurez à faire quelque chose d'exotique, de résoudre ce problème.

Comme je l'ai dit, ma recommandation est 1+2+4. Vous devez redimensionner une vignette, de qui je n'en doute pas. L'idée d'avoir une statique de la grille de réglages de l'Image et de la mise à jour des sources est très bon. L'idée d'utiliser WriteableBitmap (plus précisément WriteableBitmapEx blit fonction) pour mettre à jour les sources, c'est aussi l'un vaut la peine d'explorer.

Bonne chance!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X