<?xml version="1.0" encoding="utf-8"?>
<page xmlns="http://projectmallard.org/1.0/" type="guide" style="task" id="massif" xml:lang="el">
    <info>
      <link type="guide" xref="index#massif"/>
    
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Ελληνική μεταφραστική ομάδα GNOME</mal:name>
      <mal:email>team@gnome.gr</mal:email>
      <mal:years>2009-2015</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Δημήτρης Σπίγγος</mal:name>
      <mal:email>dmtrs32@gmail.com</mal:email>
      <mal:years>2013</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Γιάννης Κατσαμπίρης</mal:name>
      <mal:email>giannis1_86@hotmail.com</mal:email>
      <mal:years>2010</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Σίμος Ξενιτέλλης</mal:name>
      <mal:email>simos@gnome.org</mal:email>
      <mal:years>2009</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Κωνσταντίνος Κουράτορας</mal:name>
      <mal:email>kouratoras@gmail.com</mal:email>
      <mal:years>2010</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Σωτηρία Τζιούρη</mal:name>
      <mal:email>sotitz@gmail.com</mal:email>
      <mal:years>2010</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Τζένη Πετούμενου</mal:name>
      <mal:email>epetoumenou@gmail.com</mal:email>
      <mal:years>2009</mal:years>
    </mal:credit>
  
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
      <mal:name>Τουρνάρης Παύλος-Πέτρος</mal:name>
      <mal:email>p.tournaris@gmail.com</mal:email>
      <mal:years>2010</mal:years>
    </mal:credit>
  </info>
      <title>Χρησιμοποιήστε το <app>Massif</app> για την χρήσης της μνήμης κατατομής σε εφαρμογές του GNOME</title>

    <p>Αυτό το άρθρο περιγράφει πώς χρησιμοποιείται ο σωρός κατατομών <app>Massif</app> με εφαρμογές του GNOME. Περιγράφουμε πώς να τον καλέσετε, να τον ερμηνεύσετε και πώς να ενεργήσετε βάσει των αποτελεσμάτων του <app>Massif</app>. Ως παράδειγμα χρησιμοποιούμε το παιχνίδι <app>Swell Foop</app>.</p>
   <section id="optimization-massif-TBL-intro">
        <title>Εισαγωγή</title>
        <p>Η <app>Massif</app> είναι μέλος της σειράς <link href="http://valgrind.org/">valgrind</link> για εργαλεία κατατομής μνήμης. Ο σκοπός του είναι να δίνει μια λεπτομερή προβολή της δυναμικής χρήσης της μνήμης κατά τη διάρκεια του χρόνου ζωής ενός προγράμματος. Συγκεκριμένα, καταγράφει τη χρήση της μνήμης από το σωρό και τη στοίβα.</p>
        <p>Ο σωρός είναι η περιοχή στη μνήμη η οποία κατανέμεται με συναρτήσεις όπως η malloc. Μεγαλώνει κατά απαίτηση και είναι συνήθως η μεγαλύτερη περιοχή της μνήμης σε ένα πρόγραμμα. Η στοίβα είναι εκεί όπου αποθηκεύονται όλα τα τοπικά δεδομένα για τις συναρτήσεις. Αυτό συμπεριλαμβάνει τις "αυτόματες" μεταβλητές στη C και τη διεύθυνση επιστροφής για τις υπορουτίνες. Η στοίβα είναι τυπικά πολύ μικρότερη και πολύ πιο ενεργή από το σωρό. Δε θα ασχοληθούμε ειδικά με τη στοίβα μια που το <app>Massif</app> την αντιμετωπίζει σαν να ήταν μέρος του σωρού. Το <app>Massif</app> παρέχει επίσης πληροφορίες για την ποσότητα της μνήμης που χρησιμοποιείται για τη διαχείριση του σωρού.</p>
        <p>Η <app>Massif</app> παράγει δύο αρχεία εξόδου: μια γραφική επισκόπηση σε ένα αρχείο postscript και μια λεπτομερή ανάλυση σε ένα αρχείο κειμένου.</p>
    </section>
    <section id="optimization-massif-TBL-using-massif">
        <title>Χρήση της <app>Massif</app> με το GNOME</title>
        <p>Η <app>Massif</app> έχει πολύ λίγες επιλογές και για τα περισσότερα προγράμματα δεν τις χρειάζεστε. Εντούτοις για της εφαρμογές του GNOME, όπου η κατανομή μνήμης μπορεί να θαφτεί βαθιά στο glib ή στο GTK, ο αριθμός επιπέδων κάτω από την στοίβα κλήσεων που η Massif κατεβαίνει θα πρέπει να αυξηθεί. Αυτό είναι γίνεται χρησιμοποιώντας την παράμετρο --depth. Εξ ορισμού αυτό είναι ίσο με 3· αυξάνοντας το σε 5 εγγυάται ότι η στοίβα κλήσεων θα φθάσει στον κώδικά σας. Ένα ή δύο περισσότερα επίπεδα μπορούν επίσης να είναι επιθυμητά και να παρέχουν στον κώδικά σας κάποιο πλαίσιο εφαρμογής. Δεδομένου ότι το επίπεδο λεπτομέρειας γίνεται γρήγορα συντριπτικό είναι καλύτερο να αρχίσει με μικρότερη παράμετρο βάθους και να το αυξήστε μόνο όταν γίνεται προφανές ότι αυτό δεν είναι ικανοποιητικό.</p>
        <p>Είναι επίσης χρήσιμο να πείτε στο <app>Massif</app> ποιες συναρτήσεις δεσμεύουν χώρο στη μνήμη μέσω του glib. Αφαιρεί ένα περιττό στρώμα κλήσεων συναρτήσεων από τις αναφορές και σας δίνει μια σαφέστερη ιδέα ποιος κώδικας δεσμεύει χώρο στην μνήμη. Οι συναρτήσεις δέσμευσης χώρου μνήμης μέσω του glib είναι οι g_malloc, g_malloc0, g_realloc, g_try_malloc, και g_mem_chunk_alloc. Χρησιμοποιήστε την επιλογή --alloc-fn για να ενημερώστε το Masiff για αυτές.</p>
        <p>Η γραμμή-εντολών σας πρέπει επομένως να μοιάζει κάπως σαν:</p>
        <code>
valgrind --tool=massif --depth=5  --alloc-fn=g_malloc --alloc-fn=g_realloc --alloc-fn=g_try_malloc \
         --alloc-fn=g_malloc0 --alloc-fn=g_mem_chunk_alloc swell-foop
        </code>
        <p>Το <app>Swell Foop</app> είναι το πρόγραμμα που θα χρησιμοποιούμε σαν παράδειγμα. Σας προειδοποιούμε ότι, από την στιγμή που ο valgrind θα εξομοιώνει την ΚΜΕ, θα λειτουργεί <em>πολύ</em> αργά. Θα χρειαστείτε επίσης πολλή μνήμη.</p>
    </section>
    <section id="optimization-massif-TBL-interpreting-results">
        <title>Ερμηνεία των αποτελεσμάτων</title>
        <p>Η γραφική έξοδος δεδομένων του <app>Massif</app> είναι κατά ένα μεγάλο μέρος αυτοεπεξηγηματικός. Κάθε ζώνη αντιπροσωπεύει τη μνήμη που διατίθεται από μια λειτουργία σε σχέση με τον χρόνο. Μόλις προσδιορίσετε ποιες ζώνες χρησιμοποιούν την περισσότερη μνήμη, συνήθως οι μεγάλες παχιές ζώνες στην κορυφή, θα πρέπει να συμβουλευθείτε το αντίστοιχο αρχείο κειμένου για περισσότερες λεπτομέρειες.</p>
        <p>Τα αρχεία κειμένων τακτοποιούνται ιεραρχικά βάση των τμημάτων, στην κορυφή είναι μία λίστα των χειρότερων χρηστών μνήμης που τακτοποιούνται κατά σειρά βάση την μείωση του χωροχρόνου. Κάτω από αυτά είναι και άλλα τμήματα, κάθε ένα διαιρεί τα αποτελέσματα σε μικρότερες λεπτομέρειες καθώς προχωράτε προς τη στοίβα κλήσεων. Για να επεξηγήσουμε αυτό θα χρησιμοποιήσουμε την έξοδος δεδομένων της εντολής παραπάνω.</p>
        <figure>
            <title>Έξοδος δεδομένων του <app>Massif</app> για την μη-βελτιστοποιημένη έκδοση του προγράμματος <app>Swell Foop</app>.</title>
            <media type="image" src="figures/massif-before.png"/>
         </figure>
        <p>Η εικόνα παραπάνω παρουσιάζει μία χαρακτηριστική έξοδο δεδομένων σε μορφή postscript από το <app>Massif</app>. Αυτό είναι το αποτέλεσμα που θα παίρνατε παίζοντας μία πίστα από το παιχνίδι <app>Swell Foop</app> (έκδοση 2.8.0) και έπειτα το κλείνατε. Το αρχείο postscript θα έχει ένα όνομα όπως <file>massif.12345.ps</file> και το αρχείο κειμένων θα ονομάζεται <file>massif.12345.txt</file>. Ο αριθμός στη μέση είναι η ταυτότητα διαδικασίας του προγράμματος που εξετάστηκε. Εάν δοκιμάσετε πραγματικά αυτό το παράδειγμα θα βρείτε δύο εκδόσεις κάθε αρχείου, με ελαφρά διαφορετικούς νούμερα, αυτό συμβαίνει γιατί το <app>Swell Foop</app> ξεκινά μια δεύτερη διαδικασία και το <app>Massif</app> ακολουθεί και αυτή επίσης. Θα αγνοήσουμε αυτήν την δεύτερη διαδικασία, μια που καταναλώνει πολύ λίγη μνήμη.</p>
        <p>Στην κορυφή της γραφικής παράστασης βλέπουμε μια μεγάλη κίτρινη ζώνη με τίτλο gdk_pixbuf_new. Αυτό φαίνεται ως ένας ιδανικός υποψήφιος για βελτιστοποίηση, αλλά θα πρέπει να χρησιμοποιήσουμε το αρχείο κειμένων για να ανακαλύψουμε τι καλεί το gdk_pixbuf_new. Στην κορυφή του αρχείου κειμένων θα εμφανίζεται κάτι σαν το επόμενο:</p>
        <code>
Εντολή: ./swell-foop

== 0 ===========================
Συναρτήσεις κατανομής σωρών που καταμετρήθηκαν ως το 90.4% από το μετρήσιμο χωρόχρoνο

Καλείται από:
  28.8% : 0x6BF83A: gdk_pixbuf_new (in /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)

    6.1% : 0x5A32A5: g_strdup (στο /usr/lib/libglib-2.0.so.0.400.6)

    5.9% : 0x510B3C: (μέσα στο /usr/lib/libfreetype.so.6.3.7)

    3.5% : 0x2A4A6B: __gconv_open (στο /lib/tls/libc-2.3.3.so)
        </code>
        <p>Η γραμμή με το σύμβολο του '=' δείχνει πόσο βαθιά κάτω είμαστε στο ίχνος στοίβας, σε αυτήν την περίπτωση είμαστε στην κορυφή. Μετά από αυτό απαριθμεί τους βαρύτερους χρήστες της μνήμης έτσι ώστε να μειωθεί ο χωρόχρονος. Ο χωρόχρονος είναι το λόγος του ποσού της μνήμης που χρησιμοποιείται και του χρόνου χρησιμοποίησης του. Αντιστοιχεί στον περιοχή των ζωνών στη γραφική παράσταση. Αυτό το μέρος του αρχείου μας λέει αυτό που ξέρουμε ήδη: το μεγαλύτερο μέρος του χωροχρόνου αφιερώνεται στο gdk_pixbuf_new. Για να ανακαλύψουν τι κάλεσε το gdk_pixbuf_new πρέπει να ψάξουμε περαιτέρω μέσα στο αρχείο κειμένου:</p>
        <code>
== 4 ===========================
Πλαίσιο καταμέτρησης για το 28.8% του υπολογίσιμου χωροχρόνου
  0x6BF83A: gdk_pixbuf_new (στο /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
  0x3A998998: (μέσα στο /usr/lib/gtk-2.0/2.4.0/loaders/libpixbufloader-png.so)
  0x6C2760: (μέσα στο /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
  0x6C285E: gdk_pixbuf_new_from_file (στο /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)

Καλείται από:
  27.8% : 0x804C1A3: load_scenario (swell-foop.c:463)

    0.9% : 0x3E8095E: (μέσα στο /usr/lib/libgnomeui-2.so.0.792.0)

  και 1 άλλη ασήμαντη θέση
        </code>
        <p>Η πρώτη γραμμή μας λέει ότι είμαστε τώρα τέσσερα επίπεδα βαθιά μέσα στη στοίβα. Από κάτω βρίσκεται η λίστα των κλήσεων λειτουργίας που μας οδηγεί από εδώ στο gdk_pixbuf_new. Τελικά υπάρχει μία λίστα λειτουργιών που είναι στο επόμενο κάτω επίπεδο και καλούν αυτές τις λειτουργίες. Υπάρχουν, φυσικά, καταχωρίσεις για τα επίπεδα 1, 2, και 3, αλλά αυτό είναι το πρώτο επίπεδο που φθάνει ακριβώς στον κώδικα GDK του <app>Swell Foop</app>. Από αυτήν την λίστα, μπορούμε να δούμε αμέσως ότι ο προβληματικός κώδικας είναι ο load_scenario.</p>
        <p>Τώρα που ξέρουμε ποιο μέρος του κώδικά μας χρησιμοποιεί όλο χωρόχρονο μπορούμε να εξετάσουμε και να ανακαλύψουμε το γιατί. Ως αποτέλεσμα βλέπουμε ότι το load_scenario φορτώνει την pixbuf από ένα αρχείο και έπειτα δεν απελευθερώνει ποτέ την μνήμη. Αφού προσδιορίσαμε τον προβληματικό κώδικα, μπορούμε να αρχίσουμε να τον διορθώνουμε.</p>
    </section>
    <section id="optimization-massif-TBL-acting-on-results">
        <title>Ενέργειες πάνω στα αποτελέσματα</title>
        <p>Μειώνοντας την κατανάλωση του χωροχρόνου είναι κάτι καλό, αλλά υπάρχουν δύο τρόποι για την μείωση του που δεν είναι ισότιμες. Μπορείτε είτε να μειώσετε το ποσό μνήμης που διατίθεται, ή μειώστε το χρονικό διάστημα που του διατίθεται. Εξετάστε για μια στιγμή ένα πρότυπο σύστημα με μόνο δύο διαδικασίες ενεργές. Και οι δύο διαδικασίες καταναλώνουν σχεδόν όλη την φυσική μνήμη RAM και εάν κάποια στιγμή επικαλύψει η μία την άλλη το σύστημα θα κάνει αντιμετάθεση και όλα θα επιβραδύνουν. Προφανώς εάν μειώνουμε τη χρήση μνήμης σε κάθε διαδικασία με παράγοντα του δύο θα μπορούν ειρηνικά να συνυπάρξουν χωρίς την ανάγκη για αντιμετάθεση. Εάν αντ' αυτού μειώσουμε το χρόνο που διατίθεται η μνήμη με παράγοντα του δύο τότε τα δύο προγράμματα μπορούν να συνυπάρξουν, αλλά μόνο εφ' όσον οι περίοδοι υψηλής χρήσης της μνήμης τους δεν επικαλύπτονται. Έτσι είναι καλύτερο να μειωθεί το ποσό μνήμης που διατίθεται.</p>
        <p>Δυστυχώς, η επιλογή της βελτιστοποίησης περιορίζεται επίσης από τις ανάγκες του προγράμματος. Το μέγεθος των δεδομένων του pixbuf στο <app>Swell Foop</app> καθορίζεται από το μέγεθος των γραφικών του παιχνιδιού και δεν μπορεί να μειωθεί εύκολα. Εντούτοις, το χρονικό διάστημα που ξοδεύει κατά την φόρτωση του στη μνήμη μπορεί να μειωθεί δραστικά. Η παραπάνω εικόνα παρουσιάζει την ανάλυση του <app>Massif</app> για το <app>Swell Foop</app> μετά από την αλλαγή του για να απορρίπτει τα pixbufs μόλις φορτωθούν οι εικόνες στον διακομιστή X.</p>
        <figure>
            <title>Έξοδος του <app>Massif</app> για την βελτιστοποιημένο πρόγραμμα <app>Swell Foop</app>.</title>
           <media type="image" src="figures/massif-after.png"/>
            </figure>
        <p>Η χρήση του χωροχρόνου από το gdk_pixbuf_new είναι τώρα μια λεπτή ζώνη που έχει σύντομες αναλαμπές (είναι τώρα η δέκατη έκτη ζώνη και βαθυπόρφυρη απόχρωση). Σαν πρόσθετο χαρακτηριστικό, η μέγιστη χρήση μνήμης έχει ελαττωθεί κατά 200 kB δεδομένου ότι η αιχμή εμφανίζεται πριν δεσμευτεί η μνήμη. Εάν δύο διαδικασίες όπως αυτή εκτελούνται από κοινού οι πιθανότητες της μέγιστης χρήσης μνήμης συμπίπτουν, και ως εκ τούτου ο κίνδυνος αντιμετάθεσης, θα είναι αρκετά χαμηλός.</p>
        <p>Μπορούμε να το κάνουμε καλύτερα; Μια γρήγορη εξέταση της εξόδου κειμένου του <app>Massif</app> αποκαλύπτει ότι: το g_strdup είναι ο νέος σημαντικός ένοχος.</p>
        <code>
Εντολή: ./swell-foop

== 0 ===========================
Συναρτήσεις κατανομής σωρών που καταμετρήθηκαν ως το 87.6% από το μετρήσιμο χωρόχρονο

Καλείται από:
    7.7% : 0x5A32A5: g_strdup (στο /usr/lib/libglib-2.0.so.0.400.6)

    7.6% : 0x43BC9F: (μέσα στο /usr/lib/libgdk-x11-2.0.so.0.400.9)

    6.9% : 0x510B3C: (μέσα στο /usr/lib/libfreetype.so.6.3.7)

    5.2% : 0x2A4A6B: __gconv_open (στο /lib/tls/libc-2.3.3.so)
        </code>
        <p>Εάν το εξετάσουμε ποιο ενδελεχώς θα δούμε ότι καλείται από πολλές, πολλές, διαφορετικές θέσεις.</p>
        <code>
== 1 ===========================
Πλαίσιο καταμέτρησης για το 7.7% του υπολογίσιμου χωροχρόνου
  0x5A32A5: g_strdup (στο /usr/lib/libglib-2.0.so.0.400.6)

Κλήθηκε από:
    1.8% : 0x8BF606: gtk_icon_source_copy (στο /usr/lib/libgtk-x11-2.0.so.0.400.9)

    1.1% : 0x67AF6B: g_param_spec_internal (στο /usr/lib/libgobject-2.0.so.0.400.6)

    0.9% : 0x91FCFC: (μέσα στο /usr/lib/libgtk-x11-2.0.so.0.400.9)

    0.8% : 0x57EEBF: g_quark_from_string (στο /usr/lib/libglib-2.0.so.0.400.6)

  και 155 άλλες ασήμαντες θέσεις
        </code>
        <p>Τώρα αντιμετωπίζουμε την ελάττωση της ανταμοιβή μας για τις προσπάθειες βελτιστοποίησής. Οι συμβουλές γραφικών παραστάσεων είναι μια άλλη πιθανή προσέγγιση: Και οι δύο ζώνες "other" και "heap admin" είναι αρκετά μεγάλες. Αυτό μας λέει ότι υπάρχουν πολλές μικρές κατανομές που έχουν γίνει από ποικίλες θέσεις. Η εξάλειψη τους θα είναι δύσκολη, αλλά εάν μπορέσουν να ομαδοποιηθούν τότε οι μεμονωμένες κατανομές μπορούν να γίνουν μεγαλύτερες και η επιβάρυνση του "heap admin" μπορεί να μειωθεί.</p>
    </section>
    <section id="optimization-massif-TBL-caveats">
        <title>Προειδοποιήσεις</title>
        <p>Υπάρχουν μερικά πράγματα που θα πρέπει να προσέξετε: Αρχικά, ο χωρόχρονος εμφανίζεται μόνο ως ποσοστό, πρέπει να το συγκρίνετε με το γενικό μέγεθος του προγράμματος για να αποφασίσει εάν το ποσό μνήμης αξίζει να δαπανηθεί. Η γραφική παράσταση, με τον κάθετο άξονα σε kilobyte, είναι ιδανικό για κάτι τέτοιο.</p>
        <p>Αφετέρου, το <app>Massif</app> λαμβάνει υπόψη μόνο τη μνήμη που χρησιμοποιείται από τα προγράμματα σας. Οι πόροι όπως τα pixmaps αποθηκεύονται στον διακομιστή X και δεν εξετάζονται από το <app>Massif</app>. Στο παράδειγμα με το <app>Swell Foop</app> στην πραγματικότητα έχουμε μετακινήσει την κατανάλωση μνήμης μόνο την pixbufs από την πλευρά του προγράμματος πελάτη στα pixmaps από την πλευρά του διακομιστή. Αν και κάναμε μία μικρή απάτη, υπάρχουν κέρδη στην απόδοση. Αν κρατήσουμε τα δεδομένα εικόνας του διακομιστή X καθιστά τις ρουτίνες γραφικής αναπαράστασης γρηγορότερες και αφαιρεί πολύ διεπεξεργαστική επικοινωνία. Επίσης, τα pixmaps θα αποθηκευτούν σε μία εγγενή μορφή γραφικών που είναι συχνά συμπαγέστερο από τη μορφή 32-δυαδικών RGBA που χρησιμοποιείται από το gdk_pixbuf. Για να μετρηθεί η επίδραση των pixmaps και άλλων πόρων του διακομιστή X χρησιμοποιήστε το πρόγραμμα <link href="http://www.freedesktop.org/Software/xrestop">xrestop</link>.</p>
    </section>
</page>
