注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

天地不仁,以万物为Googol!

天行有常,不以物喜,不以己悲……

 
 
 

日志

 
 

为连续读取优化的一种缓存策略  

2009-10-19 22:18:02|  分类: 积累 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
事情的起因是boss要把对smb的支持从kernel转移到user模式的gio。这个迁移到还不是很复杂,改一些接口就可以。迁移过来后发现通过smb播放视频的性能下降的很厉害,在arm平台上,以前能流畅播放的视频现在完全不可看。

于是测了一下速率,使用gio通过gstreamer播放smb的视频,传输率只有100k/s多一点。进一步计时,发现gio在arm平台,即便只拷贝1个字节的文件,也要花0.16s左右的时间,而kernel模式下,只要0.01s。但是在连续读的情况下,gio可以达到600k/s多,而kernel只有400k/s。看来问题在于arm上gio由于引入dbus等操作,导致第一次读取时的延迟很长。因为gstreamer的gio插件默认一次只读4096字节,这样每次读取都要花掉0.16s,与kernel的0.01-0.02s的速度比起来,自然是慢了很多。

另外,由于卧艹的avi格式的存在,简单的顺序缓存效果不好。avi在播放过程中并不是流式读取,而是每隔一段时间就向后跳一段距离,读一小块的内容,然后再跳回来接着读。而且连续读这部分也不是严格连续,每次读取间都有一定的间隔,大概数据类似(偏移/大小):
100/30 134/46 183/34 504/30 220/45...

红色那个就是非常卧艹的地方。

解决办法是使用三个cache:current,preload,seek。current和preload存储的是顺序数据,固定的大小,在不影响操作和系统内存的情况下,尽可能大。当current命中n次后,将紧邻current的下一块数据读入到preload里。如果命中了preload,就交换preload和current,何时读新块,由上一条规则决定。如果某次读取在current和preload都没有命中,就读取需要的数据到seek里(或者读取在可接受延迟下的最大块)。如果要读取的是紧接着seek的内容,就直接更新current。

一个可以稍微优化一下的地方是,current和preload可以有一定的交叠,这样遇到边界跳转读取的情况时,可以减少对seek的读取。

一个问题是,由于arm本身速度慢,读满一个buffer可能会花很长时间,这个在开始播放和跳转的时候对用户不够流畅。可能的解决办法是先读够用的一小块,然后后面起thread去读。不过我对arm上的thread性能表现表示怀疑。这个已经有了一些实验代码,但还没在arm上实践过。

另一个问题是,为什么user下的gio,连续读取的速度反而要快过kernel呢?
  评论这张
 
阅读(582)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017