2016-07-20 96 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); 
}