Linux 多线程应用 降低内存(VSZ)占用

嵌入式开发的内存无疑是非常吃紧的。特别是一些老设备,之前的一台终端设备因为内存占用过高,出现了运行出错,进程管理的APP直接杀死了占用最高的媒体APP,导致视频输出出现异常。先优化一下VSZ好了。
于是进探索了内存优化之路。在确保长时间运行内存不会增加(没有内存泄漏)后,首先查看 /proc 下的进程 内存占用的smap 信息:

cat /proc/<pid>/smaps|grep -v ' 0 kB'

查看进程申请的内存详情
通过观察不难发现大量的内存占用都在栈上。由于这个APP是一个多线程进程,一个线程就有一个栈,导致了进程申请的内存大量被用于线程栈的申请上,每个栈8MB,仅10个线程就占用了100MB的虚拟内存空间。
stack mem
一个进程占用99MB内存,11个线程栈的内存占了88MB。那么方向就很明确了。减少栈的大小即可。
首先想到的是,直接进行全局的配置系统默认栈得大小,因为目前Linux程序的线程使用的都是默认的参数,即采用系统默认的栈大小进行开辟线程的栈。使用ulimit -s 指令在启动脚本加入:

ulimit -s 1024

以上就将系统默认栈设置为1024KB,单位是KB。启动系统,不巧的是,有些APP运行出现了异常,猜测界面APP使用了大量的变量,导致栈的溢出,APP直接就退出了。缩小系统栈还是有一定的风险,而且不知会不会引入其他的问题。
想着既然Linux系统一般都是使用pthread启动线程,而且子线程一般变量较少,不需要很大的栈空间,那么我们可以通过pthread_create的pthread_attr_t进行参数的设定设定进程生成的线程栈,达到缩小进程内存占用的目的。
将佘艳的线程生成

int thread::startThread(callable *c) {

	int const res = pthread_create(&handle_, 0, &posix_thread_proxy, static_cast<void*>(c));
	if (res != 0) {
		delete c;
		return -1;
	}

	return 0;
}

改为这样创建线程(这里的stacksize的单位是字节)

int thread::startThread(callable *c) {

	pthread_attr_t thread_attr;
	pthread_attr_init(&thread_attr);
	pthread_attr_setstacksize(&thread_attr, 1024*1024); ///< 1MB
	int const res = pthread_create(&handle_, &thread_attr, &posix_thread_proxy, static_cast<void*>(c));
	if (res != 0) {
		delete c;
		return -1;
	}
	pthread_attr_destroy(&thread_attr);

	return 0;
}

即可将原来的8MB栈大小改为1MB,效果显著。

top指令查看 左边为修改前,右侧为修改后
top
ps -o pid,comm,rss,vsz 指令查看 左边为修改前,右侧为修改后
ps
可以看到线程多的APP占用基本缩小了一半多。

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值