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 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
|
// Handle legacy sample events which might have timestamps embedded inside. |
|
if (PERFETTO_UNLIKELY(event.has_legacy_event())) { |
|
protos::pbzero::TrackEvent::LegacyEvent::Decoder leg(event.legacy_event()); |
|
if (PERFETTO_UNLIKELY(leg.phase() == 'P')) { |
|
base::Status status = TokenizeLegacySampleEvent( |
|
event, leg, *data.trace_packet_data.sequence_state); |
|
if (!status.ok()) { |
|
context_->storage->IncrementStats( |
|
stats::legacy_v8_cpu_profile_invalid_sample); |
|
} |
|
} |
|
} |
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
|
// TODO(eseckler): Replace phase with type and remove handling of |
|
// legacy_event_.phase() once it is no longer used by producers. |
|
char phase = static_cast<char>(ParsePhaseOrType()); |
|
|
|
switch (phase) { |
|
case 'B': // TRACE_EVENT_PHASE_BEGIN. |
|
return ParseThreadBeginEvent(); |
|
case 'E': // TRACE_EVENT_PHASE_END. |
|
return ParseThreadEndEvent(); |
|
case 'X': // TRACE_EVENT_PHASE_COMPLETE. |
|
return ParseThreadCompleteEvent(); |
|
case 's': // TRACE_EVENT_PHASE_FLOW_BEGIN. |
|
case 't': // TRACE_EVENT_PHASE_FLOW_STEP. |
|
case 'f': // TRACE_EVENT_PHASE_FLOW_END. |
|
return ParseFlowEventV1(phase); |
|
case 'i': |
|
case 'I': // TRACE_EVENT_PHASE_INSTANT. |
|
case 'R': // TRACE_EVENT_PHASE_MARK. |
|
return ParseThreadInstantEvent(phase); |
|
case 'b': // TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN |
|
case 'S': |
|
return ParseAsyncBeginEvent(phase); |
|
case 'e': // TRACE_EVENT_PHASE_NESTABLE_ASYNC_END |
|
case 'F': |
|
return ParseAsyncEndEvent(); |
|
case 'n': // TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT |
|
return ParseAsyncInstantEvent(); |
|
case 'T': |
|
case 'p': |
|
return ParseAsyncStepEvent(phase); |
|
case 'M': // TRACE_EVENT_PHASE_METADATA (process and thread names). |
|
return ParseMetadataEvent(); |
|
default: |
|
// Other events are proxied via the raw table for JSON export. |
|
return ParseLegacyEventAsRawEvent(); |
|
} |
— 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.
- 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
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.
-
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
Context
V8 is migrating to modern events in https://issues.chromium.org/issues/498378089. The CPU profiler emits
ProfileandProfileChunkevents under thedisabled-by-default-v8.cpu_profilercategory, which currently use the legacyTRACE_EVENT_SAMPLE_WITH_ID1macro (phase'P').The modern
TrackEvent.Typehas noTYPE_SAMPLE.Current plan is to use
TRACE_EVENT_INSTANThttps://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.Current state in the Perfetto trace processor
Tokenizer
The tokenizer special-cases V8 CPU samples at
perfetto/src/trace_processor/importers/proto/track_event_tokenizer.cc
Lines 465 to 476 in 95454ef
V8Tracker, which populates thecpu_profile_stack_sampletable.Event importer
Phase
'P'has no dedicated case in the phase switchperfetto/src/trace_processor/importers/proto/track_event_event_importer.h
Lines 209 to 244 in 95454ef
chrome_raw_tableas an opaque blob.The problem
Using
TYPE_INSTANTthere'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.TYPE_INSTANTbe 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
Note:
TokenizeModernSampleEventwill be usingTrackEvent::Decoderinstead ofLegacyEvent::Decoderrest of the mechanics from the current tokenizer will remain the same.Would a dedicated
TYPE_SAMPLEbe considered?Adding
TYPE_SAMPLEto theTrackEvent.Typeenum would:cc @camillobruni