手机游戏热更新大量小文件资源读写性能分析

手机游戏开发的通常有一个重要的模块:热更新。热更新方式的实现有很多种,增量更新就是其中的一种,增量更新是指每次的更新都是增加新的资源和脚本,有修改过的就会被覆盖,但是弃掉的资源并不会被删除。这种更新方式到了后期可能会有两个比较严重的性能问题:

1、资源文件太多影响读读取性能。极端的情况是更新目录上有上万个资源文件,一个目录的文件过多的话,在安卓上面是有访问性能问题的,fopen,access函数调用过慢。

2、资源文件太多影响解压时间 。假如使用跳包更新,也就是从1.0.0更新到1.0.100版本,1-100版本的内容合到一个zip里面,这个zip大概会有一千个文件左右的吧,这个zip的解压在ios上会过慢,但在android上不会。

先来看第一个问题的解决之道,每一个文件的问题出在同一个目录有太多文件所导致,linux的文件目录节点图示:

目录中的文件是无序排列的,从中查找一个文件是不是存在,极端情况(文件不存)就要遍历目录节点的所有文件,并做对比。这样,当一个目录的文件很多的情况下(10000)这样fstate,access或者fopen一个不存在的文件,将会对比所有的文件,这种操作就会非常费时。

   解决的办法:既然我们知道这种情况是因为一个目录太多的文件导致,那么我们将文件分散到多个目录不就行了吗?是的,但是分散到的目录应该怎么命名呢?1-100吗?然后1个目录放100个文件?这种随机命名目录名和分散的方式肯定不行的,因为目录名和文件名没有关系的话,极端的情况还是要遍历所有目录才能知道文件不存在。那么将目录命名成文件名的前两个字符怎么样?这样就解决了,比如一个文件叫abcdefg.lua,要访问它,变成了访问ab/abcdefg.lua,这样就快多了。但这时又存在了另外一个问题,假如所有的文件名都是ab开头的,10000个文件都是ab开头,那它们就会都分配到了ab目录,又退化成原来的问题了。不急,这时还有一个方法,就是将文件名hash化,将所有的文件名转换成md5, 这样文件就被打散了。实验测试证明md5打散后的文件名,提取前两位做目录名,所有的文件会非常平均地分散到各个目录中。hash文件名后的资源:

按文件名前两位命名目录,然后放在各自的目录里面:

经过这种操作,就解决了项目 后期一个目录里面文件极多的情况下的fstate,fopen的性能问题了。

 

第二个问题,关于解压1000个小文件的性能问题,我测试苹果手机大概是7s左右,这个数据其实是可以接受的,但假如到最后一个zip包有1w个文件时,这个解压速度要70s,就有点夸张了。先说结论:这个减少写入时间是不可能的。下面看分析:

苹果手机写小文件速度:

测试了以下几个写文件的api

1、c 的fopen,fwrite,fclose

2、object-c的writeDataTofile

3、c++ fstream

4、mmap内存文件影射,

在调用munmap时仍然会触发写磁盘操作,这个操作仍然会卡,如果不munmap,将所有文件的读写都走mmap,虽然能达到没有写磁盘的效果,读写效率会较高,但是代码会更复杂难维护。

5、系统的 open,write,close

以上几个写文件接口耗时数量级一样,object-c接口会稍微快一点点,写1000个文件,共24.3M,在6s左右,其它的几个接口都在7s左右。

 

测试多线程写文件操作,1,2,4个线程同时写文件操作,结果一样,所有1000个文件写完的时间和用主线程写完时间是一样的。多线程改变不了卡io的问题。

 

网上对iphone6的写文件测评结果:小文件的写速率在3-3.5m/s,这个速率和我们现在的测试数据一样,

https://diy.pconline.com.cn/573/5735157.html

 

经上述数据分析,苹果写小文件是有性能问题的,这个和API或者上层逻辑没有半毛钱关第,所以,当要写10000个小文件时,我们是无法减少时间的,只有用多线程写,不要用主线程,免得主线程卡死了,然后在主线程做个进度条,让用户体验好一点,也只能如此了。

 

另外,我还尝试了一个10000个文件的zip包,不解压,直接在里面读取数据,这种方式也是不行的,测试数据如下:

zip不解压读文件速度测试:

zip文件定位是按顺序线性查找,时间复杂度为O(n)。随着文件越多,定位时间会越长

测试2500个文件的zip

排在前面几个文件定位耗时 在0.2毫秒左右

 

排在最后几个文件定位耗时在60多毫秒

 

zip的文件格式是顺序排列,没有在前面记录所有文件长度,文件名的数据。随机查找会比较费时,如果一开始遍历一次,将所有文件记录起来,下次查找操作从记录中进行,就相当于变成了自己实现一个文件系统了。

所以,散文件热更新中,假如你要考虑游戏到了后期有上万个小文件的情况时,可以看一下上面的测试数据,再自己选一个合适的解决办法吧。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值