IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

DDMS : interprétation de Head et Allocation tracker


Sujet :

Android

  1. #1
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut DDMS : interprétation de Head et Allocation tracker
    Bonjour,

    j'ai une application qui déclenche beaucoup de GC_EXTERNAL_ALLOC ,qui, si j'ai bien compris signifie que le GC essai de récupérer de la mémoire pour de nouveaux objets.

    J'ai donc voulu utiliser les fonctions Heap et Allocation tracker du DDMS pour voir un peu ce qu'il se passe.
    Le problème étant que je ne comprend pas grand chose au résultat obtenus :

    Coté heap (voir pj) j'ai clairement 2 sources importantes de consommation mémoire , des tableaux de char et également "data object". mais à quoi cela correspond il ? "data object" à un nombre d'objet très élevé , peut être qu'il y'a moyen de travailler la dessus ?

    Coté allocation tracker(voir pj) c'est un peu plus clair. Cependant je vois beaucoup d'allocation d'une même variable au sein d'un même thread.
    Le rapport veux t'il dire que mon thread 10 consome 7x 50ko ?
    Le buffer concerné contient une image récupéré via socket puis envoyé au threadUI via message. Le thread ne devrais donc à priori pas consommer plus que la taille d'une image (en omettant les petits objets annexes )

    Extrais de l'utilisation du buffer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //Allocation d'un buffer uniquement si supérieur au précédent
    if(this.lastJpgSize < tailleJPG || this.lastJpgSize == 0 || this.datas == null)
    	this.datas		= new byte[tailleJPG];
    this.lastJpgSize = tailleJPG;
    Remplissage du buffer via la socket :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    dataRead = this.client.getReader().read(this.datas, bufferOffset, (tailleData - dataLu));
    Création de l'image
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    image = BitmapFactory.decodeByteArray(this.datas, 0, tailleJPG);
    Insertion de l'image dans un objet puis envoi de l'objet via message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Bitmap image = getImage();
    imageCam.setImage(image);
    this.message = this.handler.obtainMessage(IMAGE_AVAILABLE,imageCam);
    handler.sendMessage(this.message);
    J'ai un taux de demande d'image fixé à 10 ips , cependant une demande n'est faite qu'une fois le message précédent envoyé , je ne comprend donc pas pourquoi autant d'allocation apparaisse.

    Existe il des outils me permettant de voir clairement combien de mémoire mon application utilise et si possible quel partie du code le fait ?

    merci pour votre aide
    Images attachées Images attachées   
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  2. #2
    Expert confirmé

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Par défaut
    Bonjour,

    Déjà tu as la doc sur le DDMS ici :
    http://developer.android.com/guide/d...ging/ddms.html

    Après

    j'ai une application qui déclenche beaucoup de GC_EXTERNAL_ALLOC ,qui, si j'ai bien compris signifie que le GC essai de récupérer de la mémoire pour de nouveaux objets.
    http://stackoverflow.com/questions/4...android-logcat
    GC_FOR_MALLOC means that the GC was triggered because there wasn't enough memory left on the heap to perform an allocation. Might be triggered when new objects are being created.

    GC_EXPLICIT means that the garbage collector has been explicitly asked to collect, instead of being triggered by high water marks in the heap. Happens all over the place, but most likely when a thread is being killed or when a binder communication is taken down.

    There are a few others as well:

    GC_CONCURRENT Triggered when the heap has reached a certain amount of objects to collect.

    GC_EXTERNAL_ALLOC means that the the VM is trying to reduce the amount of memory used for collectable objects, to make room for more non-collectable.
    Après Qu'est ce que le Heap :
    http://gfx.developpez.com/tutoriel/java/gc/

    Dans la machine virtuelle, les objets naissent, vivent et meurent dans une zone mémoire appelée heap, ou tas.

    Qu'est ce que l'allocation tracker :
    DDMS provides a feature to track objects that are being allocated to memory and to see which classes and threads are allocating the objects. This allows you to track, in real time, where objects are being allocated when you perform certain actions in your application. This information is valuable for assessing memory usage that can affect application performance. If you want more granular control over where allocation data is collected, use the startAllocCounting() and stopAllocCounting() methods.

    mais à quoi cela correspond il ? "data object" à un nombre d'objet très élevé , peut être qu'il y'a moyen de travailler la dessus ?
    Cela peut correspondre à toutes allocation faites pour un objet .

    Après il faudrait que tu regardes donc dans les allocations tracker pour savoir quand cette mémoire a été allouée .


    Coté allocation tracker(voir pj) c'est un peu plus clair. Cependant je vois beaucoup d'allocation d'une même variable au sein d'un même thread.
    Le rapport veux t'il dire que mon thread 10 consome 7x 50ko ?
    Alors là je ne suis pas du tout sûr de ce que je vais te dire , mais il me semble que l'allocation tracker te montre seulement les allocation en temps réel et non les free. Ce qui veut dire que tu ne sais pas ce qui est alloué à un moment "t" via cet affichage.

    Donc cela veut dire que tu as alloué 7 * 50 Ko mais cela ne veut pas dire que tu as 7*50Ko pris en ce moment .
    Si je me rappelle on avait eu une discussion sur le reallocate ou je t'avais déjà proposé de ré-allouer si la taille grandissait , par contre comme tu alloues et non tu ré-alloues en java il faudrait vider la mémoire prise auparavant pour être plus propre ( Je pense que passer par la gestion des Array serait plus propre peut être * voir dans l'EDIT ByteArrayBuffer), ou alors allouer une taille assez importante une fois . Je ne pense pas que l'on peut forcer le gc à libérer la mémoire d'un byte . Si quelqu'un connait la méthode je suis preneur .

    Existe il des outils me permettant de voir clairement combien de mémoire mon application utilise et si possible quel partie du code le fait ?
    Il doit avoir moyen d'enrichir ce bout de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /**
             * Log Heap 
             * @param clazz the class to log the heap
             */
    	public static void logHeap(Class<?> clazz) {
    	    Double allocated = new Double(Debug.getNativeHeapAllocatedSize())/new Double((1048576));
    	    Double available = new Double(Debug.getNativeHeapSize())/new Double((1048576));
    	    Double free = new Double(Debug.getNativeHeapFreeSize())/new Double((1048576));
    	    DecimalFormat df = new DecimalFormat();
    	    df.setMaximumFractionDigits(2);
    	    df.setMinimumFractionDigits(2);
     
     
    	     Log.i("debug. =================================");
    	     Log.i("debug.heap native: allocated " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free) in [" + clazz.getName().replaceAll("com.asktingting.android.","") + "]");
    	     Log.i("debug.memory: allocated: " + df.format(new Double(Runtime.getRuntime().totalMemory()/1048576)) + "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory()/1048576))+ "MB (" + df.format(new Double(Runtime.getRuntime().freeMemory()/1048576)) +"MB free)");
    	}


    Edit :

    Le buffer concerné contient une image récupéré via socket puis envoyé au threadUI via message. Le thread ne devrais donc à priori pas consommer plus que la taille d'une image (en omettant les petits objets annexes )
    En théorie oui , sauf que le gc te videra la mémoire lorsqu'il le décidera de ce fait puisque tu fais un new[TAILLE] à chaque coup que ton image grandit tu créer donc une série d'allocation.
    Par exemple :
    Tu alloues une première fois 50 , tu alloues après une autre fois 54
    -> ce qui fait 104 au lieu de 54 au final tant que le gc n'aura pas libérer la mémoire du 50 .


    De plus après réflexion dans ma mémoire perdue tu as une classe ByteArrayBuffer qui existe elle te permettra de gérer ces ré allocation plus facilement
    http://developer.android.com/referen...rayBuffer.html

  3. #3
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Merci pour cette réponse très complète.

    Si je me rappelle on avait eu une discussion sur le reallocate ou je t'avais déjà proposé de ré-allouer si la taille grandissait
    Effectivement et c'est que je fait (?) avec le bout de code de mon message précédent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if(this.lastJpgSize < tailleJPG || this.lastJpgSize == 0 || this.datas == null)
    	this.datas		= new byte[tailleJPG];
    this.lastJpgSize = tailleJPG;
    par contre comme tu alloues et non tu ré-alloues en java il faudrait vider la mémoire prise auparavant pour être plus propre
    Pas bien compris ce que tu veux dire par là. Comment vider la mémoire avant de réallouer ?

    ou alors allouer une taille assez importante une fois
    Sachant que les données reçue peuvent aller du simple à un facteur 10 tu pense qu'il pourrait être judicieux d'allouer par exemple une fois 500ko plutôt que d'essayer d'adapter sans cesse la taille du buffer (sachant que j'ai 4 thread en parallèle et donc 4 buffers) ?

    Désolé si mes questions semblent idotes , mais le java n'est pas mon domaine de prédilection ^^
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Expert confirmé

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Par défaut
    Pas bien compris ce que tu veux dire par là. Comment vider la mémoire avant de réallouer ?
    Tu ne peux pas à partir d'un byte[] (enfin je crois), c'est là ou je voulais en venir .

    Par contre je reprends mon Edit si tu utilises ByteArrayBuffer tu éviteras tout ces problèmes nous à la non allocation à chaque fois , il te suffira te faire un append et cette classe s'en occupera pour toi .

    Sachant que les données reçue peuvent aller du simple à un facteur 10 tu pense qu'il pourrait être judicieux d'allouer par exemple une fois 500ko plutôt que d'essayer d'adapter sans cesse la taille du buffer (sachant que j'ai 4 thread en parallèle et donc 4 buffers) ?
    Oui cela serait une bonne idée , maintenant cela veut dire que pour 1 octet de plus tu serait capable de prendre 500Ko a ta heap ce qui n'est pas optimisé .

    J'insiste mais je pense que ton salut passe par la classe ByteArrayBuffer qui est à mon sens tout indiqué pour ce que tu veux faire .

    Edit :
    Attention n'utilise pas la class ByteBuffer qui elle a besoin que l'on lui donne l'allocation


    Désolé si mes questions semblent idotes , mais le java n'est pas mon domaine de prédilection ^^
    Aucun souci , il faut prendre pas mal de temps pour comprendre les gestions des mémoires . Le mieux c'est de programmer en temps réel sur des machines embarquées , pour réellement s'apercevoir de l'importance de cette partie ^^.

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    J'avais pas vu ton édit précédent , effectivement byteArrayBuffer semble tout à fait intéressant.

    il faut prendre pas mal de temps pour comprendre les gestions des mémoires
    J'en viendrait presque à regretter php ^^

    merci !
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Section <head> </head> non interprétée
    Par olive_le_malin dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 28/12/2007, 17h57
  2. outil permettant de tracker les alloc/dealloc memoire
    Par bob8181_2000 dans le forum C++Builder
    Réponses: 2
    Dernier message: 03/09/2005, 19h57
  3. Réponses: 4
    Dernier message: 03/12/2002, 16h47
  4. [Turbo Pascal] Allocation et désallocation de pointeurs dans une fonction
    Par neird dans le forum Turbo Pascal
    Réponses: 13
    Dernier message: 17/11/2002, 20h14
  5. Allocation de ressources
    Par Eric Pasquier dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 08/10/2002, 09h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo