主题
这页解释 /hnattr perf stats 输出的每个指标在看什么、通常对应哪段代码路径,以及出现高耗时时应该优先排查什么。
配套阅读:
1. 命令分层
1.1 summary
text
/hnattr perf stats summary适合先看“大头在哪”。
1.2 detail
text
/hnattr perf stats detail在 summary 基础上继续拆伤害后处理。
1.3 full
text
/hnattr perf stats full最细粒度,适合定位伤害核心内部到底是:
- 阶段匹配慢
channels慢effect慢- 还是脚本求值慢
2. 输出里的统计口径怎么看
每个指标都会显示:
次数平均P95最大总计
次数
这个指标被记录了多少次。适合判断样本量。
平均
总体平均耗时,适合看“常态成本”。
P95
最近样本里的 95 分位耗时,适合看抖动和尖峰。
最大
最近统计周期内的最大单次耗时,适合排查偶发尖峰。
总计
累计耗费总时间,适合判断是“单次慢”还是“调用太多”。
3. summary 层指标
3.1 装备刷新
表示一次装备属性刷新整体耗时。
通常包含:
- 读取玩家装备
- 物品解析
- 条件检查
- 聚合属性
- 比较是否变化
- 应用到玩家数据
如果这个值高,优先看:
- Lore / NBT 读取规则是不是太重
- 属性总数是不是太大
- 是否频繁触发无意义刷新
还要结合:
缓存命中缓存失效命中率属性变化刷新无变化刷新刷新队列战斗脏标记批次上限
3.2 物品解析
表示解析物品属性的耗时。
通常覆盖:
- Lore 扫描
- 正则匹配
- PDC/NBT 读取
- 文本到数值转换
如果它高,常见原因是:
- Lore 行太多
- 匹配规则太复杂
perf-bulk属性很多- 同时启用了较多 NBT 源
3.3 条件检查
表示配置里的条件系统耗时。
如果它高,常见原因是:
- 大量物品都带条件行
- 条件表达式过重
- 高频刷新时重复判断同样的条件
还要结合看:
条件缓存命中失效命中率
如果在 detail 里还能看到 条件缓存活跃玩家 和 TTL,那它们属于辅助状态,不是耗时指标本身,用来帮助判断当前缓存是否真的在工作。
3.4 伤害总耗时
表示一次完整伤害处理从前到后的总耗时。
它通常覆盖:
- 前置检查
- 属性快照获取
CombatPipeline核心阶段- 后处理(显示、吸血、反伤、战斗标记)
- 调试尾部
3.5 伤害核心耗时
表示 CombatPipeline.execute(...) 这一段的核心耗时。
如果它高,通常说明问题在:
- 阶段匹配太多
- 启用通道太多
channels阶段太重effect阶段太多- 脚本求值过多
3.6 Buff Tick
表示 Buff / 周期性效果调度的耗时。
如果这个值高,优先排查:
- 同时活跃的 Buff 数量
- 同时活跃的 DOT/HOT 实例数
- 周期动作频率是否过高
- 生命周期钩子是否过重
4. detail 层指标
4.1 伤害前置检查
表示真正进入伤害公式前的准备工作耗时。
4.2 属性快照获取
表示一次伤害中抓取攻击方/受击方属性快照的耗时。
4.3 后处理-伤害显示
表示伤害数字、全息、显示相关逻辑耗时。
4.4 后处理-吸血
表示吸血生效逻辑耗时。
4.5 后处理-反伤
表示反伤处理耗时。
4.6 后处理-战斗标记
表示进入/刷新战斗状态的逻辑耗时。
4.7 伤害调试尾部
表示调试输出和尾部处理耗时。
如果 debug 级别开得很高,这里通常会明显变高。
4.8 detail 层里的辅助运行态
在当前版本里,detail 视图还会附带几类辅助状态,它们不是耗时指标,而是帮助你判断系统是不是在堆积:
装备缓存玩家/已知签名条件缓存活跃玩家/TTLReload 状态(running/idle与queued)
这些字段更适合回答:
- 当前是不是大量玩家都进了装备缓存
- 条件缓存是不是几乎没命中
- 是否有重载还没消化完
5. full 层指标
先说明一下:
当前 perf 输出里有些指标名仍沿用历史命名。
读这部分时,更建议你把它理解成“对应哪一类运行阶段”,而不是再按旧配置字段去找文件。
5.1 核心-阶段匹配
表示每个 Stage 执行前,做前置判断和上下文准备的耗时。
你可以把它理解成:
- 这一跳会不会执行这个 Stage
- 这个 Stage 依赖的上游结果是否已经准备好
- 当前上下文是否满足这一步的运行条件
所以它高的时候,通常不是某条伤害公式本身慢,而是Stage 数量多、前置判断多、链路长。
5.2 核心-CHANNELS
这是一个历史指标名。放到当前版本里,可以把它理解成:
通道收集 + 按通道处理这整段的耗时。
通常会覆盖:
- 收集可用伤害通道
- 读取每个通道上的 damage / resist / penetration
- 执行
per_channel相关计算 - 构造多段伤害结果
5.3 核心-EFFECT
这也是历史指标名。放到当前版本里,更接近:
各种修正型 Stage 的总耗时。
例如你可以把它近似理解为这些阶段带来的成本:
- 增伤
- 减伤
- 暴击修正
- 斩杀修正
- 吸血
- 反伤
- 其他 modifier / value / boolean 组合逻辑
5.4 核心-scaleParts
表示对多段伤害结果做统一调整的耗时。
高的时候通常说明:
- 通道过多导致分段太多
- 多个修正型 Stage 都在反复处理同一批伤害分段
5.5 核心-脚本求值
表示所有脚本求值的总耗时。
它是下面这些细项的总和:
脚本-GENERAL脚本-条件脚本-HIT脚本-DODGE脚本-BLOCK-chance脚本-BLOCK-reduction脚本-CHANNELS脚本-EFFECT-hit脚本-EFFECT-formula
这些子项名字里虽然还保留历史命名,但阅读时可以按“命中判定 / 闪避判定 / 格挡判定 / 通道处理 / 修正阶段公式”来理解。
5.6 full 层里的运行时辅助状态
full 视图里当前还会带一组运行时持久化辅助状态:
运行时脏队列总计本地跨服Flush 中节流中最小间隔单批上限
这些字段同样不是“耗时值”,而是帮助你判断 runtime snapshot 持久化链路当前是不是在堆积:
本地:只需要落库,不额外做跨服广播跨服:落库后还需要广播runtime-snapshotFlush 中:当前已经选中并在落库流程里的玩家数节流中:因为最小 flush 间隔被暂时延后的玩家数单批上限:每轮主线程快照采集的最大人数
如果你怀疑 Buff / DOT / HOT 的离线恢复或跨服同步有积压,优先先看这组状态,再决定要不要继续盯数据库或消息总线。
6. 脚本细分指标
脚本-GENERAL
一般性脚本求值耗时。
脚本-条件
阶段 condition 的脚本耗时。
脚本-HIT
命中判定相关脚本耗时。
脚本-DODGE
闪避判定相关脚本耗时。
脚本-BLOCK-chance
格挡概率相关脚本耗时。
脚本-BLOCK-reduction
格挡减伤相关脚本耗时。
脚本-CHANNELS
通道处理相关脚本耗时。通常是最需要关注的脚本项之一。
脚本-EFFECT-hit
修正阶段里的触发判定脚本耗时。
脚本-EFFECT-formula
修正阶段里的实际数值公式耗时。
7. 常见观察结论
情况 A:伤害总耗时高,但伤害核心不高
说明慢点更可能在:
- 伤害显示
- 吸血/反伤
- 战斗标记
- 调试输出
情况 B:伤害核心高,但脚本求值不高
说明更可能是结构性成本高:
- 阶段太多
- 通道太多
DamagePart太多- 匹配/遍历太多
情况 C:脚本-CHANNELS 高
重点优化方向通常是:
- 减少启用通道
- 简化按通道处理的公式
- 能走更轻量路径的尽量别都压到脚本里
情况 D:核心-scaleParts 高
重点优化方向通常是:
- 减少多段伤害
- 减少对同一批伤害分段的重复缩放
- 减少层层修正后再整段重算
情况 E:装备刷新高,物品解析高
说明问题更像在“读装备”,不是在“打伤害”。
情况 F:Buff Tick 高
说明问题更像在“持续状态系统”,而不是瞬时伤害。
8. 推荐排查顺序
建议按这个顺序看:
summary看大头- 如果是伤害问题,再看
detail - 如果确认是核心结算,再看
full - 从
核心-CHANNELS / 核心-EFFECT / 核心-脚本求值三个方向继续细分
9. 一句话速记
装备刷新看读装备与聚合物品解析看 Lore/NBT 读取条件检查看条件系统伤害总耗时看整体伤害核心耗时看公式主干核心-CHANNELS看通道循环核心-EFFECT看效果层核心-scaleParts看多段伤害重缩放脚本-*看具体哪类公式最重Buff Tick看持续状态系统
