Blame optimization-guide/gl/massif.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" type="guide" style="task" id="massif" xml:lang="gl">
Packit 1470ea
    <info>
Packit 1470ea
      <link type="guide" xref="index#massif"/>
Packit 1470ea
    
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Fran Dieguez</mal:name>
Packit 1470ea
      <mal:email>frandieguez@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2011-2013.</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
      <title>Using <app>Massif</app> for Profiling Memory Use in GNOME Software</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
        This article describes how to use the <app>Massif</app> heap profiler with GNOME applications. We describe how to invoke, interpret, and act on the output of <app>Massif</app>. The <app>Swell Foop</app> game is used as an example. 

Packit 1470ea
   <section id="optimization-massif-TBL-intro">
Packit 1470ea
        <title>Introdución</title>
Packit 1470ea
        

Packit 1470ea
            <app>Massif</app> is a member of the <link href="http://valgrind.org/">valgrind</link> suite of memory-profiling tools. Its purpose is to give a detailed view of dynamic memory usage during the lifetime of the program. Specifically it records the memory use of the heap and the stack.
Packit 1470ea
        

Packit 1470ea
        

Packit 1470ea
            The heap is the region of memory which is allocated with functions like malloc. It grows on demand and is usually the largest region of memory in a program. The stack is where all the local data for functions is stored. This includes the "automatic" variables in C and the return address for subroutines. The stack is typically a lot smaller and a lot more active than the heap. We won't consider the stack explicitly since <app>Massif</app> treats it as though it were just another part of the heap. <app>Massif</app> also gives information about how much memory is used to manage the heap.  

Packit 1470ea
        

Packit 1470ea
            <app>Massif</app> produces two output files: a graphical overview in a postscript file and a detailed breakdown in a text file.
Packit 1470ea
        

Packit 1470ea
    </section>
Packit 1470ea
    <section id="optimization-massif-TBL-using-massif">
Packit 1470ea
        <title>Using <app>Massif</app> with GNOME</title>
Packit 1470ea
        

Packit 1470ea
          <app>Massif</app> has very few options and for many programs does not need them. However for GNOME applications, where memory allocation might be buried deep in either glib or GTK, the number of levels down the call-stack Massif descends needs to be increased. This is achieved using the --depth parameter. By default this is 3; increasing it to 5 will guarantee the call-stack reaches down to your code. One or two more levels may also be desirable to provide your code with some context. Since the level of detail becomes quickly overwhelming it is best to start with the smaller depth parameter and only increase it when it becomes apparent that it isn't sufficient.
Packit 1470ea
        

Packit 1470ea
        

Packit 1470ea
            It is also useful to tell <app>Massif</app> which functions allocate memory in glib. It removes an unnecessary layer of function calls from the reports and gives you a clearer idea of what code is allocating memory. The allocating functions in glib are g_malloc, g_malloc0, g_realloc, g_try_malloc, and g_mem_chunk_alloc. You use the --alloc-fn option to tell Massif about them.
Packit 1470ea
        

Packit 1470ea
        

A súa liña de orde debería semellarse a esta:

Packit 1470ea
        
Packit 1470ea
valgrind --tool=massif --depth=5  --alloc-fn=g_malloc --alloc-fn=g_realloc --alloc-fn=g_try_malloc \
Packit 1470ea
         --alloc-fn=g_malloc0 --alloc-fn=g_mem_chunk_alloc swell-foop
Packit 1470ea
        
Packit 1470ea
        

Packit 1470ea
            <app>Swell Foop</app> is the program we will be using as an example. Be warned that, since valgrind emulates the CPU, it will run very slowly. You will also need a lot of memory. 

Packit 1470ea
    </section>
Packit 1470ea
    <section id="optimization-massif-TBL-interpreting-results">
Packit 1470ea
        <title>Interpretar os resultados</title>
Packit 1470ea
        

Packit 1470ea
            The graphical output of <app>Massif</app> is largely self explanatory. Each band represents the memory allocated by one function over time. Once you identify which bands are using the most memory, usually the big thick ones at the top you will have to consult the text file for the details.
Packit 1470ea
        

Packit 1470ea
        

O ficheiro de texto está ordenado como unha xerarquía por seccións, na parte superior está unha lista dos peores usuarios da memoria para reducir o espazotempo. Máis abaixo de isto están as seguintes sección, cada unha delas dividindo os resultados en maior detalle como se procedera cara abaixo na pila de chamadas. Para ilustrar isto usaremos a saída da orde de arriba.

Packit 1470ea
        <figure>
Packit 1470ea
            <title><app>Massif</app> output for the unoptimized version of the <app>Swell Foop</app> program.</title>
Packit 1470ea
            <media type="image" src="figures/massif-before.png"/>
Packit 1470ea
         </figure>
Packit 1470ea
        

Packit 1470ea
            The image above shows a typical postscript output from
Packit 1470ea
            <app>Massif</app>. This is the result you would get from
Packit 1470ea
            playing a single game of <app>Swell Foop</app> (version
Packit 1470ea
            2.8.0) and then quitting. The postscript file will have a
Packit 1470ea
            name like <file>massif.12345.ps</file> and the text file
Packit 1470ea
            will be called <file>massif.12345.txt</file>. The number
Packit 1470ea
            in the middle is the process ID of the program that was
Packit 1470ea
            examined. If you actually try this example you will find
Packit 1470ea
            two versions of each file, with slightly different
Packit 1470ea
            numbers, this is because <app>Swell Foop</app> starts a
Packit 1470ea
            second process and <app>Massif</app>
Packit 1470ea
            follows that too. We will ignore this second process, it
Packit 1470ea
            consumes very little memory.

Packit 1470ea
        

Na parte superior da gráfica vese unha gran banda amarela etiquetada como gdk_pixbuf_new. Semella un candidato ideal para a optimización, pero precisarase usar o ficheiro de texto para topar que está chamando a gdk_pixbuf_new. A parte superior do ficheiro de texto mostrará algo como o seguinte:

Packit 1470ea
        
Packit 1470ea
Command: ./swell-foop
Packit 1470ea
Packit 1470ea
== 0 ===========================
Packit 1470ea
Heap allocation functions accounted for 90.4% of measured spacetime
Packit 1470ea
Packit 1470ea
Called from:
Packit 1470ea
  28.8% : 0x6BF83A: gdk_pixbuf_new (in /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
Packit 1470ea
Packit 1470ea
    6.1% : 0x5A32A5: g_strdup (in /usr/lib/libglib-2.0.so.0.400.6)
Packit 1470ea
Packit 1470ea
    5.9% : 0x510B3C: (within /usr/lib/libfreetype.so.6.3.7)
Packit 1470ea
Packit 1470ea
    3.5% : 0x2A4A6B: __gconv_open (in /lib/tls/libc-2.3.3.so)
Packit 1470ea
        
Packit 1470ea
        

Packit 1470ea
            The line with the '=' signs indicates how far down the stack trace we are, in this case we are at the top. After this it lists the heaviest users of memory in order of decreasing spacetime. Spacetime is the product of the amount of memory used and how long it was used for. It corresponds to the area of the bands in the graph. This part of the file tells us what we already know: most of the spacetime is dedicated to gdk_pixbuf_new. To find out what called gdk_pixbuf_new we need to search further down the text file:
Packit 1470ea
        

Packit 1470ea
        
Packit 1470ea
== 4 ===========================
Packit 1470ea
Context accounted for 28.8% of measured spacetime
Packit 1470ea
  0x6BF83A: gdk_pixbuf_new (in /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
Packit 1470ea
  0x3A998998: (within /usr/lib/gtk-2.0/2.4.0/loaders/libpixbufloader-png.so)
Packit 1470ea
  0x6C2760: (within /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
Packit 1470ea
  0x6C285E: gdk_pixbuf_new_from_file (in /usr/lib/libgdk_pixbuf-2.0.so.0.400.9)
Packit 1470ea
Packit 1470ea
Called from:
Packit 1470ea
  27.8% : 0x804C1A3: load_scenario (swell-foop.c:463)
Packit 1470ea
Packit 1470ea
    0.9% : 0x3E8095E: (within /usr/lib/libgnomeui-2.so.0.792.0)
Packit 1470ea
Packit 1470ea
  and 1 other insignificant place
Packit 1470ea
        
Packit 1470ea
        

Packit 1470ea
            The first line tells us we are now four levels deep into the stack. Below it is a listing of the function calls that leads from here to gdk_pixbuf_new. Finally there is a list of functions that are at the next level down and call these functions. There are, of course, also entries for levels 1, 2, and 3, but this is the first level to reach right down through the GDK code to the <app>Swell Foop</app> code. From this listing, we can see instantly that the problem code is load_scenario.
Packit 1470ea
        

Packit 1470ea
        

Agora que sabe que parte do código usa todo o espazo de tempo pódese buscar o porque. Resulta que load_scenario está cargando un pixbuf dun ficheiro e nunca libera esa memoria. Tendo identificado o código do problema pódese comezar a arranxalo.

Packit 1470ea
    </section>
Packit 1470ea
    <section id="optimization-massif-TBL-acting-on-results">
Packit 1470ea
        <title>Actuar sobre os resultados</title>
Packit 1470ea
        

Reducir o consumo do espazo de tempo é bo, pero hai dúas formas de reducilo e non son iguais. Pode tanto reducir a cantidade de memoria reservada como reducir a cantidade de tempo na que está reservada. Considere por un momento un sistema modelo con só dous procesos executándose. Ámbolos dous procesos usan case toda a RAM física e superpóñense por completo polo que o sistema terá que usar a swap e todo se ralentizará. Se no lugar disto reducimos o tempo que está reservada a memoria por un factor de dous entón os dous programas poden coexistir, pero mentres os seus períodos de alto uso de memoria non se superpoñan. Polo tanto é mellor reducir o consumo de memoria reservada.

Packit 1470ea
        

Packit 1470ea
            Unfortunately, the choice of optimization is also
Packit 1470ea
	    constrained by the needs of the program. The size of the
Packit 1470ea
	    pixbuf data in <app>Swell Foop</app> is determined by the
Packit 1470ea
	    size of the game's graphics and cannot be easily
Packit 1470ea
	    reduced. However, the amount of time it spends loaded into
Packit 1470ea
	    memory can be drastically reduced. The image below shows the <app>Massif</app> analysis of <app>Swell Foop</app> after being altered to dispose of the pixbufs once the images have been loaded into the X server.
Packit 1470ea
        

Packit 1470ea
        <figure>
Packit 1470ea
            <title><app>Massif</app> output for the optimized <app>Swell Foop</app> program.</title>
Packit 1470ea
           <media type="image" src="figures/massif-after.png"/>
Packit 1470ea
            </figure>
Packit 1470ea
        

O uso do espazo de tempo do gdk_pixbuf_new é agora unha banda máis estreita que só ten picos moi brebes (agora é a dezaseisava banda e pintada en maxenta). Ademáis, o pico de uso de memoria baixou 200 kB xa que o pico se produce antes de que se reserve outra memoria. Se dous procesos como este estiveran executándose á vez as opcións dun pico de uso de memoria coincidente, e polo tanto o risco de facer swapping, serán moi poucas.

Packit 1470ea
        

Packit 1470ea
            Can we do better ? A quick examination of <app>Massif</app>'s text output reveals: g_strdup to be the new major offender.
Packit 1470ea
        

Packit 1470ea
        
Packit 1470ea
Command: ./swell-foop
Packit 1470ea
Packit 1470ea
== 0 ===========================
Packit 1470ea
Heap allocation functions accounted for 87.6% of measured spacetime
Packit 1470ea
Packit 1470ea
Called from:
Packit 1470ea
    7.7% : 0x5A32A5: g_strdup (in /usr/lib/libglib-2.0.so.0.400.6)
Packit 1470ea
Packit 1470ea
    7.6% : 0x43BC9F: (within /usr/lib/libgdk-x11-2.0.so.0.400.9)
Packit 1470ea
Packit 1470ea
    6.9% : 0x510B3C: (within /usr/lib/libfreetype.so.6.3.7)
Packit 1470ea
Packit 1470ea
    5.2% : 0x2A4A6B: __gconv_open (in /lib/tls/libc-2.3.3.so)
Packit 1470ea
        
Packit 1470ea
        

Se miramos máis cerca nas partes que vemos se chaman desde moitas partes.

Packit 1470ea
        
Packit 1470ea
== 1 ===========================
Packit 1470ea
Context accounted for  7.7% of measured spacetime
Packit 1470ea
  0x5A32A5: g_strdup (in /usr/lib/libglib-2.0.so.0.400.6)
Packit 1470ea
Packit 1470ea
Called from:
Packit 1470ea
    1.8% : 0x8BF606: gtk_icon_source_copy (in /usr/lib/libgtk-x11-2.0.so.0.400.9)
Packit 1470ea
Packit 1470ea
    1.1% : 0x67AF6B: g_param_spec_internal (in /usr/lib/libgobject-2.0.so.0.400.6)
Packit 1470ea
Packit 1470ea
    0.9% : 0x91FCFC: (within /usr/lib/libgtk-x11-2.0.so.0.400.9)
Packit 1470ea
Packit 1470ea
    0.8% : 0x57EEBF: g_quark_from_string (in /usr/lib/libglib-2.0.so.0.400.6)
Packit 1470ea
Packit 1470ea
  and 155 other insignificant places
Packit 1470ea
        
Packit 1470ea
        

Agora encárase a redución da saída para os esforzos de optimización. O gráfico suxire outra posíbel aproximación: tanto a banda «other» como a «heap admin» son bastante largas. Isto quere dicir que existen moitas pequenas reservas realizadas desde certa variedade de sitios. Eliminalos será difícil, pero se se poden agrupar, entón as reservas son individuais poden ser máis grandes e a elevada banda «heap admin» pode reducirse.

Packit 1470ea
    </section>
Packit 1470ea
    <section id="optimization-massif-TBL-caveats">
Packit 1470ea
        <title>Advertencias</title>
Packit 1470ea
        

Existen un par de cousas para ter en conta: Primeiramente, só se informa do espazo de tempo como porcentaxe, ten que comparalo co tamaño total do programa para decidir se merece a pena perseguir a cantidade total de memoria. O gráfico, co seu eixe vertical de kilobytes, é bo para iso.

Packit 1470ea
        

Packit 1470ea
            Secondly, <app>Massif</app> only takes into account the memory used by your own program. Resources like pixmaps are stored in the X server and aren't considered by <app>Massif</app>. In the <app>Swell Foop</app> example we have actually only moved the memory consumption from client-side pixbufs to server-side pixmaps. Even though we cheated there are performance gains. Keeping the image data in the X server makes the graphics routines quicker and removes a lot of inter-process communication. Also, the pixmaps will be stored in a native graphics format which is often more compact than the 32-bit RGBA format used by gdk_pixbuf. To measure the effect of pixmaps, and other X resources use the <link href="http://www.freedesktop.org/Software/xrestop">xrestop</link> program.
Packit 1470ea
        

Packit 1470ea
    </section>
Packit 1470ea
</page>