pyclutter内存不释放解决记录

由于程序最终是在一款嵌入式平台上运行.由 python+clutter 的程序在pc上运行内存可以非常理想的释放,而在嵌入式平台上却不能释放.

开始时,一直怀疑是内存泄露的原因,但是前面的工作将内存泄露的原因也排除了.


我用c写的程序在pc上运行,没有明显的内存泄露.


后来,我将两个一模一样的程序,分别在两个平台上运行,得到的内存记录却完全不同,

在pc上能良好释放,但是在嵌入式平台上,却还是不能释放.


考虑到两种平台,有区别的地方可能就是opengl,在pc上用的是OpenGL,而在嵌入式平台上,用的却是OpenGL ES.

所以我又写一个最简单的clutter程序,仅是产生图片,然后销毁掉,在两种平台上,查看区别.

但是結果还是不同,所以怀疑是OpenGL不同导致的.怀疑是由于OpenGL的内存池不释放造成的. 但是,同事却告诉我说,OpenGL不存在内存池.


今天,又想到,是不是因为内存分配没有对齐,导致很多内存碎片的问题呢.所以去查g_malloc函数,到Memory Allocation一节时,看到对这一节的描述:

Description

These functions provide support for allocating and freeing memory.

Note

If any call to allocate memory fails, the application is terminated. This also means that there is no need to check if the call succeeded.

Note

It's important to match g_malloc() with g_free(), plain malloc() with free(), and (if you're using C++) new with delete and new[] with delete[]. Otherwise bad things can happen, since these allocators may use different memory pools (and new/delete call constructors and destructors). See also g_mem_set_vtable().


突然看到 memory pool ,原来glibc也有内存池机制啊.然后在网上看到glibc的内存池机制,以及相应的环境变量和参数.

其实的malloc的实现并非简单调用brk/sbrk,为了考虑效率glibc有“三级”优化措施,即:

1.       “小内存”分配通过 fastbin 链表实现;

2.       一般的内存分配在堆上分配,该区域称为:memory arena;

3.       比较大(比M_MMAP_THRESHOLD设定的值更大)的内存采用mmap分配,采用mmap的好处在于free后立即交还给系统,而不会被锁定而浪费内存;

在程式调用free时,glibc并不会每次调用sbrk,相反glibc会把放到暂时的内存池中,以提供下一次malloc的操作使用,这样能够达到内存分配效率的优化。

控制内存分配的函数是mallopt,其原型如下:

int mallopt(int cmd, int __val);

cmd的取值为:

M_TRIM_THRESHOLD -1

M_TOP_PAD -2

M_MMAP_THRESHOLD -3

M_MMAP_MAX -4

M_CHECK_ACTION -5

M_PERTURB -6

其含义如下:

M_TRIM_THRESHOLD

当能够被释放的内存堆积到该值时进行正真的释放(sbrk)操作;

M_TOP_PAD

内存分配时头部的附加长度。假如程式调用malloc分配1024k内存,但glibc并不会仅仅分配1024k,还需分配更多的内存(一部分用来进行glibc自身的内存分配管理使用)。

M_MMAP_THRESHOLD

假如需要分配的内存超过该值,glibc将采用mmap分配内存。

M_MMAP_MAX

用来控制最多的mmap的数目;

实例:mallopt-trim.c



事实上以上参数能够通过相应的环境变量来设定而不必修改程式,比如:

MALLOC_TRIM_THRESHOLD_=1024 ./program


对相同的c程序,在pc和嵌入式平台上测试結果相同,确定在嵌入式平台上内存不释放就是这个原因.但是,我们的程序是python程序.

看到可以mallopt函数来在代码中设置.

在c程序中,可以添加在main函数内的开头,但是,我们在python中是调用c的库,并没有main函数.

然后我觉得应该在控件创建开始的地方进行设置,但是测试結果却没有改善,看来设置并没有效果.

后来想到,既然以命令行添加环境变量的方式在c可行,那么在python中也是一样的啊,我只要设置python的环境,那么glibc库的运行环境继承来自python程序的运行环境,肯定也可行.

MALLOC_TRIM_THRESHOLD_=1024 MALLOC_MMAP_THRESHOLD_=1024  ./movie.py

結果果然可以.

当然参数值的設定应该是继续优化,网上有说最好一页大小为宜,即4k



你可能感兴趣的:(pyclutter内存不释放解决记录)