wiki:Documentatie/Ontwikkelaar/Omgeving/Performance

Version 1 (modified by adriaan, 14 years ago) (diff)

--

Metingen

(ook iets als "kwantitatieve software evaluatie")

Om metingen op OpenAC zelf uit te kunnen voeren om zo een kwantitatief beeld te krijgen van de software, hebben we tools nodig om getallen te produceren op basis van de software. Deze pagina beschrijft sommige beschikbare en gebruikte tools.

Geheugengebruik

Het meest nauwkeurig voor geheugenmeting in Python onder Linux is heapy, een tool om (interactief) de Python heap te onderzoeken. De handleiding voor heapy is nogal summier, maar er zit veel in de help binnen de module zelf. Met heapy kan je kijken hoeveel geheugen er gebruikt wordt, wat voor types het heeft, en ook zien welke veranderingen in het geheugen gebeuren als je bepaalde functionaliteit aanroept.

Installatie van Heapy

Instructies voor OpenSUSE

  • zypper in python-devel
  • Je moet guppy waarschijnlijk van source compileren:
    $ svn co https://guppy-pe.svn.sourceforge.net/svnroot/guppy-pe/trunk/guppy
    $ cd guppy
    $ python setup.py build 
    $ sudo python setup.py install 
    

Vervolgens kan je de (nogal basic) heapy tutorial volgen.

Voorbeeldsessie Heapy

>>> from guppy import hpy; heap=hpy(); del hpy
>>> heap.heap()
Partition of a set of 26126 objects. Total size = 1889564 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  11935  46   728612  39    728612  39 str

Op dit moment -- met alleen Python gestart -- is er 1.8MB in gebruik, vooral strings.

>>> heap.setref()
>>> import logica
[2012-03-17 01:04:19]:WARNING:openac:Functie doorvoer is deprecated bij callbacks maar zit nog in ModelBase
>>> heap.heap()
Partition of a set of 79843 objects. Total size = 6211716 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0  37276  47  2880268  46   2880268  46 str
     1  21661  27   846520  14   3726788  60 tuple

De setref() zorgt ervoor dat bij de volgende call we alleen nieuwe objecten zien. Het inlezen van module logica zorgt voor 6.2MB extra geheugen gebruik.

>>> heap.setref()
>>> logica.configuratie.lees()
True
>>> heap.heap()
Partition of a set of 5493 objects. Total size = 461748 bytes.
 Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)
     0    556  10   289120  63    289120  63 dict of include.primitieven.VrijObject
     1   3767  69   134268  29    423388  92 str

Het inlezen van de configuratie van OpenAC gebruikt 461kB. Dat is misschien veel voor een bestand van 21kB grootte en 573 regels. We kunnen kijken hoe we bij al die nieuwe strings komen:

>>> (heap.heap()&str).byvia
Partition of a set of 3767 objects. Total size = 134276 bytes.
 Index  Count   %     Size   % Cumulative  % Referred Via:
     0    556  15    23704  18     23704  18 "['omschrijving']"
     1    571  15    16000  12     39704  30 "['type']"
     2    558  15    15656  12     55360  41 '.keys()[10]'
     3    557  15    15608  12     70968  53 '.keys()[1]'

Hier zien we de weg (via) voor de strings die net zijn geladen. Daar zit niet zo veel verrassends in, behalve dat zo-te-zien er weinig sharing plaatsvindt. Een VrijObject kost 520 bytes of meer (520 is de dict). Dat zie je met (heap.heap()&dict).bysize.

Je kan ook met wat gefrobel ontdekken welke objecten het zijn:

>>> v=heap.heap()&dict
>>> v.byid 
Set of 711 <mixed> objects. Total size = 326520 bytes.
 Index     Size   %   Cumulative  %   Brief
     0     1672   0.5      1672   0.5 dict of class: ..TestEnv
...
>>> _.more
...

Op deze manier kunnen we bladeren door de objecten in de set v (dat zijn dicts die recent aan de heap zijn toegevoegd). De lijst byid kunnen we indexeren om een specifiek object te vinden:

>>> v.byid[39]
Set of 1 <dict of include.primitieven.VrijObject> object. Total size = 520 bytes.
 Index     Size   %   Cumulative  %   Owner Address
     0      520 100.0       520 100.0 0x88a4d0c

Tot slot kunnen we ontdekken hoe we bij dit specifieke object kunnen komen:

>>> v.byid[39].sp
 0: heap.Root.i0_modules['logica.configuratie'].__dict__['variabelen'].__dict__['_data']['rapportage_export_folder'].__dict__

Dus, ruwweg, hebben we hier logica.configuratie.variabelen!['rapportage_export_folder'] te pakken -- of beter gezegd, de __dict__ van het VrijObject dat daardoor aangeduid wordt.