# 代码分包

# 概述

# 背景

unity 导出小游戏项目后,代码是在一个 wasm 文件里,经过 brotli 压缩后,放在 wasmcode 目录下

一般小游戏的 wasm 大小都为 30M 左右,压缩后为 6M 左右

启动阶段,小游戏需要先下载完 wasmcode 再编译,这里会占用较高的内存和启动时间,这对用户都是非常重要的指标。

因此我们提供了Wasm代码分包工具,将原来的 wasm 拆分为两个,一个用于启动加载(主包),另一个可以延迟加载(子包)

使得小游戏可以先加载较小的首包进入主场景,再异步加载剩下的分包。大幅度降低下载时间和编译耗时(几秒)

另外对于iOS高性能模式,子包不会加载,会转为按函数粒度按需加载,从而大幅度减少内存压力(200-300MB),减少崩溃

本文章将先介绍操作步骤,再介绍开发者长期迭代时所需关心的核心指标以及问题

# 实现原理

目前我们采用了一种 Profile Guided Optimization 的方式,通过运行时收集信息,按函数粒度对小游戏的 wasm 代码包进行拆分

开发者可以在开发阶段,通过真机运行小游戏,并尽量覆盖游戏内的场景,特别是启动后最先进入的场景和关卡(比如新手教学,游戏最初的关卡内容)来收集信息。

工具上会显示收集到的函数个数,这时候就可以重新分包,将收集到的函数加入首包。

因此收集工作非常重要,收集的场景覆盖率越高,命中子包的时机就可以相应延后,使得首包可以满足大部分新玩家前几分钟的游戏进程

我们提供了一个微信开发者工具里的插件来辅助分包过程,依赖的开发者工具版本为 1.05.2104251 RC 及以上,稳定版 1.05.2105100 已支持。

分包技术会持续迭代,请确保使用最新的分包插件以及Unity/团结引擎导出插件,以获得最优的分包性能体验。

# 插件安装

通过开发者工具的设置-拓展设置-编辑器自定义拓展,安装 wasmCodeSplit 这个插件

# 插件更新

开发者工具上(如果用的是stable版,非minigame版)的插件一般是自动更新的

手动更新

# 插件使用

分包插件按小游戏的md5(wasmcode下的wasm文件名里的md5)来区分不同的小游戏包

相同md5的小游戏包会复用同一份分包结果

对于新构建的小游戏包,分包流程如下:

  • 点启用代码分包
  • 输入当前项目版本描述
  • 等待上传代码包
  • 等待预处理
  • 选择是否增量分包,然后下一步
  • 等待第一次分包
  • 进入正式分包阶段,先android收集,然后继续下一步
  • iOS收集,然后继续下一步
  • 选择生成profile或者release包,然后收集,这一步可以重复进行

最后一步这里已经可以随时上传体验版了

具体操作和注意事项如下

# 启用分包

打开插件开关后,在目录树上的工具栏中,可以看到插件的按钮,如图所示,点击后即可进入插件页:

# 输入版本描述

# 等待上传文件

# 等待预处理

注意:如果出现红框中的提示,说明这里的状态更新已经中断,需要重启开发者工具

这一步一般是分钟级的耗时,如果等待超过10分钟,建议先重启下开发者工具

# 选择是否增量分包

如果这个游戏之前的包已经有用过代码分包,没有比较大的代码修改的情况下(比如大范围的代码重构,更换引擎),可以使用增量更新,也就是选择之前的某个包作为参考

我们会对比前后两个包的symbol,把之前收集过的函数当做放到首包,即无需重复收集

因此要求前后两个包都必须提供symbol文件

在unity侧使用微信插件导出时,需要开启profiling func,这样打包时就会导出symbol文件(webgl.wasm.symbols.unityweb)

无需担心开启profiling func导致的包体增大,分包工具会优化函数名

# 等待分包

#

android收集 + iOS收集

分包的收集,一般需要android和iOS单独收集

收集操作:

  • 点击开发者工具的预览(注意是预览,不是真机调试,在真机上跑游戏,覆盖尽可能多的场景
  • 当插件页显示的收集到增量函数个数相对稳定时,可以点击“我已收集好,继续下一步”

这里主要关注首包函数个数,一般跑完这两个步骤首包函数占整包函数个数的30%以上就差不多了

# 重复收集与生成

android和iOS收集完,基本就可以测试和发布了

有条件的话,可以尽量覆盖各种机型(主流品牌)再多跑几次收集

每次收集发现新增函数趋于稳定之后,就可以继续点生成profile分包或者生成release分包

每次点生成时,会先跳到前面的等待分包界面,完成后再回来

# 函数名获取与手动上报

为了方便开发者分析首包函数来精简代码,提供了“已收集函数名获取”和“手动上报”的能力。

点击“获取首包函数名和新增函数的函数名”会下载并打开两个txt文件分别包含首包函数名和新增函数名。

点击“选择函数名文件手动上报”即可选择之前下载的函数名文件上报(上报格式参考获取函数名时的文件格式),方便在切换 appid 后也能实现增量分包,也可以针对自己游戏预先准备好一份函数名文件(除非确定需要,否则不建议)手动上传来节约人工运行收集函数的时间。

函数名获取与手动上报

每次生成会当前的分包version会加1

# 关闭分包

如果想回退到未分包的版本,点击关闭代码分包即可

# 注意事项

上线前

  • 生成release版分包
  • 首包函数个数至少要有原始包函数总数的30%
  • 新增收集函数个数清零
  • 关注android或者iOS普通模式的子包是否过早加载(是否有wait for func的日志)
  • 关注iOS高性能是否有fetch js相关的日志

如果有最后两点,那就还要继续收集+生成分包

上线后

  • 小游戏包先不要删掉
  • 新增收集函数个数这个数据非常重要,要尽量保持关注,包括上线后

如果上线后,有玩家遇到新增函数个数,分包插件上也会更新(主要来源是iOS高性能),或者收到小游戏数据助手的相关告警,这个时候要继续生成分包,同时提审发布

# 分包关键信息

# 分包基本信息

这里介绍基本分包的信息,具体使用见分包流程

basic-info

以上展示了分包的基本信息:

当前分包版本:profile包用来收集,release包用来发布。profile包千万不能发布上线,性能和内存表现非常差。

当前项目AppId:为当前分包小游戏的AppId。对同一个AppId的任何分包操作,都将排队进行,如果团队内有同时开发,可能会出现突然耗时很长的情况,请耐心等候。

当前插件版本:Unity启动插件版本。对应game.json中的UnityPlugin。它并不是分包插件的版本。分包插件的版本在插件扩展页面可以获取。

当前后台服务版本:为分包的技术版本,代表不同的分包技术,越新越好。截止文档攥写时,分包技术版本最新为7

当前代码md5:为小游戏项目的唯一标识,相同的md5被识别成同一分包项目。若Wasm不同但md5相同(开发者人为修改才会出现),则也会被视作同一个项目。若想对同一个小游戏项目重新预处理分包,则可以修改代码md5或者重新导出游戏包。

当前分包version:代表第几次分包。第一次分包为version 0,第二次为1,以此类推。

已经开启优化项:为空则表示没有开启任何优化项。这个优化项可以在“微信优化项”勾选。

原始包函数总个数:开发者原始Wasm包的函数个数。

当前首包函数个数:当前首包Wasm中函数的个数。

新增收集函数个数:本次收集中发现未在首包的函数。

微信优化项:对Wasm的运行表现进一步优化。开发者需要知道,这些优化项只会在部分场景有优化效果,请阅读相关说明,并自行比对优化效果。

已收集函数名获取:获取首包函数,以及新增收集的函数名字。

选择函数名文件手动上报:若开发者预先知道哪些函数一定要收集,则可以构造一个函数名文件,格式参考“已收集函数名获取”文件格式。请注意,过量的收集会膨胀代码提及,增大内存压力。请确保手动上报的函数一定需要收集。

关闭代码分包:将代码包从分包状态复原为原始小游戏包文件状态。如果需要恢复到分包状态,请开启分包并重新下载分包文件。

# 分包项目结构

分包项目结构如下:

file-structure

以上展示了分包的基本结构,我们主要关注以下文件:

wamcode:分包前,这是原小游戏Wasm包。分包后,是首包/主包。这是一定会被加载且首先被加载的Wasm。

wasmcode1:这是安卓平台的子包,不会一开始就下载以及加载,而是在游戏运行后一段时间,自动加载。或者缺失函数的时候再加载。

wasmcode2(可选):部分分包技术下,会有该分包,为iOS平台的子包,不会一开始就下载以及加载,而是在游戏运行后一段时间,自动加载。或者缺失函数的时候再加载。

webgl.wasm.symbols.unityweb:这是symbols文件,用来还原每个函数id对应的函数名,请保留,有需要的时候查看。

分包后项目大小会膨胀,这是正常的。分包需要一些辅助的文件,但只有首包(wasmcode)一定会加载,其他的则会延迟或者按需下载,对运行几乎没有影响。

首包的大小在3-5MB,子包在7-15MB,wasmcode+wasmcode1+wasmcode2在10-25MB内。

# 微信优化项

分包集合了许多定制的优化项,与游戏特征有关,按需选择。目前仅在“后台服务版本:6”及以上支持选择开启特殊优化,同时依赖开发者的分包插件和Unity导出插件等版本。如有需要请更新分包插件和Unity/团结导出插件的版本至最新,获得最好的性能体验。

  • profile包性能优化:分包后台服务版本大于等于6。会修改函数调用上报的记录方式,使得运行性能接近 release 包,提高收集函数的效率,并且不存在什么负面影响,默认开启。
  • 函数量优化:分包后台服务版本大于等于6,且unityPluginVersion≥1.2.69时支持该优化项,但默认不启用。可以进一步减小分包后的wasm包中的函数量,从而减小编译内存占用。该优化项与游戏代码特征有关,更适合存在大量调用频率非常少函数的游戏,对运行性能有0~5%负面影响,内存占用降低0-50MB,需要游戏自行测试收益并选择。函数量的减少并不反映在分包面板上,但实际函数有一定减少。 微信优化项

# 评估分包状态

开发者在函数收集/上线后,都需要关心分包是否到位,并做出及时反映。平台也在探索更易用的交互和体验方式,优化开发者体验。

# 上线前的分包收集

开发者需要关心自己分包是否到位,可以用以下方法评估分包状态:

函数收集需要保障启动时刻的函数收集,在启动和游玩的前期,是用户最容易流失的时候(前30-45s),必须保证函数完全不缺失,否则缺失会造成卡顿,影响游玩体验甚至启动速度。

通过vConsole以及日志中,是否有wait for func 或者 fetch js:等函数的日志,来判断当前是否出现了函数的缺失。同时当画面出现一卡一卡的,或者突然卡死,需要考虑当前是否出现了函数的缺失。

同时,我们还可以关注一些对应的日志,例如“首次拉取js函数:xxms”表示首次缺失函数的时间,如果在45s内,就是收集不够。还有,“在callmain完成前fetchjs”日志,表示函数缺失甚至在引擎启动阶段就出现了,这会极大影响游戏的启动时间。

如果收集过程中出现了这个问题,需要及时收集,并重新分包,保证这些函数都在首包内。

由于不同机器有一定差距,因此也会出现一个机器收集后,另一个机器出现缺失。这是正常的,开发者需要根据实际情况,例如线上启动时间的变化等,选择是否需要重新收集/分包/上线。

越多的函数在首包,首包就会越大,启动时间和占用的内存也会越多,但就现在游戏的经验来看,收集的越多越好,因为大部分的函数是不会被收集到的,分包的优势仍然非常大。但请开发者不要盲目手动上报一些不缺失的函数,这样也会影响性能表现。

如果开发者发现,自身的游戏,在不同场景上,运行到的函数数量有巨大的差别(上万个函数差别),统一打包到首包会使得首包特别大,请联系小游戏助手,获取技术上的帮助。

一般来说,函数首包收集在25~50%比较正常,一般就是35%左右。

# 上线后的缺失/收集/补救

需要首先强调的是,Profile分包严禁上线,性能有非常大折损,请用Release分包上线。

我们在线上的分包运行时,也插入了比较稀疏的上报,能够在线上缺失的时候自动收集函数。

因此,游戏上线之后,开发者仍然能通过分包面板,看到自身的新增函数个数。

新增的函数是否会影响线上的表现,有一定讨论空间。如果这个新增的函数在启动前期,那么就算只有几个函数,也应该立刻收集并重新发布。

微信分包平台为保证用户的体验,采取了Patch包机制,自动的根据收集的新增缺失函数,生成Patch包,自动修复缺失函数。但是,这与机器的系统版本、网络环境、分包插件依赖组件的版本等有关。因此,如果使用老的分包插件,或者老的Unity/团结引擎导出小游戏,可能无法使用该功能。而且,就算支持,也并不一定能成功在所有的游戏玩家设备上加载,Patch包也有上限大小,因此我们主张开发者在函数量过多(100以上)的时候,主动进行分包,并重新上线。

对于长期迭代的开发者来说,还会使用增量分包。但增量分包是基于函数名进行匹配的,而由于原函数到Wasm函数,有较长的一段编译器生成距离,因此同一个函数没有进行任何改动,其名字和结构仍然有可能变化。最终,增量分包并不一定会完全覆盖原有的所有函数。我们主张开发者应该尽可能保障前45s的启动黄金期,保证函数在首包内。后面的函数缺失,如果函数symbol文件差异非常小,则可以采用更为高效的收集方式。

# CI工具

wasm代码分包作为微信开发者工具的插件,需要开发者在微信开发者工具中手动操作,在高频发布场景下效率偏低

因此我们提供wasmsplit-ci工具,可以不打开微信开发者工具,独立使用进行分包的各种操作(真机收集除外),供开发者集成到ci流水线上

# 功能

wasmsplit-ci目前提供以下能力:

  • 打开分包
  • 生成分包
  • 获取分包信息
  • 关闭分包

建议使用场景:

  • 大版本开发阶段:按新增函数阈值定期生成profile包
  • 小版本(代码无修改或无新增函数)或者bugfix阶段:直接走增量分包生成release包

# 准备工作

# 密钥配置

wasmsplit-ci的使用需要传入密钥,需要在mp管理端-开发支持-研发工具箱-密钥管理-Wasm分包CI鉴权配置密钥

# 命令行调用

# 安装

通过npm获取

npm install -g wasmsplit-ci

# 支持命令

打开分包

Usage: wasmsplit-ci init [options]
init miniprogram
Options:
  -p, --project-path <projectPath>                
      project path, 小游戏项目的路径, 必填
  -k, --private-key-path <privateKeyPath>         
      private key path, 私钥文件的保存位置, 必填
  -d, --version-description <versionDescription>  
      version description, 版本描述
  -r, --refer-md5 <originalMd5>                   
      original code md5, 历史代码包md5
  -h, --help                                      
      display help for command

init命令会检查当前项目(appid+code_md5)的分包状态,完成必须的前置准备工作

流水线每次执行都需调用init命令进行初始化操作

如果本次流水线需要增量更新则需传入供增量参考的游戏包的md5

增量更新必须在项目首次分包时使用

示例

# 首次分包,需要增量分包
wasmsplit-ci init -p ./minigame-dir/ -k ./ci-privatekey -d "v1.0.0" -r $REFER_MD5
# 非首次分包,或者首次但不需要增量分包
wasmsplit-ci init -p ./minigame-dir/ -k ./ci-privatekey -d "v1.0.0"

查看当前分包信息

Usage: wasmsplit-ci getinfo [options]
get minigame function info
Options:  -p, --project-path <projectPath>         
      project path, 小游戏项目路径, 必填
  -k, --private-key-path <privateKeyPath>  
      private key path, 私钥文件路径, 必填
  -h, --help                               
      display help for command

getinfo获取信息,并以json格式保存在"$projectpath/.plugincache/codesplit/gameinfo.txt"中。

getinfo的json字段说明

说明
isProfile 当前分包版本(profile或release)
appid 当前项目AppId
md5 当前代码md5
subVersion 当前分包version
apiVersion 当前后台服务版本
sourceFuncNum 原始包函数总个数
increaseNum 新增收集函数个数
currentNum 当前首包函数个数

示例

wasmsplit-ci getinfo -p ./minigame-dir/ -k ./ci-privatekey

生成分包

Usage: wasmsplit-ci dosplit [options]
split minigame package
Options:  -p, --project-path <projectPath>         
      project path, 小游戏项目路径, 必填
  -k, --private-key-path <privateKeyPath>  
      private key path, 私钥文件路径, 必填
  --release                                
      release, otherwise profile, 是否release分包
  -h, --help                               
      display help for command

有新增函数即可调用,命令执行成功后会下载分包结果,应用到minigame-dir目录,执行失败可重复执行

生成分包后,可随时上传体验版

示例

# profile
wasmsplit-ci dosplit -p ./minigame-dir/ -k ./ci-privatekey
#release
wasmsplit-ci dosplit -p ./minigame-dir/ -k ./ci-privatekey --release

关闭代码分包

Usage: wasmsplit-ci disable [options]
disable code split Options:
  -p, --project-path <string>  project path, 小游戏项目路径, 必填 
  -h, --help                    display help for command

disable命令用于关闭代码分包,和插件的关闭代码分包作用相同

示例

wasmsplit-ci disable -p ./minigame-dir/

# 流水线示例流程

alt text

# 注意事项

  • 此工具不能完成真机收集过程,真机收集仍需开发者单独执行
  • 分包工具CI不提供预览及上传功能,可以使用微信开发者工具CI进行预览
  • 请不要将密钥配置文件(id_rsa.conf)放在小游戏项目下,这会导致密钥文件一同被上传
  • 日志文件保存在$projectpath/.plugincache/codesplit/log目录下,使用两个文件滚动保存(latest.log和backup.log),每个文件保存最大容量为5M
  • 如需更改appid,自行修改项目路径下project.config.json文件中的appid

# 常见问题排查

  • 错误码:-10000401 密钥检验失败,请检查密钥是否正确 验签失败,请检查公钥私钥是否匹配
  • 出现"need retry task: retryInit"之类的日志后中断执行,如果不是私钥路径错误的话,一般是私钥格式不对,私钥和MP配置的公钥都需要是PEM格式的。
  • 使用CI分包后,miniprogram-ci上传时报错"main package source size 4369KB exceed max limit 4096KB",需要更新miniprogram-ci到beta版2.1.14。

# 排查/反馈分包问题

分包运行时问题排查时,需要重点关注用户设备的运行环境,在遇到问题的时候应该要确保预先排查:

  • 问题形式:问题的发生形式,例如:启动失败、加载失败、运行时错误等。
  • 问题时刻:问题发生在哪个阶段,例如:启动、加载、运行等。
  • 问题特征:问题发生与什么环境有关,例如:设备类型、系统版本、网络环境等。
  • 是否复现:问题是否可以复现,用户遇到的量级有多少。例如:是否是随机事件,是否是用户操作导致的。

开发者自身不进行预先排查的,小游戏技术支持很难帮助开发者排查问题。

当开发者仍然无法定位和修复问题的时候,可以联系小游戏技术支持,在必要的时候,开发者需要提供游戏导出的项目文件协助排查。。

# 分包运行时问题排查

基础库版本和设备信息见vConsole或者日志如下: 基础信息

分包插件及相关信息见如下: 插件信息

分包流程运行步骤见如下:运行过程可以参考 启动流程 alt text

除了直接看vconsole,还可以导出日志文件,然后分析日志文件。 alt text

# FAQ

# 分包是否是必要的

对于 iOS 高性能模式,由于内存限制,游戏加载完整 wasm 基本就会内存 crash。分包能降低内存占用,同时我们对子包支持按需加载,才让游戏能稳定跑起来

所以如果是使用了 iOS 高性能模式则是必须的

对于 android 和 iOS 普通模式,分包主要目的是优化启动加载,另外这两个 runtime 下由于子包可以全量加载,因此对游戏运行影响最多只有加载子包的一次性影响

我们也会在启动 callmain 后 30s 提前加载子包,在这个时间之后才触发未收集函数的情况也不会有加载子包的影响

# 收集到什么时候可以结束

按照我们经验,一般首包函数有整包个数的 33%以上的时候就可以接受了,当然能尽量再收集完善刚好,个别游戏可能会接近 50%

这时候不代表没收集的函数都没用了,实际上有些函数可能只是调用比较冷门,后续还是可能会被调到,可以通过分包插件面板的新增收集函数个数来留意线上新增的情况,

如果线上新增较多(超过 50),可以考虑再往下分一次包然后提审发布

# 游戏内容难以遍历完整怎么办

我们针对这种情况也有线上patch可以进行补漏,但是patch有大小限制

建议新增收集函数个数超过100个的还是要生成新分包+发版本

# 分包总大小比原始包大/我的代码包分包后膨胀了很多怎么办?

这是正常现象。分包需要一些辅助的文件,但只有首包(wasmcode)一定会加载,其他的则会延迟或者按需下载,对运行几乎没有影响。

首包的大小在3-5MB,子包在7-15MB,wasmcode+wasmcode1+wasmcode2在10-25MB内。

  1. 分包的目的主要是将启动时需要的包减小,一般分包后wasm首包可以控制在原包的1/3到1/2之间
  2. 子包是有延迟加载的,因此耗时上不需要看总的大小,看首包的减少量即可
  3. 一般iOS高性能模式才有内存使用瓶颈,而iOS上子包是按需加载的,可以缓解内存问题 因此,这里不需要关注分包后所有wasm包的总和,主要关注wasm首包(即minigame/wasmcode)的大小即可

# 新增收集的函数要重新再次提审才会在首包吗

对的,用户下载的代码包只能是提审发布过的

# 会不会最终跑到所有函数都收集的情况

目前还没出现这种情况,超过整包 50%的都很少

大部分游戏收集 1 小时的函数个数都在 33%到 50%之间

可以等收集函数超过 75%了再来考虑这个问题

#

iOS 高性能模式收集很卡

iOS 高性能模式由于加载子包的实现不同,刚开始收集时又基本是跑子包函数,所以最开始的收集会比较卡

这个时候可以观察分包插件面板,如果能看到有新增函数个数的变化,一般就是没问题的。如果出现卡顿(并且有新增函数)或者新增函数较多(超过 50),可以先继续往下生成分包,再进行收集。游戏运行会随着收集越来越流畅

#

iOS 高性能模式代码分包后内存反而变得很高

这种情况一般是太多新增函数(比如几百个),iOS 高性能模式的子包代码也会占用大量内存,可以继续生成分包,将这部分函数放在首包(放首包的内存占用相对小些)

#

iOS 高性能模式出现 import section's count is too big

新版的插件已经规避这个问题,更新插件即可

# Profile分包可以上线吗?

不可以!性能有非常大的劣化,在内存和帧率上都表现很差,玩家体验很差。

目前由于发布时无法获取分包信息,暂无法拦截profile包上线,请不要尝试上线profile分包。

# 没有看到增量分包的界面

由于增量分包是新增的功能,因此之前的项目不能被用来增量更新。更新分包插件后,第二次导出的版本开始才可以使用

# 增量分包没生效

请检查指定参考的旧版本以及当前版本是否都有 symbol 文件,以及是否有更换引擎或者其他导致代码变动较大的操作

# 如何更新分包插件

微信开发者工具会自动更新分包插件,一般不需要手动更新。可前往微信开发者工具-编辑器区域-拓展列表查看插件版本确认是否为最新版本

请勿使用小游戏版微信开发者工具,会出现插件无法正常更新或安装。请前往:适配文档-安装与使用,下载stable版本微信开发者工具。

# 分包插件安装失败

首先确认是否为stable版本开发者工具。

有两个地方可安装插件:

  1. 编辑器区域-拓展:搜索wasm-code-split,点击安装
  2. 菜单栏-设置-拓展设置,找到wasmcodesplit,点击进入详情页,点击获取

# 分包插件卡住

遇到流程卡住问题,一般先尝试关闭分包,然后重启开发者工具,再打开分包,大部分时候有奇效

# 如何查看分包插件日志

当出现问题时,优先排查是否stable版本的微信开发者工具,能解决大部分问题。 若问题仍无法解决,可联系我们,提供日志排查。 日志获取方式:

菜单栏-微信开发者工具-调试-调试微信开发者工具,搜索关键字:extension host。可右键保存日志文件

# 为什么我的预处理/分包时间特别慢?

可能是同一个appid提交过一次预处理,正在排队。请确保一次预处理结束之后再进行其他分包操作。

分包的时候,如果开发者还在同步收集函数,分包过程会重试,以将该阶段收集的函数均纳入进入。若开发者一直在分包的时候收集函数,会一直重试,直到收集完成,过程可达数小时。

至于预处理,其耗时比正常分包长,长的可能到20-30分钟,分包则5分钟(release显著更长)。若超过再怀疑是否时间过长。

重新导出游戏包或者更换md5,若多次仍如此,联系技术人员,怀疑该Wasm包分包不适配。

重试频率不能太快,预处理要排队,多次重试,会依次执行。

# 偶发白屏闪退、内存不足闪退

iOS15.4中(https://bugs.webkit.org/show_bug.cgi?id=237180)WASM VM 在处理特定优化后的代码时,未能正确地处理内存或数据对齐,导致运行时数据被破坏。特定代码意味着和代码特征有关,并不是所有Wasm都会出现。

现象:

2025-9-26 9:14:28 [warn] Could not allocate memory: System out of memory!

Trying to allocate: 3196395193B with 16 alignment. MemoryLabel: TempOverflow

Allocation happened at: Line:xxx

# WebAssembly相关接口不存在

WebAssembly相关接口不存在(如WebAssembly.instantiate)

用户的iOS可能启用了锁定模式,因此该接口被锁定

https://support.apple.com/zh-cn/105120

# 分包下载经常出错/分包经常中断

检查本地网络状态。

点击咨询小助手