EasyDarwin开源流媒体服务器内存管理优化
—本文由EasyDarwin开源团队成员Fantasy贡献
前言
最近在linux上跑EasyDarwin发现一个很奇怪的问题,当有RTSPSession连接上来的时候,发现进程的虚拟内存映射一下就多了64M,如下图:

备注:anon标识堆内存
过程
把通过在代码里面加system(“pmap pid”)命令,一步步跟,最终确定到是在NEW RTSPSession的时候多出来的64M内存,反复review代码,发现RTSPSession类并没有申请这么大的堆内存,把整个类大小输出,也远没有这么大。表示很奇怪。
决定写一些简单的类,一个个继承RTSPSession继承过的那些类,然后在NEW RTSPSession前面new一个对象,发现就会在NEW RTSPSession之前就多出来64M内存,果真是继承的类有申请大块内存?再次review,还是没有发现。
不继承任何类,new一个对象试试,结果还是多出来了。
查阅资料,发现是glibc 的malloc捣的鬼,glibc为了分配内存的性能的问题,使用了很多叫做arena的memory pool,缺省配置在64bit下面是每一个arena为64M,一个进程可以最多有 cores * 8个arena。假设你的机器是4核的,那么最多可以有4 * 8 = 32个arena,也就是使用32 * 64 = 2048M内存。 当然你也可以通过设置环境变量来改变arena的数量.例如export MALLOC_ARENA_MAX=1
分析
我们先分析下进程内存结构:

每个进程有一个堆空间,glibc为了防止线程之间存在内存分配竞争问题,采用了预先分配的方式来解决问题,即便你malloc 1个自己也给你先分个64M虚拟内存,注意这里是虚拟内存,不是物理内存。
测试代码如下:
#include <stdio.h>
#include "tcmalloc.h"
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
volatile bool start = 0;
void *threadFunc(void *argv)
{
int pid = getpid();
char cmdstr[64] = {0};
sprintf(cmdstr,"pmap %d|grep total",pid);
while(1)
{
//if(start)
{
char *a = (char*)malloc(1024);
printf("thread malloc\n");
system(cmdstr);
//sleep(1);
start = 0;
}
sleep(1);
}
}
int main()
{
//char *a = (char*)tc_malloc(100);
pthread_t pornsaveId;
int ret = 0;
ret = pthread_create(&pornsaveId, NULL, threadFunc,NULL);
if (ret)
{
return 0;
}
//tc_free(a);
while(getchar())
{
c->score = 1000;
start = 1;
}
return 0;
}
优化建议
Google开发了一个内存管理库,perftool,其中实现和tcmalloc和jemalloc,效率要比glibc高得多,具体实现细节可以自行百度。
当通过perf工具发现大量的malloc和free的时候,可以考虑引入google的tcmalloc或者jemalloc来解决性能问题。顺便说一句,尽量少在线程池中频繁进行申请和释放内存的操作,对性能影响比较大,因为线程之间存在竞争关系。
tcmalloc使用例子
先上网下载perftool库,编译:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include "tcmalloc.h"
using namespace std;
volatile bool start = 0;
void* thread_run( void* )
{
while ( 1 )
{
if ( start )
{
cout << "Thread malloc" << endl;
char *buf = (char *)tc_malloc(1024);// char[1024];
start = 0;
}
sleep( 1 );
}
}
int main()
{
pthread_t th;
printf("wait input 111\n");
getchar();
printf("wait input 222\n");
getchar();
printf("wait input 333\n");
pthread_create( &th, 0, thread_run, 0 );
while ( (getchar() ) )
{
start = 1;
}
return(0);
}
运行后发现,没有再像glibc那样有大块映射的虚拟内存了,而且性能也提高了很多(可以写个死循环进行测试,对比调用次数)
备注:现在机器基本都是64位的,虚拟内存2^64大小,基本不用考虑虚拟内存不够用的情况。
获取更多信息
Copyright © EasyDarwin.org 2012-2016

EasyDarwin开源流媒体服务器内存管理优化的更多相关文章
- EasyDarwin开源流媒体服务器gettimeofday性能优化(3000万/秒次优化至8000万次/秒)
-本文由EasyDarwin开源团队成员贡献 一.问题描述 Easydarwin中大量使用gettimeofday来获取系统时间,对系统性能造成了一定的影响.我们来做个测试: While(1) { G ...
- EasyDarwin开源流媒体服务器性能优化之Work-stealing优化方案
本文转自EasyDarwin开源团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/52400226 EasyDarwin团队的Ba ...
- EasyDarwin开源流媒体服务器实现RTSP直播同步输出MP4、RTMP、HLS的方案思路
背景 近期跟开源团队商量,想在EasyDarwin上继续做一些功能扩展,目前EasyDarwin开源流媒体服务器只能够实现高效的RTSP推流直播转发/分发功能,输入与输出都是RTSP/RTP流,不能够 ...
- EasyDarwin开源流媒体服务器将select改为epoll的方法
本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...
- NodeJS版本EasyDarwin开源流媒体服务器开发心得
title: Node版本EasyDarwin开发心得 date: 2018-03-27 22:46:15 tags: 年后着手Node版本EasyDarwin的开发工作,截止到今天2018年03月2 ...
- EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布
EasyDarwin开源流媒体服务器(www.easydarwin.org)现在使用Go版本实现了.最新的代码提交,已经支持了推流(或者拉流)的同时进行本地存储. 本地存储的原理,是在推流的同时启动f ...
- EasyDarwin开源流媒体服务器Golang版本:拉转推功能之拉流实现方法
EasyDarwin开源流媒体服务器(www.easydarwin.org),拉转推是一个很有意义的功能,它可将一个独立的RTSP数据源"拉"到服务器,再通过转发协议转发给多个客户 ...
- 解决用EasyDarwin开源流媒体服务器做HLS直播时Flash Player卡住的问题
最近在开发EasyDarwin开源流媒体服务器HLS直播的时候发现一个现象:在PC上用flash player播放HLS和在ios上面播放HLS时,效果明显不同,在ios上播放非常稳定,而在flash ...
- EasyDarwin开源流媒体服务器提供的TS切片/HLS直播打包库
EasyHLS Github:https://github.com/EasyDarwin/EasyHLS EasyHLS是什么? EasyHLS是EasyDarwin开源流媒体社区开发的一款HLS打 ...
随机推荐
- centos 7安装postgresql10.3
最新版本安装请移步:阿里云服务器 centos 7 安装postgresql 11 一.Postgresql简介 官方网站:https://www.postgresql.org/ 简介参考zhihu文 ...
- IOS-input元素光标偏移乱跑,是什么原因
这中情况只会出现在一些ios手机上,是兼容性的问题,当然我没有认真的确认过是出现在那些ios系统上的: 之所以出现这种情况,肯定是在input上或TA的父元素上用到了position:fixed; 目 ...
- Codeforces 635D Factory Repairs【树状数组】
又是看了很久的题目... 题目链接: http://codeforces.com/contest/635/problem/D 题意: 一家工厂生产维修之前每天生产b个,维修了k天之后每天生产a个,维修 ...
- 信息收集渠道:文本分享类网站Paste Site
信息收集渠道:文本分享类网站Paste Site Paste Site是一种专门的文本分享的网站.用户可以将一段文本性质的内容(如代码)上传到网站,然后通过链接分享给其他用户.这一点很类似于现在的优酷 ...
- Java NIO中的Buffer类
Buffer 缓冲,用于批量读写数据 Buffer是一个抽象类,基本数据类型都有实现类:XxxBuffer,比如ByteBuffer.CharBuffer.IntBuffer.DoubleBu ...
- Java ArrayList 详解
只记录目前为止关注的.JDK1.8 一.基础属性 1.1 内部参数 //空存储实例.直接new ArrayList()便是以该空数组作为实例 private static final Object[] ...
- Nginx图片防盗链的方式
原文:http://www.open-open.com/code/view/1430750263460 location ~* \.(gif|jpg|jpeg|png|ico)$ { valid_re ...
- WM_SETFOCUS和WM_KILLFOCUS、WM_GETDLGCODE
procedure WMSetFocus (var Message: TWMSetFocus); message WM_SETFOCUS; //获得焦点 procedure WMKillFocus ...
- JavaScript 推断浏览器类型及32位64位
JS推断出版本号以及浏览器类型 <script type="text/javascript"> var Sys = {}; var ua = navigator.use ...
- List<InvestInfoDO> invest = advertiseDao6.qryInvestInfo(InvestInfoDO1);怎样获得list的实体类;
List<InvestInfoDO> invest = advertiseDao6.qryInvestInfo(InvestInfoDO1); 怎样获得List的实体类呢,就是怎样获得I ...