安卓原生加载资源线程卡住一段时间

  • Creator 版本: 3.7.4
  • 目标平台: Android / iOS
    游戏内的资源都是打在包里的,在加载时会卡住画面几秒钟,无论高端机还是低端机都是。
    资源都是用到哪些加载那些,在加载过程中基本游戏就是卡死的状态,想用动画做个缓冲也不行。
    assetManager.downloader里的最大并发设置为1也不行。
    有没有好的办法能让加载不卡住线程?
3赞

对,是有这个问题,我们这边原生的表现比web还要差,就是因为加载资源卡顿。web端就好很多比较平滑。

研究了一下,cocos打出的资源里面,图片是后台线程加载的,要改线程数量在
jsb_global.cpp 里面改gThreadPool的数量。默认是3.

其他的json或者cconb那些大部分文件,就是主线程加载的,接口写的异步接口但是实际上实现是同步的fileUtils::getStringFromFile. 代码在jsb-fs-utils.js 里面readFile函数里面。

我感觉卡的部分主要还是非图片类的json数据文件的文件读取。很多数据被他们嵌入到那种复合pack的json里面,加载还要解包。这部分都是在主线程里面的。web端是调用实际的异步的操作去读取文件数据,所以不会很卡。

所以要修改的是2部分,一部分后台加载的纹理,调一下线程看看,然后另外一部分json类的数据文件,看看有没有办法弄其他线程去。

也许像jsb.loadImage那样也搞一个jsb.readFile,然后把大文件的IO放到threadPool里面比较好。然后jsb-fs-utils 就调这个真实异步的函数就好了。

大哥 咋解决的啊

关键就是2个文件,jsb-fs-utils.js 和 jsb_global.cpp
我贴一点修改,具体完整实现可以参考image的做法,本来图片已经是有线程池的了。

Snipaste_2024-05-11_18-00-11
Snipaste_2024-05-11_18-00-16

不过这个只是把文件io的等待放到了线程池里面去,具体的一些json解析之类的还是在原线程里面,这个就要看引擎那边看看怎么更好的修改了。

4赞

谢谢发现并指出问题,我们看一下怎么优化。

尝试了一下,卡顿缓解了点,但还是有点卡顿

肯定的还是会有点,还有一个大头是prefab解析和生成对象。这个部分要改好就要伤筋动骨了。只能引擎那边优化。以前我们自己弄类似的东西的时候,这部分是分帧的。
另外优化的效果其实也和你文件大小有关,我们目前项目那种3d动画比较多,每个几百k的,改了io以后效果就比较明显了。
改了fs-utils.js 以后,要记得去script目录下,进行 node bundle-adapter 的操作,普通的编译引擎是编不到这部分的。编好了就会在bin/adapter目录下面看到对应平台的修改了。

1赞

建此 issue: https://github.com/cocos/cocos-engine/issues/17012

这个会在3.8.4或3.8.5修改吗

对,如果一帧内有很多的异步文件读取,比如 100 个文件,那么用线程池,很有可能在当前帧完成了此 100 个文件的读取,在下一帧开始的时候执行 Scheduler::performFunctionsInCocosThread 的时候,就需要在主线程中顺序触发此 100 个函数的 complete 事件,是可能造成卡顿的。

你可以尝试先按照 @694543141 的方式改下。

@694543141 的代码中,有个线程安全的关键点要注意一下,就是 FileUtils::getStringFromFile 不是线程安全的,因为其内部会调用线程不安全的 fullPathForFilename,需要在 getStringFromFile 之前的主线程中去调用 fullPathForFilename 获取到绝对路径后,再在子线程中把绝对路径传递给 getStringFromFile

Fixed at

现在不卡了。

5赞

:+1: :+1: :+1:

感觉这应该是 3.8.4 「性能提升」最大的一个里程碑,肉眼可见不卡

你测试了?

没有,但是理论应该如此 :grinning:

必须实践出真知啊。

新版本是:npm run build:adapter

不影响打 call :grinning: