profiler
stableA stateful code profiler that times named sections with nanosecond precision, recording call counts, totals, averages, and memory snapshots.
use plugin profiler::{Profiler, begin_section, end_section, …} Functions (15)
- Profiler Creates a new profiler instance.
- begin_section Start timing a named section
- end_section Stop timing a section, return elapsed ns
- report Get timing stats for all sections
- reset Clear all recorded timings
- active_sections List currently active section names
- section_count Count of distinct recorded sections
- section_stats Get stats for a single named section
- elapsed_ns Nanoseconds elapsed in an active section
- push_section Begin a nested (hierarchical) section
- pop_section End innermost nested section
- record_memory Record a manual memory snapshot
- memory_report Get all recorded memory snapshots
- format_report Format a report table as text
- format_flamegraph_lines Format report as folded stack lines
Overview
profiler is a stateful, in-process code profiler built around a single handle
object. You create one with Profiler(), then bracket the code you care about
with begin_section / end_section pairs (or the stack-based
push_section / pop_section for nested call trees). Every measurement is
stored with nanosecond precision, so calling the same section repeatedly
accumulates call counts, totals, averages, and min/max — exactly what you need
to find a hot path across many iterations.
The mental model is: one profiler handle holds all your sections. Timings are
recorded internally as you end sections; report and section_stats read those
aggregates back as plain tables, memory_report reads manual memory snapshots,
and the standalone format_report / format_flamegraph_lines helpers turn a
report table into printable text or folded-stack lines for flamegraph tooling.
Reach for it whenever you want lightweight, dependency-free timing without
wiring up an external profiler.
Common patterns
Time a block, run it many times, then print the aggregated table:
use plugin profiler::{Profiler, format_report}
let p = Profiler()
for i in 0..1000 {
p.begin_section("hash")
// ... work to measure ...
p.end_section("hash")
}
print(format_report(p.report()))
Build a nested call tree with the section stack and export it for a flamegraph:
use plugin profiler::{Profiler, format_flamegraph_lines}
let p = Profiler()
p.push_section("frame")
p.push_section("physics")
p.pop_section()
p.push_section("render")
p.pop_section()
p.pop_section()
print(format_flamegraph_lines(p.report()))
Pair timing with manual memory snapshots to see cost and growth side by side:
use plugin profiler::{Profiler}
let p = Profiler()
p.begin_section("load")
p.record_memory("before", 1048576)
// ... load work ...
p.record_memory("after", 4194304)
p.end_section("load")
for _, snap in p.memory_report() {
print("{snap["label"]}: {snap["bytes"]} bytes")
}
Creates a new profiler instance.
Creates a new profiler instance. Use begin_section / end_section pairs to measure code.
use plugin profiler::{Profiler, format_report}
let p = Profiler()
p.begin_section("load")
// ... work ...
p.end_section("load")
let report = p.report()
print(format_report(report))
Start timing a named section
Starts a timer for a named section. Multiple sections can be active simultaneously.
p.begin_section("parse")
p.begin_section("validate")
Stop timing a section, return elapsed ns
Stops the timer for the named section and returns #{elapsed_ns: int}. The elapsed time is also stored internally.
let result = p.end_section("parse")
print("parse took {result["elapsed_ns"]} ns")
Calling the same section name repeatedly accumulates separate samples, so the
average and call count grow with each begin_section / end_section pair:
use plugin profiler::{Profiler}
let p = Profiler()
for i in 0..3 {
p.begin_section("step")
p.end_section("step")
}
print("recorded {p.section_count()} distinct section")
Get timing stats for all sections
Returns a table of timing entries, one per recorded section, sorted alphabetically. Each entry has name, calls, total_ns, avg_ns, min_ns, max_ns.
let r = p.report()
for _, entry in r {
print("{entry["name"]}: avg {entry["avg_ns"]} ns over {entry["calls"]} calls")
}
The report table feeds directly into either text formatter — pass it to
format_report for an aligned table or to format_flamegraph_lines for folded
stacks:
use plugin profiler::{Profiler, format_report}
let p = Profiler()
p.begin_section("a")
p.end_section("a")
p.begin_section("b")
p.end_section("b")
print(format_report(p.report()))
Clear all recorded timings
Clears all section timings and active timers. Useful for resetting between benchmark iterations.
p.reset()
List currently active section names
Returns a sorted list of section names that are currently being timed (started but not yet ended).
let active = p.active_sections()
print("still timing: {active[1]}")
Count of distinct recorded sections
Returns the number of distinct sections that have been recorded (ended at least once).
print("measured {p.section_count()} sections")
Get stats for a single named section
Returns timing stats for a single named section: name, calls, total_ns, avg_ns, min_ns, max_ns. Errors if the section has never been recorded.
let stats = p.section_stats("render")
print("render avg: {stats["avg_ns"]} ns")
Use it to inspect the spread of a single hot section without rendering the whole report:
use plugin profiler::{Profiler}
let p = Profiler()
for i in 0..5 {
p.begin_section("query")
p.end_section("query")
}
let s = p.section_stats("query")
print("query: {s["calls"]} calls, min {s["min_ns"]} / max {s["max_ns"]} ns")
Nanoseconds elapsed in an active section
Returns the nanoseconds elapsed so far for an active (not yet ended) section. Useful for progress logging inside long operations.
p.begin_section("import")
// ... some work ...
print("so far: {p.elapsed_ns("import")} ns")
p.end_section("import")
Begin a nested (hierarchical) section
Begins a nested section. The full name becomes parent/child, building a hierarchical call tree compatible with flamegraph tools.
p.push_section("frame")
p.push_section("physics")
// ... physics work ...
p.pop_section()
p.pop_section()
End innermost nested section
Ends the innermost pushed section and returns #{name: string, elapsed_ns: int}.
let r = p.pop_section()
print("finished {r["name"]} in {r["elapsed_ns"]} ns")
Record a manual memory snapshot
Records a manual memory measurement snapshot with a text label and a byte count.
p.record_memory("after_load", 1048576)
p.record_memory("after_parse", 2097152)
Get all recorded memory snapshots
Returns all memory snapshots in insertion order. Each entry has label and bytes.
let mem = p.memory_report()
for _, snap in mem {
print("{snap["label"]}: {snap["bytes"]} bytes")
}
Format a report table as text
Formats a report table (from report()) as an aligned text table with columns: Section, Calls, Total(ns), Avg(ns), Min(ns), Max(ns).
use plugin profiler::{Profiler, format_report}
let p = Profiler()
p.begin_section("work")
p.end_section("work")
print(format_report(p.report()))
Format report as folded stack lines
Converts a report table into folded stack format (name total_ns), one line per section. Feed the output to inferno or similar tools.
use plugin profiler::{Profiler, format_flamegraph_lines}
let p = Profiler()
p.push_section("app")
p.push_section("db")
p.pop_section()
p.pop_section()
let lines = format_flamegraph_lines(p.report())
print(lines)