# 背景 文件名:2025-12-01_1_performance_optimization_aggressive.md 创建于:2025-12-01 创建者:User 主分支:main 任务分支:task/performance_optimization_aggressive_2025-12-01_1 Yolo模式:Off # 任务描述 对Unity音游编辑器项目进行激进的、彻底的性能优化,使用最先进的技术栈。项目限定在Windows 10+平台运行。 ## 核心问题 基于Tracy Profiler分析结果: 1. **SplineNode.ScriptUpdate**: 5.66ms (19.37%), 3,240次调用 - 函数调用开销过大 2. **递归Update模式**: 深度树形遍历导致缓存不友好 3. **剪枝不彻底**: 大量对象在非活跃时间范围内仍在Update 4. **Timeline UI更新**: 存在严重性能开销(已知问题) ## 性能目标 - 将SplineNode.ScriptUpdate从5.66ms优化到<0.5ms(**10倍以上提升**) - 帧率从77fps提升到120fps+ - 消除不必要的Update调用(减少70%+调用次数) # 项目概览 - **项目类型**: Unity音游编辑器 - **核心框架**: Convention框架 + RScript脚本系统(基于FLEE) - **主要系统**: - ScriptableObject树形更新系统 - Updatement插值系统 - IInteraction多级判定系统 - SplineCore样条线渲染 - TimelineScriptObject时间轴对象 ## 技术栈 - Unity 6.2 (6000.2.51) - C# (支持最新特性) - Tracy Profiler 0.11.1 - Windows 10+ 专用 ⚠️ 警告:永远不要修改此部分 ⚠️ # RIPER-5核心规则摘要 - 必须在响应开头声明当前模式:[MODE: MODE_NAME] - RESEARCH模式:只读取和理解,禁止建议和实施 - INNOVATE模式:讨论多种方案,禁止具体实施 - PLAN模式:创建详尽技术规范,必须转换为编号清单 - EXECUTE模式:只实施已批准计划,禁止偏离 - REVIEW模式:验证实施与计划的完全一致性 关键原则: - 未经明确许可不得在模式间转换 - EXECUTE模式必须100%忠实遵循计划 - 标记任何偏差,无论多小 - 使用中文响应(除模式声明和代码) ⚠️ 警告:永远不要修改此部分 ⚠️ # 分析 ## 当前架构分析 ### 1. Update调用链(存在问题) ``` GameController.Update() └─ RootObject.ScriptUpdate() └─ foreach (child in UpdateChilds) └─ child.ScriptUpdate() // 递归,3,240次 └─ child.UpdateTicks() // 虚函数调用 └─ 具体逻辑 ``` **性能问题**: - 递归调用开销累积 - 虚函数调用开销 - 缓存不友好(对象内存分散) - 无法并行化 - 大量对象在非活跃时间范围内仍被调用 ### 2. 现有优化机制(不足) 代码中存在一些优化: - `UpdatePerFrame`: 降低Update频率 - `IsEnableUpdate`: 静态剪枝(只能剪掉永远不更新的对象) - Update树剪枝:简化单子节点调用链 **不足之处**: - 无法剪枝"暂时不活跃"的对象 - 无法利用多核CPU - 内存布局对缓存不友好 ### 3. 技术约束 - Unity主线程限制:Transform等API必须在主线程调用 - MonoBehaviour限制:继承自MonoBehaviour的对象管理复杂 ## 可用的先进技术 ### Windows 10+ 专属优势 1. **SIMD指令集**: AVX2, AVX-512(如果CPU支持) 2. **现代CPU特性**: 更多核心,更好的缓存 3. **.NET 最新特性**: Span, Memory, stackalloc 4. **Unity DOTS**: ECS + Job System + Burst Compiler ### Unity DOTS技术栈 1. **ECS (Entity Component System)** - 数据驱动架构 - 缓存友好的内存布局 - 易于并行化 2. **C# Job System** - 托管的多线程系统 - 自动线程池管理 - 安全检查避免竞态条件 3. **Burst Compiler** - 将C#编译为高度优化的机器码 - SIMD自动向量化 - 接近C/C++的性能 4. **Collections Package** - NativeArray, NativeList等非托管集合 - 可在Job中安全使用 - 避免GC压力 ### 性能提升潜力 | 技术 | 预期提升 | 适用场景 | |------|---------|---------| | 时间范围剪枝 | 3-5倍 | 所有TimelineObject | | 扁平化调度 | 2-3倍 | Update调用链 | | Burst编译 | 5-10倍 | 数学密集计算 | | Job并行 | 2-4倍 | 批量数据处理 | | 缓存优化 | 2-3倍 | 数据访问模式 | | **综合** | **30-100倍** | 整体系统 | # 提议的解决方案 ## 方案概览 采用**混合架构**:保留MonoBehaviour作为外壳,内部使用ECS数据处理。 ### 架构设计 ``` 传统层(MonoBehaviour) ↓ 数据同步 ECS数据层(Burst Job处理) ↓ 结果同步 传统层(应用到Transform) ``` ## 核心方案要素 ### 1. 时间分片调度系统 **目标**: 只更新活跃时间范围内的对象 **实现**: - 使用SortedSet维护时间排序 - 激活/停用事件驱动 - 扁平化对象列表(无递归) **预期**: 减少70%无效Update调用 ### 2. ECS化核心系统 #### 2.1 Updatement系统(最适合ECS) - 纯数据:Entry列表、插值参数 - 纯计算:Lerp、曲线求值 - 可完全Burst编译和并行化 #### 2.2 Interaction判定系统 - 输入处理可并行化 - 判定计算可Burst优化 - 结果批量应用 #### 2.3 SplineNode计算 - 样条线计算适合SIMD - 批量计算所有节点位置 - Burst编译获得巨大提升 ### 3. Burst编译的Job ```csharp [BurstCompile] public struct UpdatementCalculationJob : IJobParallelFor { [ReadOnly] public float CurrentTime; [ReadOnly] public NativeArray Entries; [ReadOnly] public NativeArray ContentIndices; [WriteOnly] public NativeArray Results; public void Execute(int index) { // 纯数学计算,Burst自动SIMD优化 int content = ContentIndices[index]; float percent = CalculatePercent(CurrentTime, Entries, content); Results[index] = math.lerp( Entries[content].Position, Entries[content + 1].Position, EvaluateCurve(percent, Entries[content].CurveType) ); } } ``` ### 4. 内存布局优化 **SoA (Structure of Arrays) 代替 AoS (Array of Structures)**: ```csharp // 坏:AoS(缓存不友好) struct UpdatementData { float timePoint; Vector3 position; EaseCurveType curve; } UpdatementData[] data; // 数据交错 // 好:SoA(缓存友好) struct UpdatementDataSoA { NativeArray timePoints; // 连续 NativeArray positions; // 连续 NativeArray curveTypes; // 连续 } ``` ### 5. 对象池系统 - 避免GC压力 - 重用NativeArray - 预分配Job句柄 ## 实施分层 ### Phase 1: 基础设施(1周) 1. 时间分片调度器 2. UpdateScheduler基类 3. 基础性能测试框架 ### Phase 2: ECS核心(2周) 1. Updatement系统ECS化 2. Burst Job实现 3. 数据同步机制 ### Phase 3: 扩展优化(2周) 1. SplineNode优化 2. Interaction判定优化 3. 对象池和内存管理 ### Phase 4: 深度优化(1周) 1. SIMD手动优化关键路径 2. 内存布局调优 3. 性能剖析和微调 ## 技术细节 ### Job依赖管理 ```csharp // 计算Job JobHandle calcHandle = calculationJob.Schedule(count, 64); // 应用Job(依赖计算Job) JobHandle applyHandle = applyJob.Schedule(calcHandle); // 等待完成 applyHandle.Complete(); ``` ### 安全检查 Unity Job System提供编译时和运行时安全检查: - 检测数据竞争 - 验证NativeArray生命周期 - 防止悬空指针 ### Profiler集成 保持Tracy Profiler集成: ```csharp using (Profiler.BeginZone("BurstJob.Schedule")) { handle = job.Schedule(count, 64); } ``` ## 风险与挑战 ### 技术风险 1. **学习曲线**: ECS和Burst需要学习 2. **调试难度**: Burst代码调试较困难 3. **兼容性**: 现有脚本系统集成 ### 缓解措施 1. 渐进式迁移,保持向后兼容 2. 完善的性能测试 3. 详细的文档和注释 ### 回滚计划 每个Phase完成后打tag,必要时可回滚 # 当前执行步骤: "阶段2.5 - 阶段2整体测试" # 任务进度 ## 阶段1:基础设施搭建 ### 1.1 创建目录结构 [2025-12-01 17:16:16] - 已修改:创建目录 Assets/Scripts/Framework/UpdateScheduler/ - 更改:新建UpdateScheduler模块目录 - 原因:为扁平化调度器准备代码组织结构 - 阻碍因素:无 - 状态:未确认 ### 1.2 创建IUpdateable接口 [2025-12-01 17:17:30] - 已修改:创建文件 IUpdateable.cs (48行) - 更改:定义IUpdateable接口(3个方法)和UpdateMode枚举(3个值) - 原因:为ScriptableObject提供统一的Update接口,支持扁平化调度 - 阻碍因素:无 - 状态:未确认 ### 1.3 创建UpdateScheduler核心类 [2025-12-01 17:18:45] - 已修改:创建文件 UpdateScheduler.cs (201行) - 更改:实现完整的扁平化调度器(Register、DoUpdate、时间分片、Reset/Clear等) - 原因:提供时间分片和扁平化Update管理的核心实现 - 阻碍因素:无 - 状态:未确认 ### 1.4 RootObject添加Scheduler字段 [2025-12-01 17:20:15] - 已修改:RootObject.cs (添加1行,Line 19) - 更改:添加Scheduler字段并初始化 - 原因:为RootObject提供调度器实例 - 阻碍因素:无 - 状态:未确认 ### 1.5 RootObject添加清理逻辑 [2025-12-01 17:21:30] - 已修改:RootObject.cs UnloadScript方法 (添加2行,Line 38-39) - 更改:在卸载时调用Scheduler.Clear() - 原因:防止内存泄漏,正确释放注册对象 - 阻碍因素:无 - 状态:未确认 ### 1.6 阶段1整体测试 [2025-12-01 17:22:45] - 已修改:阶段1所有代码完成,等待测试 - 更改:基础设施搭建完成(3个新文件,RootObject修改2处) - 原因:验证阶段1无破坏性影响 - 测试项目: 1. 编译项目 - ✅ 已通过(无linter错误) 2. 运行编辑器 - ✅ 用户确认成功 3. 打开项目 - ✅ 用户确认成功 4. 检查RootObject.Scheduler字段 - ✅ 用户确认成功 5. 关闭项目 - ✅ 用户确认成功 6. 检查控制台无错误 - ✅ 用户确认成功 - 阻碍因素:无 - 状态:✅ 成功 - Commit: 用户已提交 ## 阶段2:接口适配 ### 2.1 ScriptableObject添加IUpdateable接口声明 [2025-12-01 17:30:00] - 已修改:ScriptableObject.cs 类声明 (Line 582,添加IUpdateable接口) - 更改:ScriptableObject实现IUpdateable接口 - 原因:使所有ScriptableObject可以被调度器管理 - 阻碍因素:无 - 状态:未确认 ### 2.2 添加Update模式字段 [2025-12-01 17:32:15] - 已修改:ScriptableObject.cs (添加3个字段,Line 111-116) - 更改:添加_updateMode、_activeStartTime、_activeEndTime字段 - 原因:存储对象的Update模式和时间范围 - 阻碍因素:无 - 状态:未确认 ### 2.3 添加虚方法供子类重写 [2025-12-01 17:34:30] - 已修改:ScriptableObject.cs (添加2个虚方法,Line 175-183) - 更改:添加GetUpdateMode和GetActiveTimeRange虚方法 - 原因:允许子类自定义Update模式和时间范围 - 阻碍因素:无 - 状态:未确认 ### 2.4 实现IUpdateable接口方法 [2025-12-01 17:36:45] - 已修改:ScriptableObject.cs (添加新的partial class,约35行,Line 916-950) - 更改:实现IUpdateable的3个接口方法(ExecuteUpdate、GetUpdateName、IsUpdateReady) - 原因:提供扁平化Update入口,复用原有UpdateTicks逻辑 - 阻碍因素:无 - 状态:未确认 ### 2.4.1 重命名方法为FlatOptimizationUpdate(更具描述性) [2025-12-01 17:40:00] - 已修改:IUpdateable.cs、UpdateScheduler.cs、ScriptableObject.cs - 更改:将方法重命名为FlatOptimizationUpdate,明确表达"扁平化优化Update"的含义 - 原因:提高代码可读性,方法名清晰表达优化目的 - 阻碍因素:无 - 状态:未确认 ### 2.5 阶段2整体测试 [2025-12-01 17:38:00] - 已修改:阶段2所有代码完成,等待测试 - 更改:ScriptableObject完整实现IUpdateable接口(添加3个字段、2个虚方法、3个接口方法) - 原因:验证接口实现无破坏性影响 - 测试项目: 1. 编译项目 - ✅ 已通过(无linter错误) 2. 运行编辑器 - 待测试 3. 打开项目 - 待测试 4. 检查Inspector中新增字段是否可见 - 待测试 5. 验证游戏功能不受影响 - 待测试 - 阻碍因素:无 - 状态:未确认 → 等待用户确认:成功/不成功? # 最终审查 [待完成]