【问题标题】:CPython memory managementPython内存管理
【发布时间】:2016-07-20 13:13:10
【问题描述】:

我正在 C 库之上编写一个 CPython 模块 mrloader,我编译了源代码并开始进行一些测试。

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);
}

我是否正确地释放了内存?

感谢您抽出宝贵时间帮助我。

【问题讨论】:

  • 您的扩展类型包含一堆指针。目前还不清楚这些是如何使用的,但是如果它们中的任何一个在任何时候都被分配了指向必须释放的内存块的唯一指针,那么dealloc 函数必须在适当的时候处理释放该内存。此外,在这种情况下,您的类型的方法必须适当地处理这些成员——例如,在用不同的指针值覆盖之前释放指向的内存。
  • 谢谢@JohnBollinger,它们以不同的方法和 closeAll() 释放。我正在搜索未清理的引用。
  • CPython 使用引用计数,这意味着数据会尽快释放,除非有循环。如果您从不创建循环数据结构,那么您对 ​​setrlimit 所做的事情可能无济于事。如果您确实使用循环数据结构,gc 接口更有可能提供帮助。
  • 明智的做法是dealloc 函数释放对象所拥有的任何尚未释放的内存;这将提供一个防止编程错误的安全网。
  • @e-nouri,我重复一遍,如果任何指针在任何时候都被分配了指向必须释放的内存块的唯一指针,那么 dealloc 函数 必须在适当的时候处理释放该内存。其他函数也可以解除分配,只要它们能够向 dealloc 函数指示它不应再次解除分配相同的内存,但您不应仅依赖于必须调用的方法来正确解除分配您的模块的用户。

标签: python c memory-management cpython


【解决方案1】:

我找到了解决方案,我使用了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;

在deallocate函数中,我在销毁PyObject之前调用了free()。现在程序使用不超过100Mb,数组很大。

释放函数:

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

【讨论】:

    猜你喜欢
    • 2018-01-08
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 2016-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    相关资源
    最近更新 更多