Migrating V8 cpu profiler from legacy phase 'P' to modern TrackEvent
- Dominant language
- C++
- Stars
- 6.5k
- Forks
- 868
- Avg merge
- 2d 1h
- Merged PRs (30d)
- 218
Description
## Context
V8 is migrating to modern events in https://issues.chromium.org/issues/498378089. The CPU profiler emits `Profile` and `ProfileChunk` events under the `disabled-by-default-v8.cpu_profiler` category, which currently use the legacy `TRACE_EVENT_SAMPLE_WITH_ID1` macro (phase `'P'`).
The modern [`TrackEvent.Type`](https://github.com/google/perfetto/blob/95454ef4fe980334e44eb723090c54c6d17c0cb2/protos/perfetto/trace/track_event/track_event.proto#L130-L162) has no `TYPE_SAMPLE`.
Current plan is to use `TRACE_EVENT_INSTANT` https://chromium-review.googlesource.com/c/v8/v8/+/7787230/5/src/profiler/profile-generator.cc since a sample event is structurally similar to instant event with a differentiating phase byte.
```
// Legacy (phase 'P'):
TrackEvent {
legacy_event {
phase: 'P'
unscoped_id: 42
}
debug_annotation { ... } ← JSON payload
}
// Modern (TYPE_INSTANT):
TrackEvent {
type: TYPE_INSTANT
name: "Profile"
debug_annotation { ← JSON payload (same format)
name: "data"
string_value: "{...\"id\":42...}" ← id is HERE (or in correlation_id)
}
}
```
## Current state in the Perfetto trace processor
### Tokenizer
The tokenizer special-cases V8 CPU samples at https://github.com/google/perfetto/blob/95454ef4fe980334e44eb723090c54c6d17c0cb2/src/trace_processor/importers/proto/track_event_tokenizer.cc#L465-L476 based on the phase type. This extracts the embedded V8 CPU profile data and feeds it to `V8Tracker`, which populates the `cpu_profile_stack_sample` table.
### Event importer
Phase `'P'` has no dedicated case in the phase switch https://github.com/google/perfetto/blob/95454ef4fe980334e44eb723090c54c6d17c0cb2/src/trace_processor/importers/proto/track_event_event_importer.h#L209-L244 — it defaults to storing the event in `chrome_raw_table` as an opaque blob.
## The problem
Using `TYPE_INSTANT` there's no way to distinguish a "regular" instant event from a CPU profile sample event at the proto level. The tokenizer must now match by **event name** (`"Profile"`, `"ProfileChunk"`) rather than by type. Similarly, DevTools must explicitly exclude these events from generic instant event handling, https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7800921.
1. Should `TYPE_INSTANT` be the recommended modern replacement for phase `'P'`?
The current approach works but requires name-based detection in the tokenizer and explicit exclusions in consumers. As part of this migration, I would need to special case tokenizer like
```cpp
if (event.type() == TYPE_INSTANT) {
if (name == "Profile" || name == "ProfileChunk") {
TokenizeModernSampleEvent(...);
}
}
```
Note: `TokenizeModernSampleEvent` will be using `TrackEvent::Decoder` instead of `LegacyEvent::Decoder` rest of the mechanics from the current tokenizer will remain the same.
2. Would a dedicated `TYPE_SAMPLE` be considered?
Adding `TYPE_SAMPLE` to the `TrackEvent.Type` enum would:
- Allow the tokenizer to continue to detect CPU profile events by type alone
- Eliminate the need for downstream consumers (DevTools) to special-case instant events by name
cc @camillobruni
Contributor guide
Research direction
Start with the V8 CPU sample handling in src/trace_processor/importers/proto/track_event_tokenizer.cc and the phase switch in track_event_event_importer.h, then review TrackEvent.Type in track_event.proto. Compare the legacy phase-P path with the proposed modern instant-event path and its DevTools exclusions. Done means the migration approach is agreed, including whether a dedicated sample type is needed and how consumers should identify these events.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- devtools, observability-sre
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100