# SC-tracy **Repository Path**: RegulusSource/sc-tracy ## Basic Information - **Project Name**: SC-tracy - **Description**: Tracy 风格的 Survivalcraft API 性能诊断模组。通过帧时间、CPU 占用、GC 周期、子系统耗时等多维度诊断游戏性能瓶颈。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-02 - **Last Updated**: 2026-08-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # sc-tracy 性能诊断模组 Tracy 风格的 Survivalcraft API 性能诊断模组。通过帧时间、CPU 占用、GC 周期、子系统耗时等多维度诊断游戏性能瓶颈。 ## 功能特性 ### 数据采集 - **帧时间**:真实帧时长、CPU 帧时长、1 秒滚动平均(复用引擎 `Time` / `PerformanceManager`) - **GC 诊断**:Gen0/1/2 收集次数、托管堆内存、当前线程分配量、GC 暂停事件(`EventListener` 监听) - **子系统耗时**:复用引擎三个 `UpdateTimeDebug` 开关(`SubsystemUpdate` / `SubsystemDrawing` / `SubsystemElectricity`),按类型聚合 Update/Draw/ElectricElement 耗时 - **电路拓扑重建探针**:Harmony 注入 `SubsystemElectricity.Update` 和 `UpdateElectricElements`,补全引擎未覆盖的拓扑重建阶段计时 ### 可视化 - **V1 后备**:`PerformanceManager.AddExtraStat` 文本行(HUD 关闭时显示,依赖 `DisplayFpsCounter`) - **V2 数字面板**:`CanvasWidget` + `LabelWidget` 多行结构化数据(FPS / 帧时间 / CPU / GC / 内存 / 子系统 Top N 排行) - **V3 滚动曲线图**:`PrimitivesRenderer2D` 自绘帧时间柱状图(CPU=橙、Total-CPU=红)、60/30fps 参考线、GC 事件标记线(紫)、电路耗时曲线(蓝)。支持细粒度呈现控制: - **留存时间**(`GraphRetentionSeconds`):曲线图左右宽度对应的时间跨度,5/10/20/30/60 秒可选 - **线条粗细**(`GraphLineWidth`):1~6 像素,用 Quad 模拟粗线(引擎 QueueLine 仅支持 1px) - **轨道布局**(`GraphTrackLayout`):Overlay(多曲线叠加同区域)或 Stacked(每条曲线独立轨道,垂直拉开分别呈现) - **像素列聚合**:按屏幕像素列聚合帧数据(取列内最大值),避免高频帧数下柱子糊成一团 ### 交互 - **设置子页面**:在游戏原生设置页面注册"sc-tracy"入口按钮,点击进入独立的 sc-tracy 设置子页面(包含所有配置开关、分析启动、报告导出) - **60 秒自动分析**:点击"开始 60 秒分析"后弹出确认提示,进入游戏后自动采集 60 秒,结束后弹出瓶颈诊断报告 - **瓶颈诊断**:自动识别硬件瓶颈(CPU 单核不足/CPU 过载/内存不足频繁 GC/GPU 显存压力/GPU 渲染瓶颈)和软件瓶颈(子系统热点/分配压力/电路过重) - **热键**:通过 `GetKeyboardMappings` 注册到游戏原生热键系统,可在设置中改键 - **本地化**:支持中文(zh-CN)和英文(en-US),通过游戏 `LanguageControl` 自动加载 ### 报告导出 - **CSV**:帧历史序列、GC 事件序列、子系统耗时排行(3 个文件,可用 Excel/WPS 打开) - **JSON 快照**:当前性能数据的完整 JSON 快照 - **Chrome Tracing JSON**:帧时间线 + GC 事件,可用 [perfetto.dev](https://ui.perfetto.dev/) 或 `chrome://tracing` 打开分析 ## 安装 将 `sc-tracy.scmod` 文件放入游戏的 `Mods` 目录,启动游戏后在模组管理器中启用。 ## 配置 配置保存于游戏自身的 `ModSettings.xml` 的 `` 节点下。首次运行使用默认值,可通过设置界面按钮或手动编辑 XML 修改。 | 配置项 | 类型 | 默认值 | 说明 | |---|---|---|---| | `HUDVisibleByDefault` | bool | true | HUD 默认是否可见 | | `Mode` | int | 1 (Standard) | 显示模式:0=Minimal, 1=Standard, 2=Full | | `EnableUpdateTimeDebug` | bool | false | 进世界时是否自动开引擎三个 UpdateTimeDebug(有 5~15% 开销) | | `EnableElectricityTopologyProbe` | bool | true | 电路拓扑重建探针(开销 <1μs/帧) | | `EnableGCEventListener` | bool | true | GC EventListener 暂停事件监听 | | `GraphHistorySeconds` | int | 10 | 曲线图滚动窗口秒数 | | `StatsUpdateIntervalMs` | int | 100 | 数字面板刷新间隔(毫秒) | | `TopNSubsystems` | int | 10 | 子系统排行显示前 N 项 | | `AutoExportOnWorldExit` | bool | false | 退出世界时自动导出报告 | | `GraphRetentionSeconds` | int | 10 | 曲线图留存时间(左右宽度对应的时间跨度,秒) | | `GraphLineWidth` | int | 3 | 曲线图线条粗细(像素数,1~6) | | `GraphTrackLayout` | int | 1 (Stacked) | 曲线图轨道布局:0=Overlay 叠加,1=Stacked 分层 | | `GraphTrackGapPixels` | int | 8 | Stacked 模式下轨道间垂直留白(像素数) | ## 热键 默认绑定如下,可在游戏设置 > 按键映射中改键: | 热键名 | 默认键 | 功能 | |---|---|---| | `TracyToggleHUD` | F8 | 开关 HUD 显示 | | `TracyCycleMode` | F9 | 切换显示模式(Minimal → Standard → Full) | | `TracyToggleStats` | F7 | 开关引擎 UpdateTimeDebug 采集 | | `TracyResetStats` | F6 | 清空所有统计数据 | | `TracyDumpReport` | F10 | 手动导出报告(CSV + JSON + Chrome Trace) | ## 显示模式 | 模式 | 显示内容 | |---|---| | **Minimal** | FPS、帧时间、CPU 帧时间、GC 次数、内存 | | **Standard** | + 进程/GPU 内存、子系统耗时 Top N 排行 | | **Full** | + 分配量、电路耗时、GC 事件统计、滚动曲线图 | ## 设置子页面 游戏主菜单 > 设置 > sc-tracy 性能诊断(入口按钮)进入独立的设置子页面。 页面功能: - **开始 60 秒分析**:弹出确认提示,进入游戏后自动采集 60 秒,结束后弹出瓶颈诊断报告 - **HUD 开关**:切换游戏内 HUD 显示 - **显示模式**:切换 Minimal / Standard / Full - **统计开关**:切换引擎 UpdateTimeDebug 采集(5~15% 开销) - **自动导出**:开关退出世界时自动导出报告 - **清空统计**:清空所有采集数据 - **导出报告**:手动导出 CSV + JSON + Chrome Trace ## 60 秒自动分析 点击设置子页面的"开始 60 秒分析"按钮后: 1. 弹出确认对话框("将在进入游戏后自动采集 60 秒...") 2. 玩家进入/创建世界后,分析自动启动 3. 采集期间强制开启引擎 UpdateTimeDebug 以获取子系统耗时 4. 60 秒后自动停止并弹出分析报告对话框 5. 报告包含瓶颈诊断 + 详细数据 + Top 5 子系统排行 ### 瓶颈诊断规则 **硬件瓶颈**: | 瓶颈 | 触发条件 | |---|---| | CPU 单核性能不足 | 平均帧时间 >16.67ms(无法 60fps)且 CPU 占用 >80% | | CPU 整体过载 | CPU 占用 >90% 且帧率 <30fps | | 内存不足频繁 GC | 60 秒内 Gen2 回收 ≥3 次或 GC 暂停总时长 >100ms | | GPU 显存压力 | GPU 显存平均占用 >1500MB | | GPU 渲染瓶颈 | 帧时间 >20ms 但 CPU 占用 <50%(GPU 受限) | **软件瓶颈**: | 瓶颈 | 触发条件 | |---|---| | 子系统热点 | 某子系统每帧耗时占总帧时间 >25% | | 分配压力 | 主线程每秒分配 >500KB | | 电路系统繁重 | 电路每帧耗时 >3ms | ## 本地化 支持中文(zh-CN)和英文(en-US),通过游戏 `LanguageControl` 自动加载。语言文件位于 `Assets/Lang/`,游戏会自动扫描并加载,无需模组代码介入。Pericles 字体已包含中文字形。 ## 报告导出 导出文件保存于游戏可执行文件目录下的 `sc-tracy-exports/` 子目录: | 文件 | 格式 | 内容 | |---|---|---| | `sc-tracy-{tag}-frames.csv` | CSV | 帧时间序列(RealTime, FrameIndex, 帧时间, CPU, GC, 内存...) | | `sc-tracy-{tag}-gc.csv` | CSV | GC 事件序列(时间、类型、暂停时长) | | `sc-tracy-{tag}-subsystems.csv` | CSV | 子系统耗时排行(按总耗时降序) | | `sc-tracy-{tag}-snapshot.json` | JSON | 当前性能数据完整快照 | | `sc-tracy-{tag}-trace.json` | Chrome Tracing JSON | 帧时间线 + GC 事件,可用 perfetto.dev 打开 | `{tag}` 为导出场景标记:`manual`(热键导出)、`settings`(设置按钮导出)、`auto_exit`(退出世界自动导出)。 ## 技术架构 ``` sc-tracy/ ├── ScTracyLoader.cs # 模组主入口(Hook 注册、热键、设置入口按钮、生命周期) ├── ModConfig.cs # 配置类(XML 持久化) ├── Profiler/ │ ├── DataTypes.cs # FrameSample / GcEvent / SubsystemTimingInfo 数据结构 │ ├── ProfilerState.cs # 全局状态中心(帧历史、GC 事件、自动分析状态机) │ ├── UpdateTimeDebugBridge.cs # C2: 桥接引擎三个 UpdateTimeDebug │ └── GcEventListener.cs # C4: EventListener 监听 GC 暂停事件 ├── Patches/ │ └── ElectricityUpdatePatch.cs # C3: Harmony 注入电路拓扑重建探针 ├── Analysis/ │ ├── AutoCaptureAnalyzer.cs # 60 秒分析 + 瓶颈识别规则 │ └── AnalysisReportDialog.cs # 分析报告对话框 ├── Display/ │ ├── ExtraStatsProvider.cs # V1: AddExtraStat 后备显示 │ ├── HudWidget.cs # V2: CanvasWidget 数字面板 │ ├── GraphRenderer.cs # V3: PrimitivesRenderer2D 滚动曲线图 │ └── ScTracySettingsScreen.cs # 设置子页面 Screen ├── Export/ │ ├── CsvExporter.cs # P3: CSV 报告导出 │ ├── JsonSnapshotExporter.cs # P3: JSON 快照导出 │ └── ChromeTraceExporter.cs # P4: Chrome Tracing JSON 导出 └── Assets/ ├── Lang/ │ ├── en-US.json # 英文语言文件 │ └── zh-CN.json # 中文语言文件 └── Screens/ └── ScTracySettings.xml # 设置子页面 XML 布局 ``` ### 数据流 ``` 每帧: Time.BeforeFrame() [引擎] 更新帧时间 → SubsystemElectricity.Update() [引擎] 电路模拟 ↳ ElectricityUpdatePatch (Prefix+Postfix) [sc-tracy] 测拓扑重建耗时 → SubsystemUpdate Hook [sc-tracy] SampleFrame() 采集 + ExtraStatsProvider → GuiUpdate Hook [sc-tracy] 挂载 HUD Widget + 热键检测 → PerformanceManager.Draw() [引擎] 绘制 FPS 计数器/Ribbon ↳ GraphRenderer (Postfix) [sc-tracy] 绘制滚动曲线图 → Time.AfterFrame() [引擎] 更新 CpuFrameDuration ``` ### 采集层方案 | 层 | 方案 | 实现 | |---|---|---| | C1 | 复用引擎 PerformanceManager | 直接读 `Time` / `Program` / `PerformanceManager` 公开字段 | | C2 | 复用引擎 UpdateTimeDebug ×3 | 开关 `SubsystemUpdate/Drawing/Electricity.UpdateTimeDebug`,读 `m_debugInfos` | | C3 | 电路拓扑重建探针 | Harmony Prefix+Postfix 注入 `UpdateElectricElements`(补全引擎盲区) | | C4 | GC EventListener | 派生 `EventListener` 监听 `GCSuspendEEStart`/`GCRestartEEStop` | ## 注意事项 - HUD 文本使用 `LabelWidget`(BitmapFont),**不含中文**,全部用英文/ASCII 显示 - `UpdateTimeDebug` 开启后有 5~15% 帧开销(复杂场景/电路),建议仅在定位瓶颈时开启(F7) - GC `EventListener` 跨平台可用(基于 EventPipe,非 ETW 专属) - 导出目录为游戏可执行文件目录下的 `sc-tracy-exports/`