fix(perf): 使用 TypeCache 加速 Skill 扫描#48
Open
daixian wants to merge 1 commit into
Open
Conversation
Owner
|
感谢你的PR贡献,我在忙完这段时间后会连同你之前的PR一起评审合并 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
每次编译之后都会Domain重载然后做反射发现,这里理论上最优是应该使用 Unity 原生的
TypeCache索引来做。让codex做了对比测试,之前的开销也只有200ms,性能瓶颈不是很大,也可以不改。以下是codex的测试和审核报告,供参考。
性能优化:使用 TypeCache 加速 Skill 扫描
改动说明
本次改动使用 Unity 原生的
TypeCache索引替代原有的全域反射扫描,用于发现带有[UnitySkill]特性的方法。旧实现的扫描路径:
新实现直接调用:
具体改动见 SkillRouter.cs。
Unity 官方说明,
TypeCache使用原生侧建立的加速索引,与遍历整个 Domain 的System.Reflection相比,更适合编辑器工具中的类型和特性查找:改动原因
原实现会遍历 Unity Domain 中所有已加载程序集、所有类型以及所有公开静态方法,扫描开销会随项目规模线性增长。
在本次测试项目中,运行时共发现 770 个
public staticSkill 方法,其中UnitySkills.Editor提供 733 个,外部xuexue.automation.editor程序集提供 37 个。改用TypeCache后,托管层处理范围直接收敛到这些带有[UnitySkill]特性的候选方法,不再遍历 Unity Domain 中的其他类型和静态方法。这对于 Domain Reload 后重建 Skill 路由缓存尤其有帮助。
新实现仍然会产生必要的处理成本,包括:
MethodInfoUnitySkillAttributeHashSet和SkillInfo因此该改动并非完全消除扫描成本,而是移除了开销最宽的全域类型和方法枚举。
性能测试
在相同 Unity 项目状态下,分别对
beta旧实现和fix/typecache-skill-discovery新实现进行了对比测试。测试方式:
SkillRouter.Refresh()beta反射扫描fix/typecache-skill-discoveryTypeCache测试结果表明,Skill 扫描和路由重建耗时稳定降低了约 90%。
测试环境
兼容性
public static限制。TypeCacheAPI 兼容性没有问题。验证结果
git diff --check通过。SkillRouter.GetSchema()测试通过。automation_command_list调用成功。审查发现
本次改动没有阻断问题,但仍有两个低优先级隐患。
重复 Skill 名称
当前注册逻辑仍然使用:
出现同名 Skill 时,后发现的方法会静默覆盖之前的结果。
Unity 官方明确说明,
TypeCache.GetMethodsWithAttribute返回结果的顺序未定义。因此,不同程序集存在同名 Skill 时,最终生效的方法可能不确定。这个问题在旧实现中已经存在,并非本次改动引入。后续可以增加重复名称检测,并输出明确错误。
窗口刷新存在重复处理
Skills 窗口刷新时会依次调用:
具体位置见 SkillsTabController.cs。
这会执行两次
TypeCache查询,并重复进行部分 Attribute 实例化、窗口列表和路由字典构建。目前
TypeCache查询本身已经很轻,这还不是性能瓶颈。后续可以让窗口直接使用SkillRouter的缓存快照,进一步消除重复处理。结论
本次改动在保持原有行为和外部 Skill 扩展能力的前提下,移除了 Skill 发现阶段对全部程序集、类型和静态方法的遍历。
实际对比测试显示,Skill 扫描和路由重建耗时降低约 90%,建议合并。