最近一直在做视频项目的外围事情,工作中发现了一个比较奇怪的问题。在接入某一家平台厂商的视频流时,使用4核2.33G机器对16路cif视频进行解码居然要占用了50%的cpu。这真是个非常不可思议的数据。在和厂商沟通过程中,对方告诉我,他们的解码可以做到2核2G的机器上跑到40路cif。这和我的测试结果差别也太大了,无法接受,于是乎单独为对方的sdk写了测试用例,4核机器上跑16路cif只用了15%-18%cpu,这个结果和对方的陈述还是比较的吻合。
看来问题确实出在后端,可是后端的设计对于所有平台都是一样的,为什么只有这家平台会出问题呢。仔细研究了代码,后端做了一个内存池,用来缓存视频数据,在这过程中也就是使用了memcpy函数。实在看不出什么东西了,只能一段一段代码注释掉,在注释掉所有memcpy后,奇迹出现了,cpu居然下来了。当时真是非常的吃惊,从来没有想过memcpy会占cpu,闻所未闻。但是疑点又出现了,为什么别的平台没有这种问题呢。
在使用windebug仔细研究线程后,cpu确实是被平台的视频回调所占用,非常的纳闷。没办法,在视频回调中设置了sleep函数,观测结果,cpu也下来了。这下问题明白了,一般视频的桢率是25桢/秒。平台在接受时,启用线程接受码流,为了不阻塞上层应用,平台在其内部一定做了丢桢机制,当接受buf大于缓存时,主动丢桢来减轻内存消耗。于是一个在其内部必然维护了2个线程,同上层应用的接口是一个视频回调线程,而在这个线程中毫无疑问没有做信号量的等待,而是采用了一种轮训的机制,不停的回调。于是就出现了最初的情况,cpu空转。
但是这里还有一个疑问,为什么注释掉memcpy也会出现cpu降低的情况呢。这个应该和memcpy消耗无关,和机器及操作系统相关,在注释掉memcpy后,操作系统应该采取了某种优化措施,控制了回调线程的工作,这个也真是在多核系统中,虽然线程空转,却不会出现单核系统cpu100%的原因。在随后的测试中,也确实验证了这一点,不同的平台和硬件配置确实在其中发生了某些影响。
山高月小,水落石出。真相往往隐藏在从从迷雾之后。