Reland "[vm] Generate event ids for synchronous begin and end events."

Fix transposed id and timestamp.

TEST=Instruments, ci
Bug: https://github.com/dart-lang/sdk/issues/49178
Change-Id: I2c2650f28050b179d26e1269729727f58201a8a8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/251581
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Ryan Macnak 2022-07-22 19:13:47 +00:00 committed by Commit Bot
parent a13ef8a5d5
commit 2d13b205d7
30 changed files with 474 additions and 255 deletions

View file

@ -24,15 +24,11 @@ DEFINE_NATIVE_ENTRY(Timeline_isDartStreamEnabled, 0, 0) {
return Bool::False().ptr();
}
DEFINE_NATIVE_ENTRY(Timeline_getNextAsyncId, 0, 0) {
DEFINE_NATIVE_ENTRY(Timeline_getNextTaskId, 0, 0) {
#if !defined(SUPPORT_TIMELINE)
return Integer::New(0);
#else
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder == NULL) {
return Integer::New(0);
}
return Integer::New(recorder->GetNextAsyncId());
return Integer::New(thread->GetNextTaskId());
#endif
}

View file

@ -152,7 +152,7 @@ namespace dart {
V(TypeError_throwNew, 4) \
V(Stopwatch_now, 0) \
V(Stopwatch_frequency, 0) \
V(Timeline_getNextAsyncId, 0) \
V(Timeline_getNextTaskId, 0) \
V(Timeline_getTraceClock, 0) \
V(Timeline_isDartStreamEnabled, 0) \
V(Timeline_reportFlowEvent, 5) \

View file

@ -1900,6 +1900,23 @@ void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
#endif
}
void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
Label* normal_ir_body) {
#if !defined(SUPPORT_TIMELINE)
__ LoadImmediate(R0, target::ToRawSmi(0));
__ Ret();
#else
__ ldr(R1, Address(THR, target::Thread::next_task_id_offset()));
__ ldr(R2, Address(THR, target::Thread::next_task_id_offset() + 4));
__ SmiTag(R0, R1); // Ignore loss of precision.
__ adds(R1, R1, Operand(1));
__ adcs(R2, R2, Operand(0));
__ str(R1, Address(THR, target::Thread::next_task_id_offset()));
__ str(R2, Address(THR, target::Thread::next_task_id_offset() + 4));
__ Ret();
#endif
}
#undef __
} // namespace compiler

View file

@ -2146,6 +2146,20 @@ void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
#endif
}
void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
Label* normal_ir_body) {
#if !defined(SUPPORT_TIMELINE)
__ LoadImmediate(R0, target::ToRawSmi(0));
__ ret();
#else
__ ldr(R0, Address(THR, target::Thread::next_task_id_offset()));
__ add(R1, R0, Operand(1));
__ str(R1, Address(THR, target::Thread::next_task_id_offset()));
__ SmiTag(R0); // Ignore loss of precision.
__ ret();
#endif
}
#undef __
} // namespace compiler

View file

@ -1937,6 +1937,24 @@ void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
#endif
}
void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
Label* normal_ir_body) {
#if !defined(SUPPORT_TIMELINE)
__ LoadImmediate(EAX, target::ToRawSmi(0));
__ ret();
#else
__ movl(EBX, Address(THR, target::Thread::next_task_id_offset()));
__ movl(ECX, Address(THR, target::Thread::next_task_id_offset() + 4));
__ movl(EAX, EBX);
__ SmiTag(EAX); // Ignore loss of precision.
__ addl(EBX, Immediate(1));
__ adcl(ECX, Immediate(0));
__ movl(Address(THR, target::Thread::next_task_id_offset()), EBX);
__ movl(Address(THR, target::Thread::next_task_id_offset() + 4), ECX);
__ ret();
#endif
}
#undef __
} // namespace compiler

View file

@ -2160,6 +2160,30 @@ void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
#endif
}
void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
Label* normal_ir_body) {
#if !defined(SUPPORT_TIMELINE)
__ LoadImmediate(A0, target::ToRawSmi(0));
__ ret();
#elif XLEN == 64
__ ld(A0, Address(THR, target::Thread::next_task_id_offset()));
__ addi(A1, A0, 1);
__ sd(A1, Address(THR, target::Thread::next_task_id_offset()));
__ SmiTag(A0); // Ignore loss of precision.
__ ret();
#else
__ lw(T0, Address(THR, target::Thread::next_task_id_offset()));
__ lw(T1, Address(THR, target::Thread::next_task_id_offset() + 4));
__ SmiTag(A0, T0); // Ignore loss of precision.
__ addi(T2, T0, 1);
__ sltu(T3, T2, T0); // Carry.
__ add(T1, T1, T3);
__ sw(T2, Address(THR, target::Thread::next_task_id_offset()));
__ sw(T1, Address(THR, target::Thread::next_task_id_offset() + 4));
__ ret();
#endif
}
#undef __
} // namespace compiler

View file

@ -2034,6 +2034,21 @@ void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
#endif
}
void AsmIntrinsifier::Timeline_getNextTaskId(Assembler* assembler,
Label* normal_ir_body) {
#if !defined(SUPPORT_TIMELINE)
__ xorq(RAX, RAX); // Return Smi 0.
__ ret();
#else
__ movq(RAX, Address(THR, target::Thread::next_task_id_offset()));
__ movq(RBX, RAX);
__ incq(RBX);
__ movq(Address(THR, target::Thread::next_task_id_offset()), RBX);
__ SmiTag(RAX); // Ignore loss of precision.
__ ret();
#endif
}
#undef __
} // namespace compiler

View file

@ -437,6 +437,7 @@ namespace dart {
V(::, _getDefaultTag, UserTag_defaultTag, 0x6c19c8a5) \
V(::, _getCurrentTag, Profiler_getCurrentTag, 0x70ead08e) \
V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, 0xc97aafb3) \
V(::, _getNextTaskId, Timeline_getNextTaskId, 0x5b2b0b0b) \
#define INTERNAL_LIB_INTRINSIC_LIST(V) \
V(::, allocateOneByteString, AllocateOneByteString, 0x9e7745d5) \

View file

@ -1249,6 +1249,7 @@ class Thread : public AllStatic {
THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
#undef DECLARE_CONSTANT_OFFSET_GETTER
static word next_task_id_offset();
static word random_offset();
static word suspend_state_init_async_entry_point_offset();

File diff suppressed because it is too large Load diff

View file

@ -318,6 +318,7 @@
FIELD(Thread, heap_base_offset) \
FIELD(Thread, callback_code_offset) \
FIELD(Thread, callback_stack_return_offset) \
FIELD(Thread, next_task_id_offset) \
FIELD(Thread, random_offset) \
FIELD(Thread, jump_to_frame_entry_point_offset) \
FIELD(Thread, tsan_utils_offset) \

View file

@ -307,6 +307,7 @@ char* Dart::DartInit(const Dart_InitializeParams* params) {
#endif
OSThread::Init();
Random::Init();
Zone::Init();
#if defined(SUPPORT_TIMELINE)
Timeline::Init();
@ -779,6 +780,7 @@ char* Dart::Cleanup() {
Timeline::Cleanup();
#endif
Zone::Cleanup();
Random::Cleanup();
// Delete the current thread's TLS and set it's TLS to null.
// If it is the last thread then the destructor would call
// OSThread::Cleanup.

View file

@ -6361,10 +6361,10 @@ DART_EXPORT void Dart_TimelineEvent(const char* label,
if (event != NULL) {
switch (type) {
case Dart_Timeline_Event_Begin:
event->Begin(label, timestamp0);
event->Begin(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_End:
event->End(label, timestamp0);
event->End(label, timestamp1_or_async_id, timestamp0);
break;
case Dart_Timeline_Event_Instant:
event->Instant(label, timestamp0);

View file

@ -9413,7 +9413,29 @@ TEST_CASE(DartAPI_TimelineDuration) {
// Make sure it is enabled.
stream->set_enabled(true);
// Add a duration event.
Dart_TimelineEvent("testDurationEvent", 0, 1, Dart_Timeline_Event_Duration, 0,
Dart_TimelineEvent("testDurationEvent", 500, 1500,
Dart_Timeline_Event_Duration, 0, NULL, NULL);
// Check that it is in the output.
TimelineEventRecorder* recorder = Timeline::recorder();
Timeline::ReclaimCachedBlocksFromThreads();
JSONStream js;
IsolateTimelineEventFilter filter(isolate->main_port());
recorder->PrintJSON(&js, &filter);
const char* json = js.ToCString();
EXPECT_SUBSTRING("\"name\":\"testDurationEvent\"", json);
EXPECT_SUBSTRING("\"ph\":\"X\"", json);
EXPECT_SUBSTRING("\"ts\":500", json);
EXPECT_SUBSTRING("\"dur\":1000", json);
}
TEST_CASE(DartAPI_TimelineBegin) {
Isolate* isolate = Isolate::Current();
// Grab embedder stream.
TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
// Add a begin event.
Dart_TimelineEvent("testBeginEvent", 1000, 1, Dart_Timeline_Event_Begin, 0,
NULL, NULL);
// Check that it is in the output.
TimelineEventRecorder* recorder = Timeline::recorder();
@ -9421,7 +9443,31 @@ TEST_CASE(DartAPI_TimelineDuration) {
JSONStream js;
IsolateTimelineEventFilter filter(isolate->main_port());
recorder->PrintJSON(&js, &filter);
EXPECT_SUBSTRING("testDurationEvent", js.ToCString());
const char* json = js.ToCString();
EXPECT_SUBSTRING("\"name\":\"testBeginEvent\"", json);
EXPECT_SUBSTRING("\"ph\":\"B\"", json);
EXPECT_SUBSTRING("\"ts\":1000", json);
}
TEST_CASE(DartAPI_TimelineEnd) {
Isolate* isolate = Isolate::Current();
// Grab embedder stream.
TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
// Add a begin event.
Dart_TimelineEvent("testEndEvent", 1000, 1, Dart_Timeline_Event_End, 0, NULL,
NULL);
// Check that it is in the output.
TimelineEventRecorder* recorder = Timeline::recorder();
Timeline::ReclaimCachedBlocksFromThreads();
JSONStream js;
IsolateTimelineEventFilter filter(isolate->main_port());
recorder->PrintJSON(&js, &filter);
const char* json = js.ToCString();
EXPECT_SUBSTRING("\"name\":\"testEndEvent\"", json);
EXPECT_SUBSTRING("\"ph\":\"E\"", json);
EXPECT_SUBSTRING("\"ts\":1000", json);
}
TEST_CASE(DartAPI_TimelineInstant) {
@ -9430,15 +9476,18 @@ TEST_CASE(DartAPI_TimelineInstant) {
TimelineStream* stream = Timeline::GetEmbedderStream();
// Make sure it is enabled.
stream->set_enabled(true);
Dart_TimelineEvent("testInstantEvent", 0, 1, Dart_Timeline_Event_Instant, 0,
NULL, NULL);
Dart_TimelineEvent("testInstantEvent", 1000, 1, Dart_Timeline_Event_Instant,
0, NULL, NULL);
// Check that it is in the output.
TimelineEventRecorder* recorder = Timeline::recorder();
Timeline::ReclaimCachedBlocksFromThreads();
JSONStream js;
IsolateTimelineEventFilter filter(isolate->main_port());
recorder->PrintJSON(&js, &filter);
EXPECT_SUBSTRING("testInstantEvent", js.ToCString());
const char* json = js.ToCString();
EXPECT_SUBSTRING("\"name\":\"testInstantEvent\"", json);
EXPECT_SUBSTRING("\"ph\":\"i\"", json);
EXPECT_SUBSTRING("\"ts\":1000", json);
}
TEST_CASE(DartAPI_TimelineAsyncDisabled) {
@ -9465,7 +9514,7 @@ TEST_CASE(DartAPI_TimelineAsync) {
// Make sure it is enabled.
stream->set_enabled(true);
int64_t async_id = 99;
Dart_TimelineEvent("testAsyncEvent", 0, async_id,
Dart_TimelineEvent("testAsyncEvent", 1000, async_id,
Dart_Timeline_Event_Async_Begin, 0, NULL, NULL);
// Check that it is in the output.
@ -9474,7 +9523,11 @@ TEST_CASE(DartAPI_TimelineAsync) {
JSONStream js;
IsolateTimelineEventFilter filter(isolate->main_port());
recorder->PrintJSON(&js, &filter);
EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
const char* json = js.ToCString();
EXPECT_SUBSTRING("\"name\":\"testAsyncEvent\"", json);
EXPECT_SUBSTRING("\"ph\":\"b\"", json);
EXPECT_SUBSTRING("\"ts\":1000", json);
EXPECT_SUBSTRING("\"id\":\"63\"", json); // Hex for some reason.
}
TEST_CASE(DartAPI_TimelineClock) {

View file

@ -75,4 +75,26 @@ uint32_t Random::NextUInt32() {
return static_cast<uint32_t>(NextState() & MASK_32);
}
static Random* global_random = nullptr;
static Mutex* global_random_mutex = nullptr;
void Random::Init() {
ASSERT(global_random_mutex == nullptr);
global_random_mutex = new Mutex(NOT_IN_PRODUCT("global_random_mutex"));
ASSERT(global_random == nullptr);
global_random = new Random();
}
void Random::Cleanup() {
delete global_random_mutex;
global_random_mutex = nullptr;
delete global_random;
global_random = nullptr;
}
uint64_t Random::GlobalNextUInt64() {
MutexLocker locker(global_random_mutex);
return global_random->NextUInt64();
}
} // namespace dart

View file

@ -28,6 +28,10 @@ class Random {
static_cast<uint64_t>(NextUInt32());
}
static uint64_t GlobalNextUInt64();
static void Init();
static void Cleanup();
private:
uint64_t NextState();
void Initialize(uint64_t seed);

View file

@ -143,6 +143,12 @@ Thread::Thread(bool is_vm_isolate)
if (!is_vm_isolate) {
InitVMConstants();
}
#if defined(DART_HOST_OS_FUCHSIA)
next_task_id_ = trace_generate_nonce();
#else
next_task_id_ = Random::GlobalNextUInt64();
#endif
}
static const double double_nan_constant = NAN;

View file

@ -1094,6 +1094,10 @@ class Thread : public ThreadState {
void InitVMConstants();
int64_t GetNextTaskId() { return next_task_id_++; }
static intptr_t next_task_id_offset() {
return OFFSET_OF(Thread, next_task_id_);
}
Random* random() { return &thread_random_; }
static intptr_t random_offset() { return OFFSET_OF(Thread, thread_random_); }
@ -1207,6 +1211,7 @@ class Thread : public ThreadState {
uword exit_through_ffi_ = 0;
ApiLocalScope* api_top_scope_;
uint8_t double_truncate_round_supported_;
ALIGN8 int64_t next_task_id_;
ALIGN8 Random thread_random_;
TsanUtils* tsan_utils_ = nullptr;

View file

@ -498,19 +498,25 @@ void TimelineEvent::Duration(const char* label,
}
void TimelineEvent::Begin(const char* label,
int64_t id,
int64_t micros,
int64_t thread_micros) {
Init(kBegin, label);
set_timestamp0(micros);
set_thread_timestamp0(thread_micros);
// Overload timestamp1_ with the async_id.
set_timestamp1(id);
}
void TimelineEvent::End(const char* label,
int64_t id,
int64_t micros,
int64_t thread_micros) {
Init(kEnd, label);
set_timestamp0(micros);
set_thread_timestamp0(thread_micros);
// Overload timestamp1_ with the async_id.
set_timestamp1(id);
}
void TimelineEvent::Counter(const char* label, int64_t micros) {
@ -655,31 +661,31 @@ void TimelineEvent::PrintJSON(JSONWriter* writer) const {
} break;
case kAsyncBegin: {
writer->PrintProperty("ph", "b");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kAsyncInstant: {
writer->PrintProperty("ph", "n");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kAsyncEnd: {
writer->PrintProperty("ph", "e");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kCounter: {
writer->PrintProperty("ph", "C");
} break;
case kFlowBegin: {
writer->PrintProperty("ph", "s");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kFlowStep: {
writer->PrintProperty("ph", "t");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kFlowEnd: {
writer->PrintProperty("ph", "f");
writer->PrintProperty("bp", "e");
writer->PrintfProperty("id", "%" Px64 "", AsyncId());
writer->PrintfProperty("id", "%" Px64 "", Id());
} break;
case kMetadata: {
writer->PrintProperty("ph", "M");
@ -728,14 +734,6 @@ void TimelineEvent::PrintJSON(JSONWriter* writer) const {
writer->CloseObject();
}
int64_t TimelineEvent::TimeOrigin() const {
return timestamp0_;
}
int64_t TimelineEvent::AsyncId() const {
return timestamp1_;
}
int64_t TimelineEvent::LowTime() const {
return timestamp0_;
}
@ -841,6 +839,13 @@ void TimelineEventScope::Init() {
return;
}
enabled_ = true;
Thread* thread = static_cast<Thread*>(this->thread());
if (thread != NULL) {
id_ = thread->GetNextTaskId();
} else {
static RelaxedAtomic<int64_t> next_bootstrap_task_id = {0};
id_ = next_bootstrap_task_id.fetch_add(1);
}
}
void TimelineEventScope::SetNumArguments(intptr_t length) {
@ -919,7 +924,7 @@ void TimelineBeginEndScope::EmitBegin() {
}
ASSERT(event != NULL);
// Emit a begin event.
event->Begin(label());
event->Begin(label(), id());
event->Complete();
}
@ -935,7 +940,7 @@ void TimelineBeginEndScope::EmitEnd() {
}
ASSERT(event != NULL);
// Emit an end event.
event->End(label());
event->End(label(), id());
StealArguments(event);
event->Complete();
}
@ -958,7 +963,7 @@ IsolateTimelineEventFilter::IsolateTimelineEventFilter(
isolate_id_(isolate_id) {}
TimelineEventRecorder::TimelineEventRecorder()
: async_id_(0), time_low_micros_(0), time_high_micros_(0) {}
: time_low_micros_(0), time_high_micros_(0) {}
#ifndef PRODUCT
void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
@ -1120,16 +1125,6 @@ void TimelineEventRecorder::WriteTo(const char* directory) {
}
#endif
int64_t TimelineEventRecorder::GetNextAsyncId() {
// TODO(johnmccutchan): Gracefully handle wrap around.
#if defined(DART_HOST_OS_FUCHSIA)
return trace_generate_nonce();
#else
uint32_t next = static_cast<uint32_t>(async_id_.fetch_add(1u));
return static_cast<int64_t>(next);
#endif
}
void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) {
if (block == NULL) {
return;
@ -1706,10 +1701,10 @@ void DartTimelineEventHelpers::ReportTaskEvent(Thread* thread,
event->AsyncEnd(name, id, start);
break;
case 'B':
event->Begin(name, start, start_cpu);
event->Begin(name, id, start, start_cpu);
break;
case 'E':
event->End(name, start, start_cpu);
event->End(name, id, start, start_cpu);
break;
default:
UNREACHABLE();

View file

@ -334,10 +334,12 @@ class TimelineEvent {
void Begin(
const char* label,
int64_t id,
int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline(),
int64_t thread_micros = OS::GetCurrentThreadCPUMicrosForTimeline());
void End(const char* label,
int64_t id,
int64_t micros = OS::GetCurrentMonotonicMicrosForTimeline(),
int64_t thread_micros = OS::GetCurrentThreadCPUMicrosForTimeline());
@ -390,8 +392,11 @@ class TimelineEvent {
int64_t ThreadCPUTimeDuration() const;
int64_t ThreadCPUTimeOrigin() const;
int64_t TimeOrigin() const;
int64_t AsyncId() const;
int64_t TimeOrigin() const { return timestamp0_; }
int64_t Id() const {
ASSERT(event_type() != kDuration);
return timestamp1_;
}
int64_t TimeDuration() const;
int64_t TimeEnd() const {
ASSERT(IsFinishedDuration());
@ -598,6 +603,8 @@ class TimelineEventScope : public StackResource {
const char* label() const { return label_; }
int64_t id() const { return id_; }
TimelineEventArgument* arguments() const { return arguments_.buffer(); }
intptr_t arguments_length() const { return arguments_.length(); }
@ -613,6 +620,7 @@ class TimelineEventScope : public StackResource {
TimelineStream* stream_;
const char* label_;
int64_t id_;
TimelineEventArguments arguments_;
bool enabled_;
@ -783,7 +791,6 @@ class TimelineEventRecorder : public MallocAllocated {
virtual void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) = 0;
#endif
virtual const char* name() const = 0;
int64_t GetNextAsyncId();
void FinishBlock(TimelineEventBlock* block);
@ -814,7 +821,6 @@ class TimelineEventRecorder : public MallocAllocated {
int64_t TimeExtentMicros() const;
Mutex lock_;
RelaxedAtomic<uintptr_t> async_id_;
int64_t time_low_micros_;
int64_t time_high_micros_;

View file

@ -79,12 +79,12 @@ intptr_t TimelineEventSystraceRecorder::PrintSystrace(TimelineEvent* event,
}
case TimelineEvent::kAsyncBegin: {
length = Utils::SNPrint(buffer, buffer_size, "S|%" Pd64 "|%s|%" Pd64 "",
pid, event->label(), event->AsyncId());
pid, event->label(), event->Id());
break;
}
case TimelineEvent::kAsyncEnd: {
length = Utils::SNPrint(buffer, buffer_size, "F|%" Pd64 "|%s|%" Pd64 "",
pid, event->label(), event->AsyncId());
pid, event->label(), event->Id());
break;
}
default:

View file

@ -78,19 +78,19 @@ void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) {
args, num_args);
break;
case TimelineEvent::kAsyncBegin:
trace_context_write_async_begin_event_record(
context, start_time, &thread, &category, &name, event->AsyncId(),
args, num_args);
trace_context_write_async_begin_event_record(context, start_time, &thread,
&category, &name,
event->Id(), args, num_args);
break;
case TimelineEvent::kAsyncEnd:
trace_context_write_async_end_event_record(
context, end_time, &thread, &category, &name, event->AsyncId(), args,
num_args);
trace_context_write_async_end_event_record(context, end_time, &thread,
&category, &name, event->Id(),
args, num_args);
break;
case TimelineEvent::kAsyncInstant:
trace_context_write_async_instant_event_record(
context, start_time, &thread, &category, &name, event->AsyncId(),
args, num_args);
context, start_time, &thread, &category, &name, event->Id(), args,
num_args);
break;
case TimelineEvent::kDuration:
trace_context_write_duration_event_record(context, start_time, end_time,
@ -98,19 +98,19 @@ void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) {
num_args);
break;
case TimelineEvent::kFlowBegin:
trace_context_write_flow_begin_event_record(
context, start_time, &thread, &category, &name, event->AsyncId(),
args, num_args);
trace_context_write_flow_begin_event_record(context, start_time, &thread,
&category, &name, event->Id(),
args, num_args);
break;
case TimelineEvent::kFlowStep:
trace_context_write_flow_step_event_record(
context, start_time, &thread, &category, &name, event->AsyncId(),
args, num_args);
trace_context_write_flow_step_event_record(context, start_time, &thread,
&category, &name, event->Id(),
args, num_args);
break;
case TimelineEvent::kFlowEnd:
trace_context_write_flow_end_event_record(
context, start_time, &thread, &category, &name, event->AsyncId(),
args, num_args);
trace_context_write_flow_end_event_record(context, start_time, &thread,
&category, &name, event->Id(),
args, num_args);
break;
default:
// TODO(zra): Figure out what to do with kCounter and kMetadata.

View file

@ -79,12 +79,12 @@ intptr_t TimelineEventSystraceRecorder::PrintSystrace(TimelineEvent* event,
}
case TimelineEvent::kAsyncBegin: {
length = Utils::SNPrint(buffer, buffer_size, "S|%" Pd64 "|%s|%" Pd64 "",
pid, event->label(), event->AsyncId());
pid, event->label(), event->Id());
break;
}
case TimelineEvent::kAsyncEnd: {
length = Utils::SNPrint(buffer, buffer_size, "F|%" Pd64 "|%s|%" Pd64 "",
pid, event->label(), event->AsyncId());
pid, event->label(), event->Id());
break;
}
default:

View file

@ -40,28 +40,18 @@ void TimelineEventMacosRecorder::OnEvent(TimelineEvent* event) {
buffer, sizeof(buffer));
break;
}
case TimelineEvent::kBegin: {
_os_signpost_emit_with_name_impl(
&__dso_handle, log, OS_SIGNPOST_INTERVAL_BEGIN,
OS_SIGNPOST_ID_EXCLUSIVE, label, "", buffer, sizeof(buffer));
break;
}
case TimelineEvent::kEnd: {
_os_signpost_emit_with_name_impl(
&__dso_handle, log, OS_SIGNPOST_INTERVAL_END,
OS_SIGNPOST_ID_EXCLUSIVE, label, "", buffer, sizeof(buffer));
break;
}
case TimelineEvent::kBegin:
case TimelineEvent::kAsyncBegin: {
_os_signpost_emit_with_name_impl(
&__dso_handle, log, OS_SIGNPOST_INTERVAL_BEGIN, event->AsyncId(),
label, "", buffer, sizeof(buffer));
_os_signpost_emit_with_name_impl(&__dso_handle, log,
OS_SIGNPOST_INTERVAL_BEGIN, event->Id(),
label, "", buffer, sizeof(buffer));
break;
}
case TimelineEvent::kEnd:
case TimelineEvent::kAsyncEnd: {
_os_signpost_emit_with_name_impl(
&__dso_handle, log, OS_SIGNPOST_INTERVAL_END, event->AsyncId(), label,
"", buffer, sizeof(buffer));
_os_signpost_emit_with_name_impl(&__dso_handle, log,
OS_SIGNPOST_INTERVAL_END, event->Id(),
label, "", buffer, sizeof(buffer));
break;
}
case TimelineEvent::kCounter: {
@ -69,8 +59,8 @@ void TimelineEventMacosRecorder::OnEvent(TimelineEvent* event) {
Utils::SNPrint(reinterpret_cast<char*>(buffer), sizeof(buffer), fmt,
event->arguments()[0].value);
_os_signpost_emit_with_name_impl(&__dso_handle, log, OS_SIGNPOST_EVENT,
event->AsyncId(), label, fmt, buffer,
sizeof(buffer));
OS_SIGNPOST_ID_EXCLUSIVE, label, fmt,
buffer, sizeof(buffer));
break;
}
default:

View file

@ -318,8 +318,8 @@ TEST_CASE(TimelineEventCallbackRecorderBasic) {
event = stream.StartEvent();
EXPECT_EQ(0, override.recorder()->CountFor(TimelineEvent::kAsyncBegin));
int64_t async_id = override.recorder()->GetNextAsyncId();
EXPECT(async_id >= 0);
int64_t async_id = thread->GetNextTaskId();
EXPECT(async_id != 0);
event->AsyncBegin("asyncBeginCabbage", async_id);
EXPECT_EQ(0, override.recorder()->CountFor(TimelineEvent::kAsyncBegin));
event->Complete();

View file

@ -157,7 +157,7 @@ void _reportInstantEvent(String category, String name, String argumentsAsJson) {
}
@patch
int _getNextAsyncId() {
int _getNextTaskId() {
return 0;
}

View file

@ -80,7 +80,7 @@ void _reportInstantEvent(String category, String name, String argumentsAsJson) {
}
@patch
int _getNextAsyncId() {
int _getNextTaskId() {
return 0;
}

View file

@ -13,8 +13,8 @@ external bool _isDartStreamEnabled();
external int _getTraceClock();
@patch
@pragma("vm:external-name", "Timeline_getNextAsyncId")
external int _getNextAsyncId();
@pragma("vm:external-name", "Timeline_getNextTaskId")
external int _getNextTaskId();
@patch
@pragma("vm:external-name", "Timeline_reportTaskEvent")

View file

@ -49,7 +49,7 @@ int _getTraceClock() => _traceClock++;
int _traceClock = 0;
@patch
int _getNextAsyncId() => 0;
int _getNextTaskId() => 0;
@patch
void _reportTaskEvent(int taskId, String phase, String category, String name,

View file

@ -60,7 +60,7 @@ class Flow {
/// If [id] is not provided, an id that conflicts with no other Dart-generated
/// flow id's will be generated.
static Flow begin({int? id}) {
return new Flow._(_begin, id ?? _getNextAsyncId());
return new Flow._(_begin, id ?? _getNextTaskId());
}
/// A "step" Flow event.
@ -112,7 +112,8 @@ class Timeline {
_stack.add(null);
return;
}
var block = new _SyncBlock._(name, arguments: arguments, flow: flow);
var block = new _SyncBlock._(name, _getNextTaskId(),
arguments: arguments, flow: flow);
_stack.add(block);
block._startSync();
}
@ -190,7 +191,7 @@ class TimelineTask {
TimelineTask({TimelineTask? parent, String? filterKey})
: _parent = parent,
_filterKey = filterKey,
_taskId = _getNextAsyncId() {}
_taskId = _getNextTaskId() {}
/// Create a task with an explicit [taskId]. This is useful if you are
/// passing a task from one isolate to another.
@ -335,6 +336,9 @@ class _SyncBlock {
/// The name of this block.
final String name;
/// Signpost needs help matching begin and end events.
final int taskId;
/// An (optional) set of arguments which will be serialized to JSON and
/// associated with this block.
final Map? arguments;
@ -344,18 +348,18 @@ class _SyncBlock {
late final String _jsonArguments = _argumentsAsJson(arguments);
_SyncBlock._(this.name, {this.arguments, this.flow});
_SyncBlock._(this.name, this.taskId, {this.arguments, this.flow});
/// Start this block of time.
void _startSync() {
_reportTaskEvent(0, 'B', category, name, _jsonArguments);
_reportTaskEvent(taskId, 'B', category, name, _jsonArguments);
}
/// Finish this block of time. At this point, this block can no longer be
/// used.
void finish() {
// Report event to runtime.
_reportTaskEvent(0, 'E', category, name, _jsonArguments);
_reportTaskEvent(taskId, 'E', category, name, _jsonArguments);
final Flow? tempFlow = flow;
if (tempFlow != null) {
_reportFlowEvent(category, "${tempFlow.id}", tempFlow._type, tempFlow.id,
@ -376,8 +380,9 @@ String _argumentsAsJson(Map? arguments) {
@pragma("vm:recognized", "asm-intrinsic")
external bool _isDartStreamEnabled();
/// Returns the next async task id.
external int _getNextAsyncId();
/// Returns the next task id.
@pragma("vm:recognized", "asm-intrinsic")
external int _getNextTaskId();
/// Returns the current value from the trace clock.
external int _getTraceClock();