EasyDarwin

面向企业级的流媒体平台框架

EasyDarwin开始于2013年,遵循 Apple开源License APSL,为了敏捷流媒体服务器开发和简化企业流媒体应用开发而诞生的。

详细 >>

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


Easydarwin中大量使用gettimeofday来获取系统时间,对系统性能造成了一定的影响。...

(本文由EasyDarwin开源团队成员贡献)

一、问题描述

Easydarwin中大量使用gettimeofday来获取系统时间,对系统性能造成了一定的影响。我们来做个测试:

While(1)
{
    Gettimeofday(&tv,NULL);
}

每秒执行次数为约3000w次;

二、我们来看看gettimeofday函数内核实现

参见:http://blog.csdn.net/russell_tao/article/details/7185588

三、my_gettimeofday()实现

static inline int getcpuspeed_mhz(unsigned int wait_us)
{
       u_int64_t tsc1, tsc2;
       struct timespec t;

        t.tv_sec = 0;
        t.tv_nsec = wait_us * 1000;

        rdtscll(tsc1);

        // If sleep failed, result is unexpected, the caller should retry
        if(nanosleep(&t, NULL))
                return -1;
         rdtscll(tsc2);
         return (tsc2 - tsc1)/(wait_us);
} 

int getcpuspeed()
{
        static int speed = -1;
         while(speed<100)
                speed = getcpuspeed_mhz(50*1000);
         return speed;
}

int my_gettimeofday(struct timeval *tv)
{
        u_int64_t tick = 0;

        // TSC偏移大于这个值,就需要重新获得系统时间
        static unsigned int max_ticks = 80000000;
        rdtscll(tick);
        if(walltime.tv_sec==0 || cpuspeed_mhz==0 ||
                (tick-walltick) > max_ticks)
        {
                if(tick==0 || cpuspeed_mhz==0)
                {
                        cpuspeed_mhz = getcpuspeed();
                        max_ticks = cpuspeed_mhz*RELOAD_TIME_US;
                }
                //printf("gettimeofday again\n");
                gettimeofday(tv, NULL);
                memcpy(&walltime, tv, sizeof(walltime));
                rdtscll(walltick);
                return 0;
        }

        memcpy(tv, &walltime, sizeof(walltime));
        // if RELOAD_TIME_US is 1, we are in the same us, no need to adjust tv
#if RELOAD_TIME_US > 1
        {
                uint32_t t;
                t = ((uint32_t)tick) / cpuspeed_mhz;
                TIME_ADD_US(tv, t);//add 1 us
        }
#endif
        return 0;
}

通过休眠一段时间,然后检查cpu TSC变化,来大概估算cpu时钟频率,然后每次调用my_gettimeofday时,通过宏,rdtscll获取寄存器rdtsc寄存器的值,系统启动后cpu的tick数,当然第一次要先获取一下当前系统时间,gettimeofday。然后根据上面计算出来的cpu频率,以及获取到的cpu已经走过的tick数,计算出相对前面的gettimeofday时间的偏移,相加后得到当前系统时间。

备注:上面讲过,由于通过休眠一段时间,统计cpu tick变化的方式统计的cpu频率有一定误差,因此。Cpu tick每走过80000000重新校验一次,如果想要更高的精度,可以把这个值缩小。

四、优化后的测试效果

8000w+次每秒,性能提高了2-3倍。

在EasyDarwin上测试,通过easypusher_file推送100路,经过my_gettimeofday优化后,cpu消耗降低8%左右。



------------------------------ 分割线 ------------------------------
本站文章除注明转载外,均为本站原创或编辑,欢迎大家转载,但请务必注明出处,尊重他人成果,谢谢。
转载请注明:EasyDarwin;非本站文章均来自互联网,转载目的在于传递更多信息,并不代表本站赞同其观点和对其真实性负责。
文章中如果有错误可联系:johnson@easydarwin.org
推荐文章
安防和移动互联网行业比较火热的移动端手机......>
有人问到像美拍、秒拍这些短视频拍摄是怎么......>
最近更新
Easydarwin中大量使用gettimeofday来获取系......>
最近很多EasyDarwin爱好者提出了手机移动端......>
第一个到达的音频RTP包就将作为音频的关键帧......>
打开手机直播立即就能显示出主播视频,其实就......>
h264的功能分为两层,视频编码层(VCL)和网......>
友情链接 | 申请链接
EasyDarwin官方微信!