微信小游戏远程加载bundle(zip压缩),解压时触发缓存上限,导致解压报错,如何处理?

微信小游戏远程加载bundle(zip压缩),解压时触发缓存上限,导致解压报错,如何处理?

此种情况的疑问:
引擎底层的“当缓存空间占满后资源会保存失败,此时会使用 LRU 算法删除比较久远的资源”还会生效么?

个人感觉:
我感觉是引擎底层清理是失效了,目前处理方案是检查到有新版本提示用户重启前,自己调用接口大清理一下,以此避免用户更新几个游戏版本后,缓存空间达上限,使用最新版本卡在进度条进不去游戏的情况。

这个问题(以及各种缓存问题)我碰到很多很多次了,每次我都找机会喷cocos的缓存机制。

我的解决办法,大改cocos的cache。
目标是让cache尽量不达到容量上限,以及写入不卡顿:

1.控制cache内的资源,通过2个阈值:条目数量,总大小。
条目数量:较少的条目数量,会让cachelist 写入不会卡顿。我控制在1200条。
总大小:控制大小不超过平台对应的限制,另外加上余量。我控制在150M。
每加入一个文件,我都会检查,如果超过阈值,立即删除64个cache内的文件。
为了支持大小统计,我对每个条目加入了size项。

2.把删除和写入全部改成同步
原始机制是清理cache删除用定时器来删,用异步接口删除。原来的问题是:满了以后,删除的速度还跟不上下载的速度,或者玩家在途中关闭时,造成删除内容和cache list 不同步。
改成同步后,避免了这个问题。

3.合适的时机删除,例如启动时,并加入重试机制,例如解压失败时候重试。
我的删除形式分成两种:
1 少量64个。用于超出阈值的即时删除
2 大量1/3,用于启动时候,或者发现解压失败时。
这2种形式,在特定环境下,都没有明显的卡顿。
解压失败时,我会立即同步清理1/3的数据,然后间隔一点点时间进行重试。
删除时,我用LRU统计来删除最早的资源。

4.cache 的版本管理
每次修改cache机制后,或者需要让玩家清理的时候,提升一个cache版本号,如果版本不匹配就清理旧的cache。

就这样才勉强解决了一部分缓存机制的问题。在某些平台上(例如抖音)还有另外未解决的问题,例如cache内(还有temp file 内)的文件被无故删除(有可能资源太多),对于这些平台我直接禁用cache(懒的改了)。

其实这些方式,还是在原来的机制上打补丁,最好的做法是重新设计一套更好的cache机制,但是改太多了怕有问题,所以就只能打打补丁。

1赞

这个问题是:清理时定时删除文件过慢,以及解压没有重试机制导致的。
它调了清理,但是没给你的zip包重试解压,但即使重试也会因为定时删除文件过慢失败。

其实,有一种办法是:不要技术解决,商务也能解决好

你指的微信扩展缓存到1G的那个吗? 它扩展后的缓存不保证持久的,就是它满了以后,可能不经过你的代码,后台删你文件,就破坏了cachelist。200M的原始缓存不会。

然后就算扩展到1G,我的游戏也会溢出,资源量还是比较大。

哪里有COCOS管理cache的文档和接口 貌似没看到过?求个说明

对外接口在assetManager 的 cacheManager 里面。

然而这个不是重点,因为对外接口也就是enable,clear之类的,没法精细控制。重点在它的实现,在引擎的 engine\platforms 里面。

一般对cache要做点稍微精细的操作,最好去引擎里面改各个平台的js。改好了再 “build:adapter” 一下就可以了。

不用ZIP方式,不用临时解压 1G还能益出?除非你每次版本更新 有大量的资源被废弃,但又占用了缓存,最终超了1G,确定有这么夸张?
至于它不保证会删除已有的cache资源的现象 我觉得这不是事 这应该不是大规模的现象,少量的资源被删除了 但你每次使用前都要加载吧 保证加载后再用就是了,我认为不会是致命问题

1.不保证会删除已有的cache资源的现象,是致命的,为什么呢。
因为cachelist 这个json里面仍然有指向这些文件的引用,cocos 会判断这个文件还存在cache,然后去读取这个文件(并不是重新下载)并失败。

这种失败的情况,我在文件删除出问题,以及抖音平台的时候就体验过了,直接失败不会再下载。而且因为cachelist是持久存在的,你不管重启几次,这个文件都必然读取失败。
更别说我们用户目录可不仅仅是存的cache,还有其他文件,如果那些关键文件被删除了,不一定保证正常启动。

所以我宁愿用200M的缓存,把管理做好一点,也不愿意碰一个随机后台删除东西的1G缓存,会破坏很多机制。

2.我们项目就是很大,最近的项目,光特效就占了1G,以前的老项目,整体资源1.5G往上,界面量超600,还有3D模型的动作,那动画很长然后类型又很多,再乘以人物数量就特别大。

咱们纯讨论啊 都是相关机制问题了,
那个1G的扩展机制,但一看到不保证临时删数据,就一直没敢用,
但又看到有说法 缺少的资源,COCOS会再自动下载,这个我一直没测过,也很不容易测试,
你说 你一个prefab吧,相关的资源粒子啊图片啊 可能一堆,你说缓存里第一次加载后正常时候,
以后某时候突然少了某个图片了,但你加载的是动画啊 引擎只会告诉你这个动画本身加载出错,但你说你怎么定位缺失的那个图片呢?
从缓存列表里删除这个图片对应的名称?还是说删除这个动画?
目前我还找到应用层资源 到cachelist对应的转换接口还,不知道都怎么处理的是

cache list 里面按单个文件处理的,缺哪个文件下哪个文件。你prefab里面突然少了哪个图片文件,下次碰到没有就会重新下,不影响整体。

但自动下载的前提是,由cocos自己的机制去删除,它会对应清理cachelist里面的条目,下次发现不在cache就重新下载了,外部删除就破坏了这个机制了。

所以现在问题不就是cachelist索引里有这个文件 但硬盘上又没这个文件了,你加载相关的资源 肯定出错了,大于1G的那个机制 不就是可能不定性的删了某个文件吗?
问题是 你怎么能重新刷新一下这个cachelist索引呢?否则不就永远僵在这里了吗?
除非你clear所有缓存,那又要重新下载所有文件了要 ,但好的坏的都被一锅端了要

问题是你 加载一个prefab 你检查这个prefab可以,但这个动画下面可能涉及到很多嵌套的子资源 怎么检查?COCOS有这个机制?
或者有没有可能 只在加载错误后,轮询一边cachelist,检查每一项是否有问题 然后定制删除这个有问题的就是了

前面有说cachelist是文件层级的,子资源也是文件,缺了就下载,这个运行起来是没问题的。

如果要加入检查,那肯定每个子资源的每个文件都要检查是否存在了,引擎层面判断是否在cache的逻辑那里,加入一步检查文件是否存在。不是上层逻辑代码层判断。

cocos加载远程资源都是通过url索引的,单文件url硬盘缓存直接给你定死了,你不换url,缓存永远可以命中。
就算你把服务器资源换了,一样给你读缓存的。
cacheList.json就是存储的资源url和映射对应磁盘上的url以及最后一次访问的时间戳。
大量资源在cdn上,后面迟早会导致磁盘空间不足。检测机制就是下载资源的时候判断是不是满了。
满了就删掉1/3旧资源,而且500ms只会删一个。
坑就在这儿,这个操作会直接导致业务层下载失败,需要业务层自己处理报错(大概率是空间不足)、下载重试。
它又不会告诉你旧资源什么时候能清除完。理论上,如果你的资源分布的不合理、bundle不够颗粒化,那游戏就直接炸了。
所以要么做一个失败时轮询下载,只到下载成功,要么就手动removeCache,自己管理资源硬盘上的生命周期,释放bundle的时候直接给手动删了。
引擎这个代码写的确实一坨,估计就没想着cocos能做什么多大的游戏。

assetManager这个设计跟没有用一样,这里的问题最多,现有的功能完全跟不上需求,以前问过官方一些问题,没有任何答复,估计他们自己都承认没做到位

给小游戏用?这么大 怎么弄,那200M连个零头都不够了 就算你用LRU方式 ,也不可能保证不超的,更何况LRU就是个鸡肋功能目前还是

颗粒化分包,用完分包释放的时候就删掉硬盘上相关的分包文件,理论上方案可行

你看看我这个楼里面的2L,就是我的解决办法,cache只存那么多条,用起来是够的。边存边删(同步)即可,我还能控制在150M缓存内。

清理掉的文件,在本轮游戏里面,因为有asset缓存和temp 文件缓存,所以不重复下载。

下一轮进入游戏,碰到没有的就再重复下载就好了。