2012-09-21 13 views
5

Ich bin völlig verwirrt über die Speichernutzung eines bestimmten Python-Skripts. Ich denke, ich weiß nicht wirklich, wie man die Verwendung trotz advice von einigen SO Fragen/Answers profilieren kann.Speicherauslastung in Python: Was ist der Unterschied zwischen memory_profiler und Guppy?

Meine Fragen sind: Was ist der Unterschied zwischen memory_profiler und guppy.hpy? Warum sagt mir jemand, dass ich große Mengen an Speicher verwende, und der andere sagt mir, dass ich nicht bin?

Ich arbeite mit pysam, eine Bibliothek für den Zugriff auf Bioinformatik SAM/BAM-Dateien. Mein Hauptskript läuft nicht schnell genug, wenn SAM (ASCII) in BAM (Binary) konvertiert wird und die Dateien dazwischen manipuliert werden.

Ich habe ein kleines Testbeispiel erstellt, um zu verstehen, wie viel Speicher bei jedem Schritt zugewiesen wird.

# test_pysam.py: 

import pysam 
#from guppy import hpy 

TESTFILENAME = ('/projectnb/scv/yannpaul/MAR_CEJ082/' + 
       'test.sam') 
#H = hpy() 

@profile # for memory_profiler 
def samopen(filename): 
# H.setrelheap() 
    samf = pysam.Samfile(filename) 
# print H.heap() 
    pass 


if __name__ == "__main__": 
    samopen(TESTFILENAME) 

Überwachung der Speichernutzung mit memory_profiler (python -m memory_profiler test_pysam.py) ergibt die folgende Ausgabe:

Filename: test_pysam.py 

Line # Mem usage Increment Line Contents 
================================================ 
    10        @profile # for memory_profiler 
    11        def samopen(filename): 
    12  10.48 MB  0.00 MB # print H.setrelheap() 
    13 539.51 MB 529.03 MB  samf = pysam.Samfile(filename) 
    14        # print H.heap() 
    15 539.51 MB  0.00 MB  pass 

Dann @profile Dekorateur kommentieren und uncommenting die guppy bezogenen Linien, erhalte ich die folgende Ausgabe (python test_pysam.py):

Partition of a set of 3 objects. Total size = 624 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0  1 33  448 72  448 72 types.FrameType 
    1  1 33  88 14  536 86 __builtin__.weakref 
    2  1 33  88 14  624 100 csamtools.Samfile 

Die Gesamtgröße der Zeile 13 beträgt in einem Fall 529,03 MB und 624 Bytes in der anderen. Was ist hier eigentlich los? 'test.sam' ist eine ~ 52MB SAM Datei (wieder ein ASCII Format). Es ist ein bisschen schwierig für mich, tief in pysam zu graben, da es ein Wrapper um eine C-Bibliothek ist, die sich auf samtools bezieht. Unabhängig davon, was eine Samfile eigentlich ist, sollte ich in der Lage sein zu lernen, wie viel Speicher zugeordnet ist, um es zu erstellen. Welche Prozedur sollte ich verwenden, um die Speicherauslastung jedes Schritts meines größeren, komplexeren Python-Programms korrekt zu profilieren?

+0

Beachten Sie, dass "test.sam" in einer zweiten Zeile ist, weil es ein viel längerer Name war und sobald ich es änderte, merkte ich, dass meine Zeilennummer aus wäre, wenn ich den Dateinamen auf eine Zeile setzen würde. – Yann

Antwort

7

Was ist der Unterschied zwischen memory_profiler und guppy.hpy?

Verstehen Sie den Unterschied zwischen Ihrer internen Ansicht des Heap und der externen Ansicht des Betriebssystems Ihres Programms? (Wenn zum Beispiel der Python-Interpreter free auf 1MB aufruft, gibt das aus mehreren Gründen nicht sofort oder vielleicht sogar immer 1MB an Seiten an das Betriebssystem zurück.) Wenn Sie dies tun, ist die Antwort ziemlich einfach: memory_profiler fragt das Betriebssystem nach Ihrem Speicherverbrauch; Guppy ermittelt es intern von den Haufenstrukturen.

Darüber hinaus hat memory_profiler ein Feature, das Guppy nicht automatisch mit der Funktion versieht, einen Bericht nach jeder Codezeile zu drucken. es ist ansonsten viel einfacher und einfacher, aber weniger flexibel. Wenn es etwas gibt, von dem du weißt, dass du es machen willst und memory_profiler es nicht zu tun scheint, kann es das wahrscheinlich nicht; mit Guppy, vielleicht kann es, also studieren Sie die Dokumente und die Quelle.

Warum sagt mir jemand, dass ich riesige Mengen an Speicher verwende, und der andere sagt mir, dass ich nicht bin?

Es ist schwer sicher, aber hier sind einige Vermutungen; Die Antwort ist wahrscheinlich eine Kombination aus mehr als einem:

Vielleicht nutztattsools verwendet mmap, um klein genug Dateien vollständig in den Speicher abzubilden. Dies würde die Seitennutzung um die Größe der Datei erhöhen, die Heap-Nutzung jedoch nicht erhöhen.

Vielleicht erstellt Tools oder Pysam eine Menge temporärer Objekte, die schnell freigegeben werden. Du könntest viel Fragmentierung haben (nur ein Paar lebt PyObjects auf jeder Seite), oder das malloc deines Systems hat vielleicht entschieden, dass es viele Knoten in seiner Freelist wegen der Art der Zuweisung behalten sollte, oder dass es Seiten nicht zurückgegeben hat auf das Betriebssystem noch nicht, oder die VM des Betriebssystems hat möglicherweise keine Seiten zurückgewonnen, die zurückgegeben wurden. Der genaue Grund ist fast immer unmöglich zu erraten; Am einfachsten ist es anzunehmen, dass freigegebener Speicher niemals zurückgegeben wird.

Welche Prozedur soll ich verwenden, um die Speichernutzung jedes Schritts meines größeren, komplexeren Python-Programms korrekt zu profilieren?

Wenn Sie nach Speicherauslastung aus der Sicht des Betriebssystems fragen, macht memory_profiler genau das, was Sie wollen. Während das Graben in Pysam schwierig sein kann, sollte es trivial sein, einige der Funktionen mit dem @profile Decorator zu umhüllen. Dann wissen Sie, welche C-Funktionen für das Gedächtnis verantwortlich sind. Wenn Sie tiefer graben möchten, müssen Sie natürlich auf der C-Ebene profilieren (es sei denn, es gibt Informationen in den Unterlagen-Dokumenten oder aus der Sammel-Community).

+0

Große Antwort, danke. – Yann