2016-07-20 56 views
0

我正在C庫上編寫一個CPython模塊mrloader,我編譯了源代碼並開始進行一些測試。CPython內存管理

Python需要4 Gb的RAM運行100次迭代循環才能從網絡獲取一些數據。這是一個大問題,所以我使用resource來限制RAM的數量並測試Python GC是否釋放內存。我得到了Segmentation fault

我用this文檔和this來編寫模塊,我認爲在收集對象時我做錯了什麼,因爲如果我不限制RAM,它將完成100循環,但它會使用4Gb的內存。

在mrloader CPython代碼,我有一個結構,像這樣:

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

Python的測試,像這樣:

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() 

在CPython的代碼中,destructor聲明如下所示:

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

我正確地釋放內存嗎?

我很感謝你的時間幫助我。

+1

您的擴展類型,包含了一些指針。目前還不清楚它們是如何使用的,但是如果它們中的任何一個在任何時候被賦予唯一指向必須釋放的內存塊的指針,那麼'dealloc'函數必須在適當時處理釋放該內存。此外,在這種情況下,類型的方法必須適當地處理這些成員 - 例如,在用不同的指針值覆蓋指針值之前釋放指向的內存。 –

+0

謝謝@JohnBollinger,他們以不同的方法釋放,並且closeAll()。我正在搜索哪些引用未被清理。 –

+0

CPython使用引用計數,這意味着數據儘快釋放,除非有循環。如果你從不創建循環數據結構,那麼你使用'setr​​limit'做的事情不可能有幫助。如果你使用循環數據結構,['gc'](https://docs.python.org/3/library/gc.html)接口更有可能提供幫助。 – zwol

回答

0

我找到了解決方案,我使用的是PyArrayObject,我沒有在聲明的結構中保留一個指針。內存沒有被釋放,因爲這個巨大的numpy數組。

所以我的結構看起來像現在這樣:

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; 

而且在解除分配功能,我破壞PyObject自之前調用free()。現在該程序不使用超過100Mb,數組很大。

解除分配功能:

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