2016-07-20 17 views
0

Ich schreibe ein CPython-Modul mrloader über eine C-Bibliothek, kompilierte Quellcode und begann mit einigen Tests.CPython Speicherverwaltung

Python benötigt 4 GB RAM, um eine 100-Iterationsschleife auszuführen, um einige Daten aus dem Netzwerk zu erhalten. Dies ist ein großes Problem, also habe ich resource verwendet, um die Menge an RAM zu begrenzen und zu testen, ob die Python-GCs den Speicher freigeben. Ich habe eine Segmentation fault.

Ich benutzte this Dokumentation und this, um das Modul zu schreiben, und ich denke, ich mache etwas falsch, wenn die Objekte gesammelt werden, denn wenn ich nicht den RAM begrenzen beendet die 100 Schleife, aber es verwendet 4 GB Speicher.

Im mrloader CPython Code habe ich eine Struktur wie folgt:

typedef struct { 
    PyObject_HEAD 
    AL_KEY ienaKey; 
    char* dataPath; 
    int nbParams; 
    char** pListOfParams; 
    CLIST_S* listParam; 
    AL_DEFP_S *pListeParamInfo; 
    int* pIndexParamIsTopana; 
} MRLoader; 

Die Python-Test ist in etwa so:

def limit_memory(maxsize): 
    soft, hard = resource.getrlimit(resource.RLIMIT_AS) 
    resource.setrlimit(resource.RLIMIT_AS, (maxsize, hard)) 

limit_memory(8589934592/10) 

for i in xrange(100): 
    print '----------------------------', i, '--------------------------' 
    obj = MRLoader.MRLoader(MR) 
    obj.initReaderCadence(paramList, cadence, zdtStart, zdtStop) 
    print obj.getData() 
    obj.closeAll() 

Im CPython Code wird die destructor wie so erklärt:

static void MRLoader_dealloc(MRLoader *self){ 
    self->ob_type->tp_free((PyObject *)self); 
} 

Entarre ich den Speicher korrekt?

Ich schätze Ihre Zeit, die mir hilft.

+1

Ihr Erweiterungstyp eine Reihe von Zeigern enthält. Es ist unklar, wie diese verwendet werden, aber wenn einer von ihnen zu irgendeinem Zeitpunkt der einzige Zeiger auf einen Speicherblock zugewiesen wird, der freigegeben werden muss, dann muss die "dealloc" -Funktion den Speicher freigeben, wenn es angemessen ist. Darüber hinaus müssen die Methoden Ihres Typs in diesem Fall diese Member entsprechend behandeln - z. B. den angegebenen Speicher freigeben, bevor der Zeigerwert durch einen anderen überschrieben wird. –

+0

Vielen Dank @JohnBollinger, Sie sind in verschiedenen Methoden freigegeben, und die CloseAll(). Ich suche, welche Referenzen nicht gereinigt werden. –

+0

CPython verwendet Referenzzählung, was bedeutet, dass Daten so schnell wie möglich freigegeben werden, sofern keine Zyklen vorhanden sind. Wenn Sie niemals zyklische Datenstrukturen anlegen, kann das, was Sie mit 'setrlimit' machen, nicht helfen. Wenn Sie zyklische Datenstrukturen verwenden, sind die ['gc'] (https://docs.python.org/3/library/gc.html) Schnittstellen wahrscheinlich hilfreicher. – zwol

Antwort

0

Ich fand die Lösung, ich habe PyArrayObject verwendet, dass ich keinen Zeiger für in der deklarierten Struktur gehalten habe. Der Speicher wurde wegen dieser riesigen Anzahl von Arrays nicht freigegeben.

So wie dies mein struct Blick jetzt:

typedef struct { 
    PyObject_HEAD 
    AL_KEY ienaKey; 
    char* dataPath; 
    int nbParams; 
    char** pListOfParams; 
    CLIST_S* listParam; 
    AL_DEFP_S *pListeParamInfo; 
    int* pIndexParamIsTopana; 
    // Added this pointer to the numpy array 
    reel64* pValueArray; 
} libzihc_MRLoader; 

Und in der ausplanen Funktion, rief ich free() vor dem PyObject selbst zu zerstören. Jetzt verwendet das Programm nicht mehr als 100 MB, das Array ist groß.

Ausplanen Funktion:

static void MRLoader_dealloc(MRLoader *self){ 
    free(self->pValueArray) 
    self->ob_type->tp_free((PyObject *)self); 
}