Nomad changes
All checks were successful
Deploy fil (kreuzberg) / deploy (push) Successful in 49s

This commit is contained in:
Henrik Jess Nielsen
2026-06-01 23:40:55 +02:00
parent 72b1a0a6ed
commit b4c07d3693
5723 changed files with 1130655 additions and 0 deletions

122
tools/perf/extract_top_symbols.py Executable file
View File

@@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""Extract top self-time symbols from a pprof flamegraph SVG.
Usage:
python3 tools/perf/extract_top_symbols.py flamegraphs/<sha>/baseline.svg [N=15]
Reports the top-N functions by aggregate sample count, filtered to drop
system / dependency frames so kreuzberg::* hotspots surface clearly.
The SVG is the standard pprof flamegraph output; each rectangle has a
`<title>fn (samples, percent%)</title>` element. We aggregate per-function
sample counts across all stack instances — that's an over-counting heuristic
(a function called from many places shows up larger than its true self-time),
but it's the right signal for "is this function on the hot path?"
"""
from __future__ import annotations
import re
import sys
from collections import Counter
from pathlib import Path
# Filter out stack frames that are dependencies, the runtime, or system noise.
# The remaining frames are kreuzberg's own code (or close enough to be actionable).
EXCLUDE_PREFIXES = (
"__", # __mh_execute_header, __os_lock_..., __pthread_...
"_", # _open$NOCANCEL, _os_cpu_..., _pthread_...
"onnx::", # ORT internals
"ort_sys::",
"tokio::",
"std::",
"core::",
"alloc::",
"_$LT$std",
"image::", # image crate
"pdf_oxide::", # pdf_oxide internals
"memchr::",
"regex::",
"serde::",
"tracing::",
"lopdf::",
"pprof::",
)
# Explicit numeric address frames (raw hex / decimal) — appear when symbols are stripped.
ADDRESS_PATTERN = re.compile(r"^\d+$|^0x[0-9a-f]+$")
def is_kreuzberg_or_application(symbol: str) -> bool:
"""Return True if the symbol is application-level (likely kreuzberg crate)."""
if not symbol:
return False
if ADDRESS_PATTERN.match(symbol):
return False
return not symbol.startswith(EXCLUDE_PREFIXES)
def short(symbol: str, max_len: int = 110) -> str:
"""Trim a long symbol name for display, abbreviating generic args."""
s = re.sub(r"<[^>]*>", "<>", symbol)
if len(s) > max_len:
s = "..." + s[-(max_len - 3) :]
return s
def main() -> int:
if len(sys.argv) < 2:
print(f"usage: {sys.argv[0]} <flamegraph.svg> [top_n=15]", file=sys.stderr)
return 2
svg_path = Path(sys.argv[1])
top_n = int(sys.argv[2]) if len(sys.argv) > 2 else 15
if not svg_path.is_file():
print(f"error: {svg_path} is not a file", file=sys.stderr)
return 2
content = svg_path.read_text()
pattern = re.compile(r"<title>([^<]+) \(([0-9,]+) samples, ([\d.]+)%\)</title>")
matches = pattern.findall(content)
if not matches:
print(f"warning: no <title> elements found in {svg_path}", file=sys.stderr)
return 1
samples_per_fn: Counter[str] = Counter()
for fn, samples, _pct in matches:
samples_per_fn[fn] += int(samples.replace(",", ""))
total_samples = sum(samples_per_fn.values()) or 1
# Application-level symbols, ranked by aggregate samples.
app_ranked = sorted(
((fn, s) for fn, s in samples_per_fn.items() if is_kreuzberg_or_application(fn)),
key=lambda x: -x[1],
)
if not app_ranked:
print(
"warning: no application-level symbols matched filters — "
"is the binary built with --profile profiling? a release-stripped "
"build only contains system frames.",
file=sys.stderr,
)
# Fall back to showing top frames regardless.
app_ranked = sorted(samples_per_fn.items(), key=lambda x: -x[1])
print(f"# Top {top_n} symbols by aggregate sample count from {svg_path.name}")
print(f"# (out of {len(samples_per_fn)} unique frames; total samples {total_samples})")
print()
print(f"{'rank':>4} {'samples':>8} {'%total':>7} symbol")
print("-" * 80)
for rank, (fn, samples) in enumerate(app_ranked[:top_n], start=1):
pct = 100.0 * samples / total_samples
print(f"{rank:>4} {samples:>8} {pct:>6.2f}% {short(fn)}")
return 0
if __name__ == "__main__":
raise SystemExit(main())