test(06-18): migrate 5 existing perf files to performance.mark/measure

- measureCase sampling loop now pairs mark(startTag)/mark(endTag) with
  measure(measureName, startTag, endTag) and clears marks/measures per sample
- tag names derive from caseName+scale so they never collide across cases
- WARMUP_RUNS/SAMPLE_RUNS/median/min/p95/toFixed(3)/columns unchanged
This commit is contained in:
unanmed 2026-09-16 20:26:42 +08:00
parent 0da0117cd4
commit 6c4d3709d3
5 changed files with 95 additions and 15 deletions

View File

@ -107,7 +107,9 @@ interface PerfRecord {
const records: PerfRecord[] = [];
/**
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95,
* 计时经 performance.mark / performance.measure 成对标记完成,
* 采样后按名清理标记与测量
* @param caseName 测量项名称
* @param scale 规模档位
* @param run 单次被测量的操作
@ -121,11 +123,25 @@ function measureCase(
run();
}
// 必须先打标记再测量:对不存在的标记做 measure 会抛错;
// 标记还必须逐样本清理,否则同名标记会被解析成首次位置而得到累计耗时
const startTag = 'perf:' + caseName + ':' + scale + ':start';
const endTag = 'perf:' + caseName + ':' + scale + ':end';
const measureName = 'perf:' + caseName + ':' + scale;
const samples: number[] = [];
for (let i = 0; i < SAMPLE_RUNS; i++) {
const start = globalThis.performance.now();
globalThis.performance.mark(startTag);
run();
samples.push(globalThis.performance.now() - start);
globalThis.performance.mark(endTag);
const measure = globalThis.performance.measure(
measureName,
startTag,
endTag
);
samples.push(measure.duration);
globalThis.performance.clearMarks(startTag);
globalThis.performance.clearMarks(endTag);
globalThis.performance.clearMeasures(measureName);
}
samples.sort((left, right) => left - right);

View File

@ -77,7 +77,9 @@ interface PerfRecord {
const records: PerfRecord[] = [];
/**
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95,
* 计时经 performance.mark / performance.measure 成对标记完成,
* 采样后按名清理标记与测量
* @param caseName 测量项名称
* @param scale 规模档位
* @param run 单次被测量的操作
@ -91,11 +93,25 @@ function measureCase(
run();
}
// 必须先打标记再测量:对不存在的标记做 measure 会抛错;
// 标记还必须逐样本清理,否则同名标记会被解析成首次位置而得到累计耗时
const startTag = 'perf:' + caseName + ':' + scale + ':start';
const endTag = 'perf:' + caseName + ':' + scale + ':end';
const measureName = 'perf:' + caseName + ':' + scale;
const samples: number[] = [];
for (let i = 0; i < SAMPLE_RUNS; i++) {
const start = globalThis.performance.now();
globalThis.performance.mark(startTag);
run();
samples.push(globalThis.performance.now() - start);
globalThis.performance.mark(endTag);
const measure = globalThis.performance.measure(
measureName,
startTag,
endTag
);
samples.push(measure.duration);
globalThis.performance.clearMarks(startTag);
globalThis.performance.clearMarks(endTag);
globalThis.performance.clearMeasures(measureName);
}
samples.sort((left, right) => left - right);

View File

@ -174,7 +174,9 @@ function clearCodes(flat: readonly number[]): number[] {
}
/**
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95,
* 计时经 performance.mark / performance.measure 成对标记完成,
* 采样后按名清理标记与测量
* @param caseName 测量项名称
* @param scale 规模档位
* @param run 单次被测量的操作
@ -188,11 +190,25 @@ function measureCase(
run();
}
// 必须先打标记再测量:对不存在的标记做 measure 会抛错;
// 标记还必须逐样本清理,否则同名标记会被解析成首次位置而得到累计耗时
const startTag = 'perf:' + caseName + ':' + scale + ':start';
const endTag = 'perf:' + caseName + ':' + scale + ':end';
const measureName = 'perf:' + caseName + ':' + scale;
const samples: number[] = [];
for (let i = 0; i < SAMPLE_RUNS; i++) {
const start = globalThis.performance.now();
globalThis.performance.mark(startTag);
run();
samples.push(globalThis.performance.now() - start);
globalThis.performance.mark(endTag);
const measure = globalThis.performance.measure(
measureName,
startTag,
endTag
);
samples.push(measure.duration);
globalThis.performance.clearMarks(startTag);
globalThis.performance.clearMarks(endTag);
globalThis.performance.clearMeasures(measureName);
}
samples.sort((left, right) => left - right);

View File

@ -106,7 +106,9 @@ interface PerfRecord {
const records: PerfRecord[] = [];
/**
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95,
* 计时经 performance.mark / performance.measure 成对标记完成,
* 采样后按名清理标记与测量
* @param caseName 测量项名称
* @param scale 规模档位
* @param run 单次被测量的操作
@ -120,11 +122,25 @@ function measureCase(
run();
}
// 必须先打标记再测量:对不存在的标记做 measure 会抛错;
// 标记还必须逐样本清理,否则同名标记会被解析成首次位置而得到累计耗时
const startTag = 'perf:' + caseName + ':' + scale + ':start';
const endTag = 'perf:' + caseName + ':' + scale + ':end';
const measureName = 'perf:' + caseName + ':' + scale;
const samples: number[] = [];
for (let i = 0; i < SAMPLE_RUNS; i++) {
const start = globalThis.performance.now();
globalThis.performance.mark(startTag);
run();
samples.push(globalThis.performance.now() - start);
globalThis.performance.mark(endTag);
const measure = globalThis.performance.measure(
measureName,
startTag,
endTag
);
samples.push(measure.duration);
globalThis.performance.clearMarks(startTag);
globalThis.performance.clearMarks(endTag);
globalThis.performance.clearMeasures(measureName);
}
samples.sort((left, right) => left - right);

View File

@ -103,7 +103,9 @@ interface PerfRecord {
const records: PerfRecord[] = [];
/**
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95
* 测量一次用例:先预热若干次,再采样后取中位数、最小值与 p95,
* 计时经 performance.mark / performance.measure 成对标记完成,
* 采样后按名清理标记与测量
* @param caseName 测量项名称
* @param scale 规模档位
* @param run 单次被测量的操作
@ -117,11 +119,25 @@ function measureCase(
run();
}
// 必须先打标记再测量:对不存在的标记做 measure 会抛错;
// 标记还必须逐样本清理,否则同名标记会被解析成首次位置而得到累计耗时
const startTag = 'perf:' + caseName + ':' + scale + ':start';
const endTag = 'perf:' + caseName + ':' + scale + ':end';
const measureName = 'perf:' + caseName + ':' + scale;
const samples: number[] = [];
for (let i = 0; i < SAMPLE_RUNS; i++) {
const start = globalThis.performance.now();
globalThis.performance.mark(startTag);
run();
samples.push(globalThis.performance.now() - start);
globalThis.performance.mark(endTag);
const measure = globalThis.performance.measure(
measureName,
startTag,
endTag
);
samples.push(measure.duration);
globalThis.performance.clearMarks(startTag);
globalThis.performance.clearMarks(endTag);
globalThis.performance.clearMeasures(measureName);
}
samples.sort((left, right) => left - right);