Skip to content

feat: --cpu-prof flags for CPU profiles#31909

Merged
littledivy merged 9 commits intodenoland:mainfrom
littledivy:cpu-prof
Mar 9, 2026
Merged

feat: --cpu-prof flags for CPU profiles#31909
littledivy merged 9 commits intodenoland:mainfrom
littledivy:cpu-prof

Conversation

@littledivy
Copy link
Copy Markdown
Member

This PR adds --cpu-prof, --cpu-prof-dir, --cpu-prof-md, --cpu-prof-name and --cpu-prof-interval

Example usage:

> target/debug/deno -A --cpu-prof --cpu-prof-md getrandom.js
> cat CPU.1769017882255.25986.md

# CPU Profile

| Duration | Samples | Interval | Functions |
| --- | --- | --- | --- |
| 833.06ms | 641 | 1000us | 10 |

**Top 10:** `op_crypto_get_random_values` 98.5%, `(garbage collector)` 0.7%, `getRandomValues` 0.6%, `assertBranded` 0.2%

## Hot Functions (Self Time)

| Self% | Self | Total% | Total | Function | Location |
| ---: | ---: | ---: | ---: | --- | --- |
| 98.5% | 533.00ms | 98.5% | 533.00ms | `op_crypto_get_random_values` | [native code] |
| 0.7% | 4.00ms | 0.7% | 4.00ms | `(garbage collector)` | [native code] |
| 0.6% | 3.00ms | 0.6% | 3.00ms | `getRandomValues` | 00_crypto.js:5274 |
| 0.2% | 1.00ms | 0.2% | 1.00ms | `assertBranded` | 00_webidl.js:1149 |

## Call Tree (Total Time)

| Total% | Total | Self% | Self | Function | Location |
| ---: | ---: | ---: | ---: | --- | --- |
| 16.8% | 91.00ms | 16.8% | 91.00ms | `(anonymous)` | server.js:1 |
| 0.6% | 3.00ms | 0.6% | 3.00ms |   `getRandomValues` | 00_crypto.js:5274 |
| 98.5% | 533.00ms | 98.5% | 533.00ms |     `op_crypto_get_random_values` | [native code] |
| 0.7% | 4.00ms | 0.7% | 4.00ms | `(garbage collector)` | [native code] |
| 0.0% | 0.00ms | 0.0% | 0.00ms | `dispatchLoadEvent` | 99_main.js:461 |
| 0.0% | 0.00ms | 0.0% | 0.00ms |   `dispatchEvent` | 02_event.js:1035 |
| 0.0% | 0.00ms | 0.0% | 0.00ms |     `assertBranded` | 00_webidl.js:1149 |

## Function Details

### `op_crypto_get_random_values`
[native code] | Self: 98.5% (533.00ms) | Total: 98.5% (533.00ms) | Samples: 533

### `(garbage collector)`
[native code] | Self: 0.7% (4.00ms) | Total: 0.7% (4.00ms) | Samples: 4

### `getRandomValues`
00_crypto.js:5274 | Self: 0.6% (3.00ms) | Total: 0.6% (3.00ms) | Samples: 3

### `assertBranded`
00_webidl.js:1149 | Self: 0.2% (1.00ms) | Total: 0.2% (1.00ms) | Samples: 1

Copy link
Copy Markdown
Contributor

@kajukitli kajukitli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm — nice feature addition for CPU profiling

the implementation is clean:

  • flags are well-structured with sensible defaults
  • CpuProfilerState uses inspector session to control V8's profiler
  • markdown report generation is a nice touch for quick analysis

the test coverage looks good with specs for basic usage, custom names, and md output

one minor thing: the --cpu-prof-interval default of 1000µs (1ms) is reasonable, but might want to document that higher values = less overhead but coarser resolution

kajukitli added a commit to kajukitli/docs that referenced this pull request Mar 8, 2026
Documents the new --cpu-prof flags added in denoland/deno#31909:
- --cpu-prof: Enable CPU profiling
- --cpu-prof-dir: Output directory
- --cpu-prof-name: Custom filename
- --cpu-prof-interval: Sampling interval
- --cpu-prof-md: Generate Markdown report

Includes example of the Markdown report output format.
bartlomieju and others added 3 commits March 8, 2026 16:45
… eval support

Move the 5 cpu-prof fields from RunFlags to a single CpuProfFlags struct
on the top-level Flags, making it easy to add cpu-prof to more subcommands.
Add --cpu-prof support to `deno eval` with a spec test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove duplicate CpuProfConfig struct from cli/worker.rs, use
  CpuProfilerConfig from runtime everywhere
- Change cpu_prof_interval type from i32 to u32 (sampling interval
  can't be negative)
- Remove misleading Total columns from markdown report (they were
  identical to Self columns without proper descendant walking)
- Extract shared cpu_prof_filename() helper, eliminating duplicated
  timestamp/PID generation and unwrap() on SystemTime
- Always append worker ID to filename for web workers, even with
  custom --cpu-prof-name, preventing file overwrites
- Keep last two path segments in format_location() for better context
- Add --cpu-prof flags to deno serve subcommand
- Document that --cpu-prof-dir implicitly enables profiling
- Add explanatory comments for clippy allow and profile_msg_id race

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's ship it

@littledivy littledivy merged commit 22258fb into denoland:main Mar 9, 2026
112 checks passed
bartlomieju added a commit that referenced this pull request Mar 14, 2026
…hs (#32572)

## Summary

Builds on top of #31909 to add interactive SVG flamegraph generation for
CPU profiles, plus improvements to the existing `--cpu-prof`
functionality.

### New: `--cpu-prof-flamegraph` flag

Generates a self-contained, interactive SVG flamegraph alongside the
`.cpuprofile` file. No external dependencies required — the SVG is
generated directly from V8 CPU profile data.

```bash
deno run --cpu-prof --cpu-prof-flamegraph script.ts
# or
deno eval --cpu-prof --cpu-prof-flamegraph "/* code */"
```

**Flamegraph features:**
- Click any frame to zoom into that subtree
- "Reset Zoom" button to restore full view
- Ctrl+F / "Search" button for regex-based function search with magenta
highlighting and matched percentage
- "Invert" checkbox to flip into an icicle graph (root at top)
- Hover any frame to see function name and sample count in the status
bar
- Responsive — fills the browser viewport, adapts on resize
- Warm color gradient matching `cargo-flamegraph` / inferno style

### Other improvements
- **`deno eval` support**: All `--cpu-prof-*` flags now work with `deno
eval`
- **Fixed total time calculation**: The markdown report now properly
computes inclusive time (self + all descendants) using bottom-up tree
aggregation, instead of showing only self time

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants