/path/to/engine/src/third_party/dart/runtime/vm/timeline.cc
// 执行宏定义
DEFINE_FLAG(charp,
timeline_streams,
NULL,
"Comma separated list of timeline streams to record. "
"Valid values: all, API, Compiler, CompilerVerbose, Dart, "
"Debugger, Embedder, GC, Isolate, and VM.");
// 展开后:
charp FLAG_timeline_streams = Flags::Register_charp(&FLAG_timeline_streams, 'timeline_streams', NULL, "Comma separated list of timeline streams to record. "
"Valid values: all, API, Compiler, CompilerVerbose, Dart, "
"Debugger, Embedder, GC, Isolate, and VM.");
/path/to/engine/src/third_party/dart/runtime/vm/flags.cc
const char* Flags::Register_charp(charp* addr,
const char* name,
const char* default_value,
const char* comment) {
ASSERT(Lookup(name) == NULL);
Flag* flag = new Flag(name, comment, addr, Flag::kString);
AddFlag(flag);
return default_value;
}
path/to/engine/src/flutter/runtime/dart_vm.cc
char* flags_error = Dart_SetVMFlags(args.size(), args.data());
/path/to/engine/src/third_party/dart/runtime/vm/flags.cc
char* Flags::ProcessCommandLineFlags(int number_of_vm_flags,
const char** vm_flags) {
...
while ((i < number_of_vm_flags) &&
IsValidFlag(vm_flags[i], kPrefix, kPrefixLen)) {
const char* option = vm_flags[i] + kPrefixLen;
Parse(option);
i++;
}
...
}
bool Flags::SetFlagFromString(Flag* flag, const char* argument) {
ASSERT(!flag->IsUnrecognized());
switch (flag->type_) {
...
case Flag::kString: {
*flag->charp_ptr_ = argument == NULL ? NULL : strdup(argument);
break;
}
....
}
flag->changed_ = true;
return true;
}
union {
void* addr_;
bool* bool_ptr_;
int* int_ptr_;
uint64_t* uint64_ptr_;
charp* charp_ptr_;
FlagHandler flag_handler_;
OptionHandler option_handler_;
}
/path/to/engine/src/third_party/dart/runtime/vm/timeline.h
// stream 申明
static TimelineStream stream_
TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
// 展开后
static TimelineStream stream_API_;
static TimelineStream stream_Compiler_;
static TimelineStream stream_Dart_;
static TimelineStream stream_Embedder_;
....
/path/to/engine/src/third_party/dart/runtime/vm/timeline.h
// 获取 Stream
static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
// 展开后
static TimelineStream* GetAPIStream() { return &stream_API_; }
static TimelineStream* GetDartStream() { return &stream_Dart_; }
static TimelineStream* GetEmbedderStream() { return &stream_Embedder_; }
...
/path/to/engine/src/third_party/dart/runtime/vm/timeline.cc
TimelineStream Timeline::stream_##name##_(#name, fuchsia_name, false);
TIMELINE_STREAM_LIST(TIMELINE_STREAM_DEFINE)
// 展开后
TimelineStream Timeline::stream_API_("API", "dart:api", false);
TimelineStream Timeline::stream_Dart_("Dart", "dart:dart", false);
TimelineStream Timeline::stream_Embedder_("Embedder", "dart:embedder", false);
...
void Timeline::Init() {
ASSERT(recorder_ == NULL);
recorder_ = CreateTimelineRecorder();
ASSERT(recorder_ != NULL);
enabled_streams_ = GetEnabledByDefaultTimelineStreams();
// Global overrides.
stream_##name##_.set_enabled(HasStream(enabled_streams_, #name));
TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT)
}
{
TRACE_EVENT0("flutter", "Shell::CreateWithSnapshots");
}
// 展开后
::fml::tracing::TraceEvent0("flutter", "Shell::CreateWithSnapshots");
::fml::tracing::ScopedInstantEnd __trace_end___LINE__("Shell::CreateWithSnapshots");
path/to/engine/src/third_party/dart/runtime/vm/dart_api_impl.cc
DART_EXPORT void Dart_TimelineEvent(const char* label,
int64_t timestamp0,
int64_t timestamp1_or_async_id,
Dart_Timeline_Event_Type type,
intptr_t argument_count,
const char** argument_names,
const char** argument_values) {
...
TimelineStream* stream = Timeline::GetEmbedderStream();
ASSERT(stream != NULL);
TimelineEvent* event = stream->StartEvent();
...
switch (type) {
case Dart_Timeline_Event_Begin:
event->Begin(label, timestamp0);
break;
case Dart_Timeline_Event_End:
event->End(label, timestamp0);
break;
...
}
...
event->Complete();
}
/path/to/engine/src/third_party/dart/runtime/vm/timeline.cc
TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() {
// Grab the current thread.
OSThread* thread = OSThread::Current();
ASSERT(thread != NULL);
Mutex* thread_block_lock = thread->timeline_block_lock();
...
thread_block_lock->Lock(); // 会一直持有,直到调用 CompleteEvent()
...
TimelineEventBlock* thread_block = thread->timeline_block();
if ((thread_block != NULL) && thread_block->IsFull()) {
MutexLocker ml(&lock_);
// Thread has a block and it is full:
// 1) Mark it as finished.
thread_block->Finish();
// 2) Allocate a new block.
thread_block = GetNewBlockLocked();
thread->set_timeline_block(thread_block);
} else if (thread_block == NULL) {
MutexLocker ml(&lock_);
// Thread has no block. Attempt to allocate one.
thread_block = GetNewBlockLocked();
thread->set_timeline_block(thread_block);
}
if (thread_block != NULL) {
// NOTE: We are exiting this function with the thread's block lock held.
ASSERT(!thread_block->IsFull());
TimelineEvent* event = thread_block->StartEvent();
return event;
}
....
thread_block_lock->Unlock();
return NULL;
}
/path/to/engine/src/third_party/dart/runtime/vm/timeline.cc
void TimelineEvent::Begin(const char* label,
int64_t micros,
int64_t thread_micros) {
Init(kBegin, label);
set_timestamp0(micros);
set_thread_timestamp0(thread_micros);
}
Init: 记录事件标签名,事情类型(kBegin,kEnd),End 一般会在作用域析构时调用(下面会分析)。
micros: 记录系统启动后运行的时间戳。
thread_micros: 记录该线程CPU运行的时间戳。
/path/to/engine/src/third_party/dart/runtime/vm/timeline.cc
void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) {
...
// Grab the current thread.
OSThread* thread = OSThread::Current();
ASSERT(thread != NULL);
// Unlock the thread's block lock.
Mutex* thread_block_lock = thread->timeline_block_lock();
...
thread_block_lock->Unlock();
}
void TimelineEventBlock::Finish() {
...
in_use_ = false;
if (Service::timeline_stream.enabled()) {
ServiceEvent service_event(NULL, ServiceEvent::kTimelineEvents);
service_event.set_timeline_event_block(this);
Service::HandleEvent(&service_event);
}
}
path/to/engine/flutter/fml/trace_event.h
class ScopedInstantEnd {
public:
ScopedInstantEnd(const char* str) : label_(str) {}
~ScopedInstantEnd() { TraceEventEnd(label_); }
private:
const char* label_;
FML_DISALLOW_COPY_AND_ASSIGN(ScopedInstantEnd);
};
flutter run --trace-startup --profile
path/to/flutter/packages/flutter_tools/lib/src/tracing.dart
/// Download the startup trace information from the given observatory client and
/// store it to build/start_up_info.json.
Future<void> downloadStartupTrace(VMService observatory, { bool awaitFirstFrame = true }) async {
final Tracing tracing = Tracing(observatory);
final Map<String, dynamic> timeline = await tracing.stopTracingAndDownloadTimeline(
awaitFirstFrame: awaitFirstFrame,
);
......
final Map<String, dynamic> traceInfo = <String, dynamic>{
'engineEnterTimestampMicros': engineEnterTimestampMicros,
};
......
traceInfo['timeToFrameworkInitMicros'] = timeToFrameworkInitMicros;
......
traceInfo['timeToFirstFrameRasterizedMicros'] = firstFrameRasterizedTimestampMicros - engineEnterTimestampMicros;
......
traceInfo['timeToFirstFrameMicros'] = timeToFirstFrameMicros;
......
traceInfo['timeAfterFrameworkInitMicros'] = firstFrameBuiltTimestampMicros - frameworkInitTimestampMicros;
......
traceInfoFile.writeAsStringSync(toPrettyJson(traceInfo));
}
/// Download the startup trace information from the given observatory client and
/// store it to build/start_up_info.json.
Future<void> downloadStartupTrace(VMService observatory, { bool awaitFirstFrame = true }) async {
final Tracing tracing = Tracing(observatory);
final Map<String, dynamic> timeline = await tracing.stopTracingAndDownloadTimeline(
awaitFirstFrame: awaitFirstFrame,
);
......
// 原来的 start_up_info.json 生成
traceInfoFile.writeAsStringSync(toPrettyJson(traceInfo));
......
// 新增 start_up_trace_events.json 生成
final String traceEventsFilePath = globals.fs.path.join(getBuildDirectory(), 'start_up_trace_events.json');
final File traceEventsFile = globals.fs.file(traceEventsFilePath);
final List<Map<String, dynamic>> events =
List<Map<String, dynamic>>.from((timeline['traceEvents'] as List<dynamic>).cast<Map<String, dynamic>>());
traceEventsFile.writeAsStringSync(toPrettyJson(events));
}
path/to/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
public FlutterEngine(
Context context,
FlutterLoader flutterLoader,
FlutterJNI flutterJNI,
PlatformViewsController platformViewsController,
String[] dartVmArgs,
boolean automaticallyRegisterPlugins) {
......
}
new FlutterEngine(mPlatform.getApplication().getApplicationContext(),
FlutterLoader.getInstance(),new FlutterJNI(),new String[]{"--trace-startup"},true);
path/to/engine/src/flutter/shell/platform/darwin/common/command_line.mm
fml::CommandLine CommandLineFromNSProcessInfo() {
std::vector<std::string> args_vector;
for (NSString* arg in [NSProcessInfo processInfo].arguments) {
args_vector.emplace_back(arg.UTF8String);
}
return fml::CommandLineFromIterators(args_vector.begin(), args_vector.end());
}
path/to/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm
- (instancetype)initWithDartVmArgs:(nullable NSArray<NSString*>*)args {
return [self initWithPrecompiledDartBundle:nil dartVmArgs:args];
}
_dartProject = [[FlutterDartProject alloc] initWithPrecompiledDartBundle:dartBundle dartVmArgs:@[@"--trace-startup"]];
_engine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:_dartProject allowHeadlessExecution:YES];
path/to/flutter/packages/flutter/lib/src/rendering/debug.dart
bool debugProfilePaintsEnabled = false;
path/to/flutter/packages/flutter/lib/src/widgets/debug.dart
bool debugProfileBuildsEnabled = false;
std::unique_ptr<IOSContext> IOSContext::Create(IOSRenderingAPI rendering_api) {
TRACE_EVENT0("flutter", "IOSContext::Create");
......
FML_CHECK(false);
return nullptr;
}
[The Trace Event Profiling Tool]
https://www.chromium.org/developers/how-tos/trace-event-profiling-tool