test(06-18): add whole-map critical timing and total/avg summary table

Adds a third metric that calls the real calculateCritical for every monster on
the merged map and fully consumes the generator, plus a second console.table
with monsters / total ms (sampled median of one full-map sweep) / avg ms.
avg ms equals total ms divided by the monster count.
This commit is contained in:
unanmed 2026-09-16 20:39:45 +08:00
parent c193c4e9a9
commit 5317b2f1e3

View File

@ -12,7 +12,7 @@ import {
type IReadonlyHeroAttribute,
type ISpecial
} from '@user/data-base';
import { type IMapDamage } from '@user/data-system';
import { type IDamageSystem, type IMapDamage } from '@user/data-system';
import { CoreState, createCoreState } from '../src/core';
import { type IHaloValue, type IZoneValue } from '../src/enemy/special';
import floorDataset from './fixtures/floors.json';
@ -292,12 +292,31 @@ interface PerfRecord {
/** 本次运行累积的性能记录,由 afterAll 统一打印 */
const records: PerfRecord[] = [];
/** 全图临界计算的汇总记录,总量与单怪均值分开成列 */
interface CriticalRecord {
/** 测量项名称 */
readonly case: string;
/** 规模档位 */
readonly scale: string;
/** 该规模的全图怪物数量 */
readonly monsters: number;
/** 全图扫一遍的采样中位耗时,单位毫秒 */
readonly 'total ms': number;
/** 单怪平均耗时,等于总量除以怪物数,单位毫秒 */
readonly 'avg ms': number;
}
/** 全图临界计算的汇总记录,由 afterAll 在第二张表打印 */
const criticalRecords: CriticalRecord[] = [];
/** 一次测量所需的完整场景,管理器在工厂里解析一次以免样本内做属性查找 */
interface IScenarioFixture {
/** 顶层数据端状态 */
readonly state: CoreState;
/** 当前绑定的地图伤害管理器 */
readonly mapDamage: IMapDamage<IEnemyAttr, IHeroAttr>;
/** 当前绑定的伤害系统 */
readonly damageSystem: IDamageSystem<IEnemyAttr, IHeroAttr>;
/** 合并地图宽度 */
readonly width: number;
/** 合并地图高度 */
@ -593,11 +612,21 @@ function createScenarioFixture(mapCount: number): IScenarioFixture {
state.enemyContext.buildup();
const hero = state.enemyContext.getBindedHero()!;
const mapDamage = state.enemyContext.getMapDamage()!;
return { state, mapDamage, width, height, monsterCount, hero };
const damageSystem = state.enemyContext.getDamageSystem()!;
return {
state,
mapDamage,
damageSystem,
width,
height,
monsterCount,
hero
};
}
afterAll(() => {
console.table(records);
console.table(criticalRecords);
});
describe('真实大地图战斗场景性能', () => {
@ -628,5 +657,33 @@ describe('真实大地图战斗场景性能', () => {
}
});
});
// 覆盖前 N 张真实地图合并后,对全图每只怪各一次完整临界计算
it(`measures critical over ${mapCount} merged maps`, () => {
const fixture = createScenarioFixture(mapCount);
const label = String(mapCount) + '/' + String(fixture.monsterCount);
const record = measureCase('全图怪物单次临界计算', label, () => {
for (const entry of fixture.state.enemyContext.iterateEnemy()) {
const view = entry[1];
for (const _critical of fixture.damageSystem.calculateCritical(
view,
'atk'
)) {
// 必须完整消费生成器,否则测不到临界二分枚举的真实开销
}
}
});
// 同规模内怪物数是常量,故「中位总量 / 怪物数」即单怪平均耗时的中位数
criticalRecords.push({
case: '全图怪物单次临界计算',
scale: label,
monsters: fixture.monsterCount,
'total ms': record['median ms'],
'avg ms': Number(
(record['median ms'] / fixture.monsterCount).toFixed(3)
)
});
});
}
});