- perf/run-all.sh: масштабы 1 и 2, шаги reset -> gen -> verify -> stand -> preflight -> scroll -> coauthor -> grow -> modals -> modals_profiling -> memory -> memtrend -> [control4x] -> bench -> aggregate; лог и run-all.status.json, возобновление (PERF_STEPS, PERF_SKIP_RESET), сухой режим с оценкой длительности, PERF_S2_REPEATS/PERF_S2_TARGETS, контроль CPU 4x (PERF_CONTROL_TARGETS). - Основная метрика: main_thread_ms и main_thread_ms_per_step в скролле (CDP TaskDuration), frame_excess_ms; в summary.md первыми строками. - SQL-статистика по шагам: PERF_SQLSTATS_TAG -> sql/<шаг>/ (sqlstats --out). - netlog: тела /auth/ не пишутся, поля password/token/secret вырезаются. - scroll.spec: уникальные имена целей (лист ССП с суффиксом /ssp, год в отчёте проекта) - иначе Playwright не запускал файл из-за дублей. - PERF_TRACE=0 для прогонов с одним повтором. - README: scroll-coauthor, run-all, возобновление, без CPU 4/6 в матрицах. - design.md: уточнена формулировка R-2, решения Task 10a. Refs #202 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.1 KiB
Python
71 lines
3.1 KiB
Python
import json
|
|
from perfkit import results
|
|
from perfkit.aggregate import summarize, render_md
|
|
|
|
|
|
def rec(**kw):
|
|
r = {"run_id": "r1", "scenario": "s", "target": "t", "role": "admin", "scale": 1,
|
|
"cpu_rate": 1, "repeat": 0, "metrics": {}, "artifacts": [], "incomplete": False, "ts": "x"}
|
|
r.update(kw)
|
|
return r
|
|
|
|
|
|
def test_summarize_median_p95(tmp_path):
|
|
for v in [10, 20, 30, 40, 100]:
|
|
results.append(tmp_path, rec(metrics={"long_task_ms": v}))
|
|
g = summarize(tmp_path)["groups"][0]
|
|
m = g["metrics"]["long_task_ms"]
|
|
assert (m["median"], m["p95"], m["n"], m["min"], m["max"]) == (30, 100, 5, 10, 100)
|
|
|
|
|
|
def test_summarize_groups_by_cpu_rate(tmp_path):
|
|
results.append(tmp_path, rec(cpu_rate=1, metrics={"a": 1}))
|
|
results.append(tmp_path, rec(cpu_rate=6, metrics={"a": 2}))
|
|
assert len(summarize(tmp_path)["groups"]) == 2
|
|
|
|
|
|
def test_incomplete_records_counted_separately(tmp_path):
|
|
results.append(tmp_path, rec(metrics={"a": 1}))
|
|
results.append(tmp_path, rec(metrics={"a": 999}, incomplete=True))
|
|
g = summarize(tmp_path)["groups"][0]
|
|
assert g["incomplete_n"] == 1
|
|
assert g["metrics"]["a"]["max"] == 1 and g["metrics"]["a"]["n"] == 1
|
|
|
|
|
|
def test_append_path_and_md(tmp_path):
|
|
results.append(tmp_path, rec(metrics={"a": 1.5, "flag": True, "s": "x"}))
|
|
assert (tmp_path / "s.jsonl").exists()
|
|
s = summarize(tmp_path)
|
|
assert "flag" not in s["groups"][0]["metrics"]
|
|
md = render_md(s)
|
|
assert "| a |" in md and "median" in md
|
|
|
|
|
|
def test_traced_records_excluded_and_metric_hidden(tmp_path):
|
|
results.append(tmp_path, rec(repeat=0, metrics={"long_task_ms": 999, "traced": 1}))
|
|
results.append(tmp_path, rec(repeat=1, metrics={"long_task_ms": 10, "traced": 0}))
|
|
results.append(tmp_path, rec(repeat=2, metrics={"long_task_ms": 20, "traced": 0}))
|
|
g = summarize(tmp_path)["groups"][0]
|
|
assert "traced" not in g["metrics"]
|
|
assert g["n"] == 2 and g["traced_n"] == 1
|
|
assert g["metrics"]["long_task_ms"]["max"] == 20
|
|
assert "| traced |" not in render_md(summarize(tmp_path))
|
|
|
|
|
|
def test_read_all_ignores_network_log(tmp_path):
|
|
results.append(tmp_path, rec(metrics={"a": 1}))
|
|
(tmp_path / "network.jsonl").write_text(json.dumps({"method": "GET", "url": "http://x/api/v1/y"}) + "\n", encoding="utf-8")
|
|
assert len(summarize(tmp_path)["groups"]) == 1
|
|
|
|
|
|
def test_main_thread_metrics_in_md_first(tmp_path):
|
|
"""Основная метрика (решение человека): main_thread_ms_per_step / main_thread_ms - первыми строками таблицы группы."""
|
|
for v in (100.0, 200.0, 300.0):
|
|
results.append(tmp_path, rec(scenario="scroll", metrics={
|
|
"frame_n": 10, "long_task_ms": v, "main_thread_ms": v * 2, "main_thread_ms_per_step": v / 50, "steps": 50}))
|
|
md = render_md(summarize(tmp_path))
|
|
rows = [l.split("|")[1].strip() for l in md.splitlines() if l.startswith("| ") and not l.startswith("| metric")]
|
|
assert rows[:2] == ["main_thread_ms_per_step", "main_thread_ms"]
|
|
assert "| main_thread_ms_per_step | 4 | 6 | 2 | 6 | 3 |" in md
|
|
assert set(rows[2:]) == {"frame_n", "long_task_ms", "steps"}
|