locked
Optimisation de l'utilisation mémoire: diminuer le pique d'utilisation mémoire RRS feed

  • Question

  • Bonjour,

     

    Je suis entrain de finaliser ma première application qui fait un petit traitement d'image.

    Lors des tests contrôlés sous marketplace testkit j'ai un pique mémoire à 122Mo, celui se produit pendant le traitement d'une image capturé avec l'appareil photo (8M pixels).

    Je cherche a diminuer ce pique sous les 90Mo autorisé par le marketplace tout en gardant la même résolution d'image

    Auriez vous des pistes a me donner pour cela?

     

    Merci d'avance

    Romain

    jeudi 19 janvier 2012 09:06

Réponses

  • As-tu identifié précisément quel(s) appel(s) provoque une fuite mémoire ? Ton code est "vaste", il faut isoler la partie qui consomme sans libéré (en désactivant au fur et à mesure des portion de code par exemple).

    Petite astuce concernant cette partie:

     

    MediaLibrary library = new MediaLibrary();
    
    if (source == true)
    {
       library.SavePictureToCameraRoll("ColoMorphCapture.jpg", myFileStream);
    }
    if (source == false)
    {
       library.SavePicture("ColoMorphPicture.jpg", myFileStream);
    }
    
    

    Je te recommande, dans des cas comme celui-ci (ou tu n'aura qu'un seul appel de méthode sur un objet instancié) de ne pas instancier celui-ci dans une variable, mais plutôt de le créer "à la volé" et de l'utiliser tout de suite (le GC va immédiatement libérer les ressources sans se poser de question), exemple :

     

     

    if (source == true)
       new MediaLibrary().SavePictureToCameraRoll("ColoMorphCapture.jpg", myFileStream);
    if (source == false)
       new MediaLibrary().SavePicture("ColoMorphPicture.jpg", myFileStream);
    

     


    Pour que la discussion puisse être identifiée comme résolue merci de marquer les réponses qui vous ont aidées à solutionner votre problème comme "réponse".
    mardi 24 janvier 2012 08:53

Toutes les réponses

  • ton traitement sur l'image doit etre bcp trop lourd, sans code on ne pourra t'aider
    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue
    jeudi 19 janvier 2012 09:47
  • Merci pour ta réponse

    Voici le code de mon traitement:

     

     

    //////////////////////////////////////////////////////
    // Traitement                                             //
    //////////////////////////////////////////////////////
    int size = wb.PixelWidth * wb.PixelHeight;
    for (int i = 0; i < (size); i++)
    {
         int cp = wb.Pixels[i];
         var alpha = (byte)(cp >> 24);
         var red = (byte)(cp >> 16);
         var green = (byte)(cp >> 8);
         var blue = (byte)(cp);
    
         Color c = Color.FromArgb(0, 0, 0, 0);
    
         // traitement ( inversion rouge et vert )
         var swap = green;
         green = red;
         red = swap;
    
         c.A = alpha;
         c.R = red;
         c.G = green;
         c.B = blue;
    
         wb.Pixels[i] = c.A << 24 | c.R << 16 | c.G << 8 | c.B;
    }
    

    Si tu as quelques pistes a me suggérer je suis preneur :)

     


    • Modifié Romain.P jeudi 19 janvier 2012 10:04
    jeudi 19 janvier 2012 10:04
  • Optimisons ceci, tu passes par un color qui sert a rien, et tu as bcp trop de variable locale

     

    int size = wb.PixelWidth * wb.PixelHeight;
    for (int i = 0; i < (size); i++)
    {
         int cp = wb.Pixels[i];
     wb.Pixels[i] =  (byte)(cp >> 24) << 24 | (byte)(cp >> 8) << 16 | (byte)(cp >> 16) << 8 |  (byte)(cp);
    }
    
    


     

     


    S'il vous plaît n'oublier pas de marquer la ou les réponses qui aident à résoudre votre problème. Pour que la discussion puisse être marquée comme résolue
    jeudi 19 janvier 2012 10:56
  • Merci pour ton aide, je testerai ça ce soir en rentrant du boulot
    jeudi 19 janvier 2012 11:26
  • Bon alors j'ai testé, c'est un peu mieux mais c'est pas encore ça. Je reste à 102Mo

    J'ai fait pas mal de tests dont voici les résultats:

    - fonction entière: traitement + ouverture d'une nouvelle page avec un control image et 2 textblock -> 102Mo

    - fonction traitement sans l'ouverture de la nouvelle page -> 65Mo

    - fonction complète: traitement sans afficher les images -> 92Mo

    - ouverture de l'appli avec chargement d'un panorama, 2 boutons, un control image et une applicationbar -> 43,5Mo

     

    Je peux éventuellement gagner un peu si j'affiche des images redimensionnées en basse résolution mais je trouve quand même assez étrange d'avoir une si grosse consommation juste pour l ouverture de l'appli.

    Je peux te montrer le code si tu as besoin, je peux t envoyer un lien pour le télécharger en mp si tu veux pour y voir plus claire


    • Modifié Romain.P jeudi 19 janvier 2012 21:46
    jeudi 19 janvier 2012 21:41
  • Je remonte un peu mon poste.

    Après quelques conseils de Rudy et quelques autres développeurs, j'ai bien identifié la source de mes fuites mémoires et j'en ai corrigé quelques une. Malgré ça j'ai toujours la mémoire utilisé par mes 3 fonction suivante qui ne se libère pas une fois sortie de la fonction. La seule façon de la libérer c'est de fermer l'appli... Pas top !

    Si quelqu'un a une idée d'où ça peut venir, je lui en serai très reconnaissant :)

     

     

    try
                {
                    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        if (!store.DirectoryExists("Images/ColoMorph"))
                        {
                            store.CreateDirectory("Images/ColoMorph");
                        }
    
                        using (IsolatedStorageFileStream isoStream = store.OpenFile(link, FileMode.Create))
                        {
                            Extensions.SaveJpeg(
                            wb,
                            isoStream,
                            wb.PixelWidth,
                            wb.PixelHeight,
                            0,
                            100);
    
                            isoStream.Close();
                            isoStream.Dispose();
                            store.Dispose();
                        }
                    }
                }
                catch (Exception ex)
                {
                    ShowException(ex);
                }




    try
                {
                    // enregistrement dans l'IS
                    using (var myStore = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        if (myStore.FileExists("TempJPEG"))
                        {
                            myStore.DeleteFile("TempJPEG");
                        }
    
                        IsolatedStorageFileStream myFileStream = myStore.CreateFile("TempJPEG");
                        Uri uri = new Uri("ColoMorph;component/TempJPEG.jpg", UriKind.Relative);
    
                        // création du flux JPEG
                        image.SaveJpeg(myFileStream, image.PixelWidth, image.PixelHeight, 0, 100);
                        myFileStream.Close();
                        myFileStream.Dispose();
    
                        // sauvegarde de l'IS à la galerie
                        myFileStream = myStore.OpenFile("TempJPEG", FileMode.Open, FileAccess.Read);
                        myStore.Dispose();
                       
                        MediaLibrary library = new MediaLibrary();
    
                        if (source == true)
                        {
                            library.SavePictureToCameraRoll("ColoMorphCapture.jpg", myFileStream);
                        }
                        if (source == false)
                        {
                            library.SavePicture("ColoMorphPicture.jpg", myFileStream);
                        }
    
                        myFileStream.Close();
                        myFileStream.Dispose();
    
                        library.Dispose();
                    }
                }
                catch (Exception ex)
                {
                    ShowException(ex);
                }


    try
                {
                    using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        if (store.FileExists(link) == true)
                        {
                            using (IsolatedStorageFileStream isoStream = store.OpenFile(link, FileMode.Open))
                            {
                                BitmapImage bmp = new BitmapImage();
                                bmp.SetSource(isoStream);
    
                                isoStream.Close();
                                isoStream.Dispose();
    
                                store.Dispose();
                                return bmp;
                            }
                        }
                        else
                        {
                            store.Dispose();
                            return null;
                        }
                    }
                }
                catch (Exception ex)
                {
                    ShowException(ex);
                    return null;
                }


     

     

    J'ai aussi un autre petit souci, impossible d'afficher certaines images de l'interface dans mon appli lorsque je les met en contenu alors qu'elles apparaissent bien sur l'éditeur de visual studio ! La seule façon de les afficher dans l'appli est de les passer en "ressources"

    Une idée?

     

    Merci à tous

    Romain



    lundi 23 janvier 2012 22:38
  • As-tu identifié précisément quel(s) appel(s) provoque une fuite mémoire ? Ton code est "vaste", il faut isoler la partie qui consomme sans libéré (en désactivant au fur et à mesure des portion de code par exemple).

    Petite astuce concernant cette partie:

     

    MediaLibrary library = new MediaLibrary();
    
    if (source == true)
    {
       library.SavePictureToCameraRoll("ColoMorphCapture.jpg", myFileStream);
    }
    if (source == false)
    {
       library.SavePicture("ColoMorphPicture.jpg", myFileStream);
    }
    
    

    Je te recommande, dans des cas comme celui-ci (ou tu n'aura qu'un seul appel de méthode sur un objet instancié) de ne pas instancier celui-ci dans une variable, mais plutôt de le créer "à la volé" et de l'utiliser tout de suite (le GC va immédiatement libérer les ressources sans se poser de question), exemple :

     

     

    if (source == true)
       new MediaLibrary().SavePictureToCameraRoll("ColoMorphCapture.jpg", myFileStream);
    if (source == false)
       new MediaLibrary().SavePicture("ColoMorphPicture.jpg", myFileStream);
    

     


    Pour que la discussion puisse être identifiée comme résolue merci de marquer les réponses qui vous ont aidées à solutionner votre problème comme "réponse".
    mardi 24 janvier 2012 08:53
  • J'ai fait la petite modif que tu m'as donné.

    J'ai aussi forcé l'appel du GC avec des GC.Collect à la fin de chacun de mes fonctions, ce qui a fait baissé mon pique de conso mémoire à 82Mo au lieu de 125Mo

    De plus cela a rendu stable la consommation mémoire qui ne s'incrémente plus avec l'utilisation des fonctionnalités de l'appli !

    mercredi 25 janvier 2012 09:02