first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
# flamegraph
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`FlameGraphGenerator` builds a flame-graph data structure from `ProfileEntry` arrays by nesting entries on start/end-time containment. The output is a `FlameNode` tree compatible with `d3-flame-graph` and similar visualisers; SVG/HTML rendering is intentionally out of scope (a downstream concern), but `toD3Format` produces the exact JSON shape these libraries expect.
## Features
- Pure containment algorithm: an entry whose `[startTime, endTime]` interval is fully inside another's becomes a child of it.
- Tie-breaking on equal start times: wider spans first so they own the narrower children.
- Self-time computation: `selfTime = value - sum(children.value)`, never negative.
- `collapseRecursive(node)` merges consecutive same-name parent/child pairs, useful for cleaning up tail-recursive call patterns before rendering.
- `toD3Format(node)` strips internal fields (`selfTime`, `startTime`, `endTime`) so the JSON is exactly `{ name, value, children }`.
## Usage: Basic
```ts
import { FlameGraphGenerator } from "@suaveplan/profiler";
const gen = new FlameGraphGenerator();
const tree = gen.generate(profiler.getEntries());
const d3Json = gen.toD3Format(tree);
```
## Usage: Advanced
```ts
import { FlameGraphGenerator } from "@suaveplan/profiler";
const gen = new FlameGraphGenerator();
const rawTree = gen.generate(entries);
const collapsed = gen.collapseRecursive(rawTree);
// rawTree shows the full recursion stack; collapsed flattens
// `parser → parser → parser → leaf` into `parser → leaf`.
const json = gen.toD3Format(collapsed);
await writeFile("flame.json", JSON.stringify(json));
```
## API Reference
- `class FlameGraphGenerator` — no constructor args (stateless).
- Methods:
- `generate(entries: readonly ProfileEntry[]): FlameNode`
- `toD3Format(node: FlameNode): { name, value, children }`
- `collapseRecursive(node: FlameNode): FlameNode`
## Implementation Notes
The internal `MutableFlameNode` carries `startTime`/`endTime` for the duration of tree construction so containment checks remain O(1) per node-pair; the final `freeze` step drops these fields and returns the immutable `FlameNode` shape. When a new entry is inserted, the algorithm first checks for a containing existing child (recursing into it) and otherwise creates a new node, absorbing any existing siblings the new entry contains. This handles arbitrary insertion order — the input is sorted by start-time ascending, ties broken by wider span first, before insertion starts.