GLib中GThread Pool内存占用的问题
2012-11-08 21:04
155 查看
最近,我们发现有个简单的程序内存占用特别大,该程序自启动开始就占用着2.7G左右的内存。最初,大家都觉得不可思议,因为这个程序功能非常简单:
1)它采用多socket多线程的方式,即每个socket链接都是一个线程,但该线程的功能很简单,就是持续接收socket数据。2)程序的另外一个功能就是转发数据。我排查了程序各处代码,没有发现有申请大块内存的地方,即便socket接收所采用的buffer,也不到1KB。
那是什么东西吃掉了2.7G的内存?
(1)继续排查,因为我们采用了GLib库,所以此处暂且将线程变小。结果发现,内存占用小了很多。
(2)分别测试1,10,20,40,80个线程时,内存占用情况,发现每增加一个线程,基本上会增加9M内存左右。
(3)定位问题。从(2)可以看出,问题出在线程上,我首先想到应该是线程堆栈大小出了问题,于是做了一个简单的测试:使用ulimit -s查看到当前系统设置的堆栈大小为10240(即10M),那么当我通过ulimit -s 5120之后,发现那个简单程序占用内存将之了1.3G。
OK,到这里问题就清楚了。GThread Pool在创建线程时,采用的是系统默认堆栈大小(如果需要设置堆栈大小,需要开启编译条件,并设置一个环境变量)。而不知道是谁设置了系统默认堆栈为10240,从而导致简单程序在多线程时内存占用巨大。
昨天写了更正此问题的方式(1.重新编译库。2.显示指定线程栈大小),但尝试之后发现在GThread Pool里都不可行。根据GThread Pool的官方说明:之所以每个线程都采用默认栈大小,是要解决多个Thread Pool公用线程的情况:如果线程的栈大小不一致,会导致无法在多个Thread Pool中被使用到。事实上,在GThread Pool代码中(glib-2.34.0),deprecated目录含有可指定堆栈大小的接口(gthread-deprecated.c),不过已被废弃。
目前我们的代码中,只采用了一个GThread Pool,所以不会出现多个Thread Pool共用线程的情况。即便如此,我也找不出方法去设置GThread Pool中线程的栈大小(要修改库代码的除外)。
官方还给出了一个可选择的方法,自己基于GAsyncQueue实现可指定堆栈大小的Thread Pool。这个办法略显繁琐,但也是一种可行的方式。当然,为了不修改库代码,需要在库上封装一层,以实现我们所需的可指定线程栈大小的Thread Pool。
1)它采用多socket多线程的方式,即每个socket链接都是一个线程,但该线程的功能很简单,就是持续接收socket数据。2)程序的另外一个功能就是转发数据。我排查了程序各处代码,没有发现有申请大块内存的地方,即便socket接收所采用的buffer,也不到1KB。
那是什么东西吃掉了2.7G的内存?
(1)继续排查,因为我们采用了GLib库,所以此处暂且将线程变小。结果发现,内存占用小了很多。
(2)分别测试1,10,20,40,80个线程时,内存占用情况,发现每增加一个线程,基本上会增加9M内存左右。
(3)定位问题。从(2)可以看出,问题出在线程上,我首先想到应该是线程堆栈大小出了问题,于是做了一个简单的测试:使用ulimit -s查看到当前系统设置的堆栈大小为10240(即10M),那么当我通过ulimit -s 5120之后,发现那个简单程序占用内存将之了1.3G。
OK,到这里问题就清楚了。GThread Pool在创建线程时,采用的是系统默认堆栈大小(如果需要设置堆栈大小,需要开启编译条件,并设置一个环境变量)。而不知道是谁设置了系统默认堆栈为10240,从而导致简单程序在多线程时内存占用巨大。
昨天写了更正此问题的方式(1.重新编译库。2.显示指定线程栈大小),但尝试之后发现在GThread Pool里都不可行。根据GThread Pool的官方说明:之所以每个线程都采用默认栈大小,是要解决多个Thread Pool公用线程的情况:如果线程的栈大小不一致,会导致无法在多个Thread Pool中被使用到。事实上,在GThread Pool代码中(glib-2.34.0),deprecated目录含有可指定堆栈大小的接口(gthread-deprecated.c),不过已被废弃。
目前我们的代码中,只采用了一个GThread Pool,所以不会出现多个Thread Pool共用线程的情况。即便如此,我也找不出方法去设置GThread Pool中线程的栈大小(要修改库代码的除外)。
官方还给出了一个可选择的方法,自己基于GAsyncQueue实现可指定堆栈大小的Thread Pool。这个办法略显繁琐,但也是一种可行的方式。当然,为了不修改库代码,需要在库上封装一层,以实现我们所需的可指定线程栈大小的Thread Pool。
相关文章推荐
- GLib中GThread Pool内存占用的问题
- 解决Apache长时间占用内存大的问题,Apache 内存优化方法
- Linux服务器Cache占用过多内存导致系统内存不足问题的排查解决(续)
- J2ME 内存占用的问题
- 解决w3wp.exe占用CPU和内存问题
- 解决w3wp.exe占用CPU和内存问题
- 真正解决win2003下apache的httpd.exe占用内存的问题
- java内存占用问题(一)
- dllhost.exe占用内存过高的问题
- 解决w3wp.exe内存占用问题
- 正确理解Linux内存占用过高的问题
- linux内存占用问题调查——slab
- CI框架在CLI下执行占用内存过大问题的解决方法
- OneTab扩展:解决 Chrome 内存占用过多问题
- 解决PHP加速器eAccelerator导致php-cgi占用内存过多的问题
- 解决CodeIgniter大量查询sql时占用内存大问题
- 关于c++中map的内存占用问题
- 《C++中类对象的内存布局和占用空间》《C++ 类里面,函数占用存储空间问题 》
- 解决iis内存占用过大的问题
- ASP+SQL查询查询问题--SQL占用很大内存?