Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle deprecation of Dart_TimelineEvent Embedder API #42497

Merged
merged 2 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions flow/frame_timings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
#include "flutter/fml/time/time_delta.h"
#include "flutter/fml/time/time_point.h"

#define TRACE_EVENT_WITH_FRAME_NUMBER(recorder, category_group, name) \
TRACE_EVENT1(category_group, name, "frame_number", \
recorder->GetFrameNumberTraceArg())
#define TRACE_EVENT_WITH_FRAME_NUMBER(recorder, category_group, name, \
flow_id_count, flow_ids) \
TRACE_EVENT1_WITH_FLOW_IDS(category_group, name, flow_id_count, flow_ids, \
"frame_number", \
recorder->GetFrameNumberTraceArg())

namespace flutter {

Expand Down
126 changes: 102 additions & 24 deletions fml/trace_event.cc

Large diffs are not rendered by default.

154 changes: 128 additions & 26 deletions fml/trace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,27 @@
::fml::tracing::TraceCounterNopHACK((a), (b), (c), (arg1), __VA_ARGS__);

#define FML_TRACE_EVENT(a, b, args...) TRACE_DURATION(a, b)
// On Fuchsia, the flow_id arguments to this macro are ignored.
#define FML_TRACE_EVENT_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids, ...) \
FML_TRACE_EVENT(category_group, name)

#define TRACE_EVENT0(a, b) TRACE_DURATION(a, b)
// On Fuchsia, the flow_id arguments to this macro are ignored.
#define TRACE_EVENT0_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids) \
TRACE_EVENT0(category_group, name)
#define TRACE_EVENT1(a, b, c, d) TRACE_DURATION(a, b, c, d)
// On Fuchsia, the flow_id arguments to this macro are ignored.
#define TRACE_EVENT1_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids, arg1_name, arg1_val) \
TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
#define TRACE_EVENT2(a, b, c, d, e, f) TRACE_DURATION(a, b, c, d, e, f)
#define TRACE_EVENT_ASYNC_BEGIN0(a, b, c) TRACE_ASYNC_BEGIN(a, b, c)
// On Fuchsia, the flow_id arguments to this macro are ignored.
#define TRACE_EVENT_ASYNC_BEGIN0_WITH_FLOW_IDS(category_group, name, id, \
flow_id_count, flow_ids) \
TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id)
#define TRACE_EVENT_ASYNC_END0(a, b, c) TRACE_ASYNC_END(a, b, c)
#define TRACE_EVENT_ASYNC_BEGIN1(a, b, c, d, e) TRACE_ASYNC_BEGIN(a, b, c, d, e)
#define TRACE_EVENT_ASYNC_END1(a, b, c, d, e) TRACE_ASYNC_END(a, b, c, d, e)
Expand Down Expand Up @@ -83,49 +99,93 @@
// ```
//
// Instead, either use different `name` or `arg1` parameter names.
#define FML_TRACE_EVENT(category_group, name, ...) \
::fml::tracing::TraceEvent((category_group), (name), __VA_ARGS__); \
#define FML_TRACE_EVENT_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids, ...) \
::fml::tracing::TraceEvent((category_group), (name), (flow_id_count), \
(flow_ids), __VA_ARGS__); \
__FML__AUTO_TRACE_END(name)

#define TRACE_EVENT0(category_group, name) \
::fml::tracing::TraceEvent0(category_group, name); \
// Avoid using the same `name` and `argX_name` for nested traces, which can
// lead to double free errors. E.g. the following code should be avoided:
//
// ```cpp
// {
// TRACE_EVENT1("flutter", "Foo::Bar", "count", "initial_count_value");
// ...
// TRACE_EVENT_INSTANT1("flutter", "Foo::Bar",
// "count", "updated_count_value");
// }
// ```
//
// Instead, either use different `name` or `arg1` parameter names.
#define FML_TRACE_EVENT(category_group, name, ...) \
FML_TRACE_EVENT_WITH_FLOW_IDS((category_group), (name), \
/*flow_id_count=*/(0), /*flow_ids=*/(nullptr), \
__VA_ARGS__)

#define TRACE_EVENT0_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids) \
::fml::tracing::TraceEvent0(category_group, name, flow_id_count, flow_ids); \
__FML__AUTO_TRACE_END(name)

#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
::fml::tracing::TraceEvent1(category_group, name, arg1_name, arg1_val); \
#define TRACE_EVENT0(category_group, name) \
TRACE_EVENT0_WITH_FLOW_IDS(category_group, name, /*flow_id_count=*/0, \
/*flow_ids=*/nullptr)

#define TRACE_EVENT1_WITH_FLOW_IDS(category_group, name, flow_id_count, \
flow_ids, arg1_name, arg1_val) \
::fml::tracing::TraceEvent1(category_group, name, flow_id_count, flow_ids, \
arg1_name, arg1_val); \
__FML__AUTO_TRACE_END(name)

#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val) \
TRACE_EVENT1_WITH_FLOW_IDS(category_group, name, /*flow_id_count=*/0, \
/*flow_ids=*/nullptr, arg1_name, arg1_val)

#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, \
arg2_val) \
::fml::tracing::TraceEvent2(category_group, name, arg1_name, arg1_val, \
::fml::tracing::TraceEvent2(category_group, name, /*flow_id_count=*/0, \
/*flow_ids=*/nullptr, arg1_name, arg1_val, \
arg2_name, arg2_val); \
__FML__AUTO_TRACE_END(name)

#define TRACE_EVENT_ASYNC_BEGIN0_WITH_FLOW_IDS(category_group, name, id, \
flow_id_count, flow_ids) \
::fml::tracing::TraceEventAsyncBegin0(category_group, name, id, \
flow_id_count, flow_ids);

#define TRACE_EVENT_ASYNC_BEGIN0(category_group, name, id) \
::fml::tracing::TraceEventAsyncBegin0(category_group, name, id);
TRACE_EVENT_ASYNC_BEGIN0_WITH_FLOW_IDS( \
category_group, name, id, /*flow_id_count=*/0, /*flow_ids=*/nullptr)

#define TRACE_EVENT_ASYNC_END0(category_group, name, id) \
::fml::tracing::TraceEventAsyncEnd0(category_group, name, id);

#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
arg1_val) \
::fml::tracing::TraceEventAsyncBegin1(category_group, name, id, arg1_name, \
arg1_val);
#define TRACE_EVENT_ASYNC_BEGIN1(category_group, name, id, arg1_name, \
arg1_val) \
::fml::tracing::TraceEventAsyncBegin1( \
category_group, name, id, /*flow_id_count=*/0, /*flow_ids=*/nullptr, \
arg1_name, arg1_val);

#define TRACE_EVENT_ASYNC_END1(category_group, name, id, arg1_name, arg1_val) \
::fml::tracing::TraceEventAsyncEnd1(category_group, name, id, arg1_name, \
arg1_val);
::fml::tracing::TraceEventAsyncEnd1( \
category_group, name, id, /*flow_id_count=*/0, /*flow_ids=*/nullptr, \
arg1_name, arg1_val);

#define TRACE_EVENT_INSTANT0(category_group, name) \
::fml::tracing::TraceEventInstant0(category_group, name);
::fml::tracing::TraceEventInstant0( \
category_group, name, /*flow_id_count=*/0, /*flow_ids=*/nullptr);

#define TRACE_EVENT_INSTANT1(category_group, name, arg1_name, arg1_val) \
::fml::tracing::TraceEventInstant1(category_group, name, arg1_name, arg1_val);
::fml::tracing::TraceEventInstant1( \
category_group, name, /*flow_id_count=*/0, /*flow_ids=*/nullptr, \
arg1_name, arg1_val);

#define TRACE_EVENT_INSTANT2(category_group, name, arg1_name, arg1_val, \
arg2_name, arg2_val) \
::fml::tracing::TraceEventInstant2(category_group, name, arg1_name, \
arg1_val, arg2_name, arg2_val);
::fml::tracing::TraceEventInstant2( \
category_group, name, /*flow_id_count=*/0, /*flow_ids=*/nullptr, \
arg1_name, arg1_val, arg2_name, arg2_val);

#define TRACE_FLOW_BEGIN(category, name, id) \
::fml::tracing::TraceEventFlowBegin0(category, name, id);
Expand Down Expand Up @@ -157,6 +217,8 @@ void TraceSetAllowlist(const std::vector<std::string>& allowlist);
typedef void (*TimelineEventHandler)(const char*,
int64_t,
int64_t,
intptr_t,
const int64_t*,
Dart_Timeline_Event_Type,
intptr_t,
const char**,
Expand All @@ -176,13 +238,17 @@ void TraceTimelineEvent(TraceArg category_group,
TraceArg name,
int64_t timestamp_micros,
TraceIDArg id,
size_t flow_id_count,
const uint64_t* flow_ids,
Dart_Timeline_Event_Type type,
const std::vector<const char*>& names,
const std::vector<std::string>& values);

void TraceTimelineEvent(TraceArg category_group,
TraceArg name,
TraceIDArg id,
size_t flow_id_count,
const uint64_t* flow_ids,
Dart_Timeline_Event_Type type,
const std::vector<const char*>& names,
const std::vector<std::string>& values);
Expand Down Expand Up @@ -241,7 +307,8 @@ void TraceCounter(TraceArg category,
Args... args) {
#if FLUTTER_TIMELINE_ENABLED
auto split = SplitArguments(args...);
TraceTimelineEvent(category, name, identifier, Dart_Timeline_Event_Counter,
TraceTimelineEvent(category, name, identifier, /*flow_id_count=*/0,
/*flow_ids=*/nullptr, Dart_Timeline_Event_Counter,
split.first, split.second);
#endif // FLUTTER_TIMELINE_ENABLED
}
Expand All @@ -255,23 +322,34 @@ void TraceCounterNopHACK(TraceArg category,
Args... args) {}

template <typename... Args>
void TraceEvent(TraceArg category, TraceArg name, Args... args) {
void TraceEvent(TraceArg category,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids,
Args... args) {
#if FLUTTER_TIMELINE_ENABLED
auto split = SplitArguments(args...);
TraceTimelineEvent(category, name, 0, Dart_Timeline_Event_Begin, split.first,
split.second);
TraceTimelineEvent(category, name, 0, flow_id_count, flow_ids,
Dart_Timeline_Event_Begin, split.first, split.second);
#endif // FLUTTER_TIMELINE_ENABLED
}

void TraceEvent0(TraceArg category_group, TraceArg name);
void TraceEvent0(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids);

void TraceEvent1(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids,
TraceArg arg1_name,
TraceArg arg1_val);

void TraceEvent2(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids,
TraceArg arg1_name,
TraceArg arg1_val,
TraceArg arg2_name,
Expand Down Expand Up @@ -300,6 +378,8 @@ void TraceEventAsyncComplete(TraceArg category_group,
name, // name
begin_micros, // timestamp_micros
identifier, // identifier
0, // flow_id_count
nullptr, // flow_ids
Dart_Timeline_Event_Async_Begin, // type
split.first, // names
split.second // values
Expand All @@ -309,6 +389,8 @@ void TraceEventAsyncComplete(TraceArg category_group,
name, // name
end_micros, // timestamp_micros
identifier, // identifier
0, // flow_id_count
nullptr, // flow_ids
Dart_Timeline_Event_Async_End, // type
split.first, // names
split.second // values
Expand All @@ -318,13 +400,17 @@ void TraceEventAsyncComplete(TraceArg category_group,

void TraceEventAsyncBegin0(TraceArg category_group,
TraceArg name,
TraceIDArg id);
TraceIDArg id,
size_t flow_id_count,
const uint64_t* flow_ids);

void TraceEventAsyncEnd0(TraceArg category_group, TraceArg name, TraceIDArg id);

void TraceEventAsyncBegin1(TraceArg category_group,
TraceArg name,
TraceIDArg id,
size_t flow_id_count,
const uint64_t* flow_ids,
TraceArg arg1_name,
TraceArg arg1_val);

Expand All @@ -334,15 +420,22 @@ void TraceEventAsyncEnd1(TraceArg category_group,
TraceArg arg1_name,
TraceArg arg1_val);

void TraceEventInstant0(TraceArg category_group, TraceArg name);
void TraceEventInstant0(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids);

void TraceEventInstant1(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids,
TraceArg arg1_name,
TraceArg arg1_val);

void TraceEventInstant2(TraceArg category_group,
TraceArg name,
size_t flow_id_count,
const uint64_t* flow_ids,
TraceArg arg1_name,
TraceArg arg1_val,
TraceArg arg2_name,
Expand Down Expand Up @@ -376,7 +469,10 @@ class ScopedInstantEnd {
class TraceFlow {
public:
explicit TraceFlow(const char* label) : label_(label), nonce_(TraceNonce()) {
TraceEvent0("flutter", label_, /*flow_id_count=*/1,
/*flow_ids=*/&nonce_);
TraceEventFlowBegin0("flutter", label_, nonce_);
TraceEventEnd(label_);
}

~TraceFlow() { End(label_); }
Expand All @@ -386,19 +482,25 @@ class TraceFlow {
}

void Step(const char* label = nullptr) const {
TraceEvent0("flutter", label ? label : label_, /*flow_id_count=*/1,
/*flow_ids=*/&nonce_);
TraceEventFlowStep0("flutter", label ? label : label_, nonce_);
TraceEventEnd(label ? label : label_);
}

void End(const char* label = nullptr) {
if (nonce_ != 0) {
TraceEvent0("flutter", label ? label : label_, /*flow_id_count=*/1,
/*flow_ids=*/&nonce_);
TraceEventFlowEnd0("flutter", label ? label : label_, nonce_);
TraceEventEnd(label ? label : label_);
nonce_ = 0;
}
}

private:
const char* label_;
size_t nonce_;
uint64_t nonce_;

FML_DISALLOW_COPY_AND_ASSIGN(TraceFlow);
};
Expand Down
16 changes: 9 additions & 7 deletions runtime/dart_vm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -472,13 +472,15 @@ DartVM::DartVM(const std::shared_ptr<const DartVMData>& vm_data,
// As this call is immediately after initialization of the Dart VM,
// we are interested in only one timestamp.
int64_t micros = Dart_TimelineGetMicros();
Dart_TimelineEvent("FlutterEngineMainEnter", // label
micros, // timestamp0
micros, // timestamp1_or_async_id
Dart_Timeline_Event_Instant, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
Dart_RecordTimelineEvent("FlutterEngineMainEnter", // label
micros, // timestamp0
micros, // timestamp1_or_async_id
0, // flow_id_count
nullptr, // flow_ids
Dart_Timeline_Event_Instant, // event type
0, // argument_count
nullptr, // argument_names
nullptr // argument_values
);
}

Expand Down
21 changes: 12 additions & 9 deletions runtime/dart_vm_initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,17 @@ void DartVMInitializer::Initialize(Dart_InitializeParams* params,
void DartVMInitializer::Cleanup() {
FML_DCHECK(gDartInitialized);

// Dart_TimelineEvent is unsafe during a concurrent call to Dart_Cleanup
// Dart_RecordTimelineEvent is unsafe during a concurrent call to Dart_Cleanup
// because Dart_Cleanup will destroy the timeline recorder. Clear the
// initialized flag so that future calls to LogDartTimelineEvent will not
// call Dart_TimelineEvent.
// call Dart_RecordTimelineEvent.
//
// Note that this is inherently racy. If a thread sees that gDartInitialized
// is set and proceeds to call Dart_TimelineEvent shortly before another
// thread calls Dart_Cleanup, then the Dart_TimelineEvent call may crash
// if Dart_Cleanup deletes the timeline before Dart_TimelineEvent completes.
// In practice this is unlikely because Dart_Cleanup does significant other
// work before deleting the timeline.
// is set and proceeds to call Dart_RecordTimelineEvent shortly before another
// thread calls Dart_Cleanup, then the Dart_RecordTimelineEvent call may crash
// if Dart_Cleanup deletes the timeline before Dart_RecordTimelineEvent
// completes. In practice this is unlikely because Dart_Cleanup does
// significant other work before deleting the timeline.
//
// The engine can not safely guard Dart_Cleanup and LogDartTimelineEvent with
// a lock due to the risk of deadlocks. Dart_Cleanup waits for various
Expand All @@ -142,12 +142,15 @@ void DartVMInitializer::Cleanup() {
void DartVMInitializer::LogDartTimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
intptr_t flow_id_count,
const int64_t* flow_ids,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values) {
if (gDartInitialized) {
Dart_TimelineEvent(label, timestamp0, timestamp1_or_async_id, type,
argument_count, argument_names, argument_values);
Dart_RecordTimelineEvent(label, timestamp0, timestamp1_or_async_id,
flow_id_count, flow_ids, type, argument_count,
argument_names, argument_values);
}
}
Loading