DFiP_Budget_planing/perf/tests/test_analysis.py
Andrey Epifancev 8e9f53a478 perf: скрипты разбора и сводные данные прогонов 20261026
- perf/analysis: разбор trace (timeline_breakdown), CPU-профилей с source maps
  (cpuprofile_top), heap snapshots (heapdiff), циклов памяти, сравнения масштабов,
  ручной EXPLAIN вложенных запросов (explain_manual), API против X-DB-Time-Ms
  (api_split), сводка горячих точек; тесты ядра в perf/tests/test_analysis.py
- perf/e2e/scenarios/hotspots.spec.ts: CPU-профиль, рендеры React, мутации DOM
  после фильтра, рост CSS-правил по циклам (вне run-all)
- prod-сборка с source maps: PERF_SOURCEMAP=1, perf/stand.sh web-sourcemap (:8082)
- perf/report-data/20261026-s1, 20261026-s2 (summary, sql, analysis, explain-manual),
  t5-types (иллюстрация CPU 6x)
- design.md: решения T10b без обсуждения

Refs #202

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 12:43:46 +04:00

44 lines
1.8 KiB
Python

"""Самопроверка ядра скриптов perf/analysis (без стенда)."""
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "analysis"))
import cpuprofile_top # noqa: E402
import timeline_breakdown # noqa: E402
def test_self_times_nested_and_category_inheritance():
evs = [
{"name": "RunTask", "ts": 0, "dur": 100},
{"name": "FunctionCall", "ts": 10, "dur": 50},
{"name": "V8.Unknown", "ts": 20, "dur": 10}, # наследует scripting
{"name": "Layout", "ts": 70, "dur": 20},
]
st = {e["name"]: (s, c) for e, s, c in timeline_breakdown.self_times(evs)}
assert st["RunTask"] == (30.0, "other")
assert st["FunctionCall"] == (40.0, "scripting")
assert st["V8.Unknown"] == (10.0, "scripting")
assert st["Layout"] == (20.0, "rendering")
def test_vlq_decode():
assert cpuprofile_top.vlq_decode("AAAA") == [0, 0, 0, 0]
assert cpuprofile_top.vlq_decode("CAAC") == [1, 0, 0, 1]
assert cpuprofile_top.vlq_decode("D") == [-1]
assert cpuprofile_top.vlq_decode("gB") == [16]
def test_sourcemap_lookup(tmp_path):
# строка 0: col 0 -> a.js:1:0, col 5 -> a.js:3:2; строка 1: col 0 -> b.js:1:0
m = {"version": 3, "sources": ["../../../../../web/src/a.js", "../../../../../web/node_modules/x/b.js"],
"names": [], "mappings": "AAAA,KAEE;ACFF"}
p = tmp_path / "t.js.map"
p.write_text(json.dumps(m))
sm = cpuprofile_top.SourceMap(p)
assert sm.lookup(0, 3)[:2] == ("web/src/a.js", 1)
assert sm.lookup(0, 9)[:2] == ("web/src/a.js", 3)
assert sm.lookup(1, 0)[0] == "web/node_modules/x/b.js"
assert cpuprofile_top.package_of("web/node_modules/@emotion/hash/dist/x.js") == "node_modules/@emotion/hash"