mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
* Namespaces have been updated to reflect the move from //flutter/sky/shell to //flutter/shell. * shell/BUILD.gn file has been split into smaller GN files for each subcomponent of the shell (common, GPU, diagnostic, testing). * GN dependencies have been rewritten to stop exposing common shell dependencies as public. Duplicates have also been removed. * GPU subcomponent has been updated make it more suitable for Vulkan integration. * The GLFW backend has been resurrected.
213 lines
6.7 KiB
C++
213 lines
6.7 KiB
C++
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/shell/common/tracing_controller.h"
|
|
|
|
#include <string>
|
|
|
|
#include "base/trace_event/trace_event.h"
|
|
#include "dart/runtime/include/dart_tools_api.h"
|
|
#include "flutter/common/threads.h"
|
|
#include "flutter/runtime/dart_init.h"
|
|
#include "flutter/shell/common/shell.h"
|
|
#include "lib/ftl/logging.h"
|
|
|
|
namespace shell {
|
|
|
|
TracingController::TracingController()
|
|
: picture_tracing_enabled_(false), tracing_active_(false) {
|
|
blink::SetEmbedderTracingCallbacks(
|
|
std::unique_ptr<blink::EmbedderTracingCallbacks>(
|
|
new blink::EmbedderTracingCallbacks([this]() { StartTracing(); },
|
|
[this]() { StopTracing(); })));
|
|
}
|
|
|
|
TracingController::~TracingController() {
|
|
blink::SetEmbedderTracingCallbacks(nullptr);
|
|
}
|
|
|
|
static const char* WARN_UNUSED_RESULT
|
|
ConstructDartTimelineValue(std::vector<void*>& free_list,
|
|
const char* format,
|
|
...) {
|
|
static const char* kConversionError = "Argument Conversion Error";
|
|
const char* return_value = nullptr;
|
|
|
|
va_list args;
|
|
va_start(args, format);
|
|
char* string;
|
|
if (vasprintf(&string, format, args) != -1) {
|
|
return_value = string;
|
|
free_list.push_back(string);
|
|
} else {
|
|
return_value = kConversionError;
|
|
}
|
|
va_end(args);
|
|
|
|
return return_value;
|
|
}
|
|
|
|
static void BaseTraceEventCallback(base::TraceTicks timestamp,
|
|
char phase,
|
|
const unsigned char* category_group_enabled,
|
|
const char* name,
|
|
unsigned long long id,
|
|
int num_args,
|
|
const char* const arg_names[],
|
|
const unsigned char arg_types[],
|
|
const unsigned long long arg_values[],
|
|
unsigned int flags) {
|
|
Dart_Timeline_Event_Type type = Dart_Timeline_Event_Begin;
|
|
|
|
switch (phase) {
|
|
case TRACE_EVENT_PHASE_BEGIN:
|
|
type = Dart_Timeline_Event_Begin;
|
|
break;
|
|
case TRACE_EVENT_PHASE_END:
|
|
type = Dart_Timeline_Event_End;
|
|
break;
|
|
case TRACE_EVENT_PHASE_INSTANT:
|
|
type = Dart_Timeline_Event_Instant;
|
|
break;
|
|
case TRACE_EVENT_PHASE_ASYNC_BEGIN:
|
|
type = Dart_Timeline_Event_Async_Begin;
|
|
break;
|
|
case TRACE_EVENT_PHASE_ASYNC_END:
|
|
type = Dart_Timeline_Event_Async_End;
|
|
break;
|
|
case TRACE_EVENT_PHASE_COUNTER:
|
|
type = Dart_Timeline_Event_Counter;
|
|
break;
|
|
default:
|
|
// For TRACE_EVENT_PHASE_COMPLETE events, this callback still receives
|
|
// discrete begin-end pairs. This greatly simplifies things. We dont have
|
|
// to track the second timestamp to pass to the Dart timeline event
|
|
// because we never see a Dart_Timeline_Event_Duration event.
|
|
FTL_DCHECK(false) << "Unknown trace event phase";
|
|
return;
|
|
}
|
|
|
|
// Try to convert all arguments to strings to pass to the Dart timeline.
|
|
|
|
char const* dart_argument_values[num_args];
|
|
|
|
std::vector<void*> free_list;
|
|
|
|
#define CONVERT_VAL(format) \
|
|
dart_argument_values[i] = \
|
|
ConstructDartTimelineValue(free_list, format, arg_values[i])
|
|
|
|
for (int i = 0; i < num_args; i++) {
|
|
switch (arg_types[i]) {
|
|
case TRACE_VALUE_TYPE_BOOL:
|
|
CONVERT_VAL("%d");
|
|
break;
|
|
case TRACE_VALUE_TYPE_UINT:
|
|
CONVERT_VAL("%u");
|
|
break;
|
|
case TRACE_VALUE_TYPE_INT:
|
|
CONVERT_VAL("%d");
|
|
break;
|
|
case TRACE_VALUE_TYPE_DOUBLE:
|
|
CONVERT_VAL("%f");
|
|
break;
|
|
case TRACE_VALUE_TYPE_POINTER:
|
|
CONVERT_VAL("%p");
|
|
break;
|
|
case TRACE_VALUE_TYPE_STRING:
|
|
case TRACE_VALUE_TYPE_COPY_STRING:
|
|
// We don't need to reallocate for strings since the string will be
|
|
// used within this scope.
|
|
dart_argument_values[i] = reinterpret_cast<char*>(arg_values[i]);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
|
|
#undef CONVERT_VAL
|
|
|
|
Dart_TimelineEvent(name, // label
|
|
timestamp.ToInternalValue(), // timestamp0
|
|
0, // timestamp1_or_async_id
|
|
type, // event type
|
|
num_args, // argument_count
|
|
(const char**)(arg_names), // argument_names
|
|
(const char**)(dart_argument_values) // argument_values
|
|
);
|
|
|
|
// Free up the items that had to be heap allocated (if any)
|
|
for (void* item : free_list) {
|
|
free(item);
|
|
}
|
|
}
|
|
|
|
static void AddTraceMetadata() {
|
|
blink::Threads::Gpu()->PostTask([]() { Dart_SetThreadName("gpu_thread"); });
|
|
blink::Threads::UI()->PostTask([]() { Dart_SetThreadName("ui_thread"); });
|
|
blink::Threads::IO()->PostTask([]() { Dart_SetThreadName("io_thread"); });
|
|
}
|
|
|
|
void TracingController::StartTracing() {
|
|
if (tracing_active_)
|
|
return;
|
|
tracing_active_ = true;
|
|
StartBaseTracing();
|
|
AddTraceMetadata();
|
|
}
|
|
|
|
void TracingController::StartBaseTracing() {
|
|
auto config = base::trace_event::TraceConfig(
|
|
"*,disabled-by-default-skia", base::trace_event::RECORD_CONTINUOUSLY);
|
|
|
|
auto log = base::trace_event::TraceLog::GetInstance();
|
|
|
|
log->SetEnabled(config, base::trace_event::TraceLog::MONITORING_MODE);
|
|
log->SetEventCallbackEnabled(config, &BaseTraceEventCallback);
|
|
}
|
|
|
|
void TracingController::StopTracing() {
|
|
if (!tracing_active_) {
|
|
return;
|
|
}
|
|
|
|
tracing_active_ = false;
|
|
|
|
StopBaseTracing();
|
|
}
|
|
|
|
void TracingController::StopBaseTracing() {
|
|
auto trace_log = base::trace_event::TraceLog::GetInstance();
|
|
trace_log->SetDisabled();
|
|
trace_log->SetEventCallbackDisabled();
|
|
}
|
|
|
|
std::string TracingController::TracePathWithExtension(
|
|
const std::string& directory,
|
|
const std::string& extension) const {
|
|
base::Time::Exploded exploded;
|
|
base::Time now = base::Time::Now();
|
|
|
|
now.LocalExplode(&exploded);
|
|
|
|
std::stringstream stream;
|
|
// Example: trace_2015-10-08_at_11.38.25.121_.extension
|
|
stream << directory << "/trace_" << exploded.year << "-" << exploded.month
|
|
<< "-" << exploded.day_of_month << "_at_" << exploded.hour << "."
|
|
<< exploded.minute << "." << exploded.second << "."
|
|
<< exploded.millisecond << "." << extension;
|
|
return stream.str();
|
|
}
|
|
|
|
std::string TracingController::PictureTracingPathForCurrentTime() const {
|
|
return PictureTracingPathForCurrentTime(traces_base_path_);
|
|
}
|
|
|
|
std::string TracingController::PictureTracingPathForCurrentTime(
|
|
const std::string& directory) const {
|
|
return TracePathWithExtension(directory, "skp");
|
|
}
|
|
|
|
} // namespace shell
|