—本文由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大小,基本不用考虑虚拟内存不够用的情况。

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Copyright © EasyDarwin.org 2012-2016

EasyDarwin开源流媒体服务器内存管理优化的更多相关文章

  1. EasyDarwin开源流媒体服务器gettimeofday性能优化(3000万/秒次优化至8000万次/秒)

    -本文由EasyDarwin开源团队成员贡献 一.问题描述 Easydarwin中大量使用gettimeofday来获取系统时间,对系统性能造成了一定的影响.我们来做个测试: While(1) { G ...

  2. EasyDarwin开源流媒体服务器性能优化之Work-stealing优化方案

    本文转自EasyDarwin开源团队成员Alex的博客:http://blog.csdn.net/cai6811376/article/details/52400226 EasyDarwin团队的Ba ...

  3. EasyDarwin开源流媒体服务器实现RTSP直播同步输出MP4、RTMP、HLS的方案思路

    背景 近期跟开源团队商量,想在EasyDarwin上继续做一些功能扩展,目前EasyDarwin开源流媒体服务器只能够实现高效的RTSP推流直播转发/分发功能,输入与输出都是RTSP/RTP流,不能够 ...

  4. EasyDarwin开源流媒体服务器将select改为epoll的方法

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin网络模型介绍 EventContext负责监听所有网络读写事件,Even ...

  5. NodeJS版本EasyDarwin开源流媒体服务器开发心得

    title: Node版本EasyDarwin开发心得 date: 2018-03-27 22:46:15 tags: 年后着手Node版本EasyDarwin的开发工作,截止到今天2018年03月2 ...

  6. EasyDarwin开源流媒体服务器Golang版本:服务端录像功能发布

    EasyDarwin开源流媒体服务器(www.easydarwin.org)现在使用Go版本实现了.最新的代码提交,已经支持了推流(或者拉流)的同时进行本地存储. 本地存储的原理,是在推流的同时启动f ...

  7. EasyDarwin开源流媒体服务器Golang版本:拉转推功能之拉流实现方法

    EasyDarwin开源流媒体服务器(www.easydarwin.org),拉转推是一个很有意义的功能,它可将一个独立的RTSP数据源"拉"到服务器,再通过转发协议转发给多个客户 ...

  8. 解决用EasyDarwin开源流媒体服务器做HLS直播时Flash Player卡住的问题

    最近在开发EasyDarwin开源流媒体服务器HLS直播的时候发现一个现象:在PC上用flash player播放HLS和在ios上面播放HLS时,效果明显不同,在ios上播放非常稳定,而在flash ...

  9. EasyDarwin开源流媒体服务器提供的TS切片/HLS直播打包库

    EasyHLS  Github:https://github.com/EasyDarwin/EasyHLS EasyHLS是什么? EasyHLS是EasyDarwin开源流媒体社区开发的一款HLS打 ...

随机推荐

  1. 学习javascript设计模式之代理模式

    1.代理模式为一个对象提供一个代用品或占位符,以便控制对它的访问. 2.不用代理模式: 客户 -> 本体  使用代理模式:  客户 -> 代理 -> 本体 3.例子场景1 点击操作与 ...

  2. hdu 3478 Catch 二分图染色

    题目链接 题意 小偷逃跑,从某个点出发,每下一个时刻能够跑到与当前点相邻的点. 问是否存在某一个时刻,小偷可能在图中的任意一个点出现. 思路 结论 如果该图为连通图且不为二分图,则可能,否则不可能. ...

  3. poj 2112(二分+网络流)

    Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 15749   Accepted: 5617 ...

  4. 小程序-生成一个小程序码画在canvas画布上生成一张图片分享出去

    这个需求我遇到过2次.一次是在识别二维码后跳转到其它页面,另一次是识别二维码后进入到生成小程序码的当前页面. 我有一个梦想,就是成为一名黑客!!!!!! 小程序中js wx.request({     ...

  5. 第三章 poj 1064——关于带精度的二分法

    /* 题意:给定n个实数l[i],给定一个k 问:求最大的ans,使得sum l[i]/ans i=1 to n >=k,且ans最大*/ #include <iostream> # ...

  6. (入门SpringBoot)SpringBoot配置全局异常(五)

    Spring的全局异常,用于捕获程序员没有捕获的异常.具体请看下面代码: 1.ControllerAdvice拦截异常,统一处理.通过Spring的AOP来管理. @ControllerAdvicep ...

  7. SnakeYaml使用

    新的项目中需要将yaml文件解析为对象,调研了决定使用snakeYaml,下面看一看怎么使用. 一.引入依赖 因为项目是使用maven构建的,所以我们在pom文件中引入snakeYaml的依赖,如下: ...

  8. Android 测试自定义纯数字软键盘

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  9. 深入解析Ajax——系列(一)

    常常写脚本的人.有时候会用到$ajax,有时候也会用到$post和$get,这几个方法都是用来从Webserver上获取静态的数据文件. jQuery对ajax操作进行了封装,在jquery中$.aj ...

  10. SQL获取年月日方法

    方法一:利用DATENAME 在SQL数据库中,DATENAME(datetype,date)函数的作用是从日期中提取指定部分数据,其返回类型是nvarchar.datetype类型见附表1. SEL ...