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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章