mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 16:00:45 +00:00
[vm] On Fuchsia, enable timeline streams based on the state of system trace categories.
Allows categories to be selected through arguments to `trace` instead of changing VM flags and rebuilding. Change-Id: Ia1ec6b58ca0b765c3d675b7d4938acc5f624b768 Reviewed-on: https://dart-review.googlesource.com/c/91860 Reviewed-by: Zach Anderson <zra@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
644026da51
commit
dc555eb9a7
|
@ -221,6 +221,12 @@ library_for_all_configs("libdart") {
|
|||
"third_party/double-conversion/src:libdouble_conversion",
|
||||
":generate_version_cc_file",
|
||||
]
|
||||
if (is_fuchsia) {
|
||||
extra_deps += [
|
||||
"//zircon/public/lib/fbl",
|
||||
"//zircon/public/lib/trace-engine",
|
||||
]
|
||||
}
|
||||
configurable_deps = [
|
||||
"platform:libdart_platform",
|
||||
"vm:libdart_lib",
|
||||
|
|
|
@ -67,8 +67,6 @@ library_for_all_configs("libdart_vm") {
|
|||
"//garnet/public/lib/component/cpp",
|
||||
"//sdk/fidl/fuchsia.timezone",
|
||||
|
||||
# TODO(zra): When the platform-specific timeline code is moved out to
|
||||
# the embedder, this can go away.
|
||||
"//zircon/public/lib/fbl",
|
||||
"//zircon/public/lib/trace-engine",
|
||||
]
|
||||
|
@ -85,6 +83,12 @@ library_for_all_configs("libdart_vm") {
|
|||
|
||||
library_for_all_configs("libdart_lib") {
|
||||
target_type = "source_set"
|
||||
if (is_fuchsia) {
|
||||
extra_deps = [
|
||||
"//zircon/public/lib/fbl",
|
||||
"//zircon/public/lib/trace-engine",
|
||||
]
|
||||
}
|
||||
include_dirs = [ ".." ]
|
||||
allsources =
|
||||
async_runtime_sources + collection_runtime_sources +
|
||||
|
|
|
@ -205,8 +205,8 @@ void Timeline::Init() {
|
|||
ASSERT(recorder_ != NULL);
|
||||
enabled_streams_ = GetEnabledByDefaultTimelineStreams();
|
||||
// Global overrides.
|
||||
#define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
|
||||
stream_##name##_.Init(#name, HasStream(enabled_streams_, #name));
|
||||
#define TIMELINE_STREAM_FLAG_DEFAULT(name, fuchsia_name) \
|
||||
stream_##name##_.set_enabled(HasStream(enabled_streams_, #name));
|
||||
TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT)
|
||||
#undef TIMELINE_STREAM_FLAG_DEFAULT
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ void Timeline::Cleanup() {
|
|||
#endif
|
||||
|
||||
// Disable global streams.
|
||||
#define TIMELINE_STREAM_DISABLE(name, not_used) \
|
||||
#define TIMELINE_STREAM_DISABLE(name, fuchsia_name) \
|
||||
Timeline::stream_##name##_.set_enabled(false);
|
||||
TIMELINE_STREAM_LIST(TIMELINE_STREAM_DISABLE)
|
||||
#undef TIMELINE_STREAM_DISABLE
|
||||
|
@ -270,13 +270,13 @@ void Timeline::PrintFlagsToJSON(JSONStream* js) {
|
|||
}
|
||||
{
|
||||
JSONArray availableStreams(&obj, "availableStreams");
|
||||
#define ADD_STREAM_NAME(name, not_used) availableStreams.AddValue(#name);
|
||||
#define ADD_STREAM_NAME(name, fuchsia_name) availableStreams.AddValue(#name);
|
||||
TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
|
||||
#undef ADD_STREAM_NAME
|
||||
}
|
||||
{
|
||||
JSONArray recordedStreams(&obj, "recordedStreams");
|
||||
#define ADD_RECORDED_STREAM_NAME(name, not_used) \
|
||||
#define ADD_RECORDED_STREAM_NAME(name, fuchsia_name) \
|
||||
if (stream_##name##_.enabled()) { \
|
||||
recordedStreams.AddValue(#name); \
|
||||
}
|
||||
|
@ -377,8 +377,8 @@ void TimelineEventArguments::Free() {
|
|||
TimelineEventRecorder* Timeline::recorder_ = NULL;
|
||||
MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
|
||||
|
||||
#define TIMELINE_STREAM_DEFINE(name, enabled_by_default) \
|
||||
TimelineStream Timeline::stream_##name##_;
|
||||
#define TIMELINE_STREAM_DEFINE(name, fuchsia_name) \
|
||||
TimelineStream Timeline::stream_##name##_(#name, fuchsia_name, false);
|
||||
TIMELINE_STREAM_LIST(TIMELINE_STREAM_DEFINE)
|
||||
#undef TIMELINE_STREAM_DEFINE
|
||||
|
||||
|
@ -389,7 +389,7 @@ TimelineEvent::TimelineEvent()
|
|||
thread_timestamp1_(-1),
|
||||
state_(0),
|
||||
label_(NULL),
|
||||
category_(""),
|
||||
stream_(NULL),
|
||||
thread_(OSThread::kInvalidThreadId),
|
||||
isolate_id_(ILLEGAL_PORT) {}
|
||||
|
||||
|
@ -404,7 +404,7 @@ void TimelineEvent::Reset() {
|
|||
state_ = 0;
|
||||
thread_ = OSThread::kInvalidThreadId;
|
||||
isolate_id_ = ILLEGAL_PORT;
|
||||
category_ = "";
|
||||
stream_ = NULL;
|
||||
label_ = NULL;
|
||||
arguments_.Free();
|
||||
set_event_type(kNone);
|
||||
|
@ -546,14 +546,6 @@ void TimelineEvent::Complete() {
|
|||
}
|
||||
}
|
||||
|
||||
void TimelineEvent::StreamInit(TimelineStream* stream) {
|
||||
if (stream != NULL) {
|
||||
category_ = stream->name();
|
||||
} else {
|
||||
category_ = "";
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineEvent::Init(EventType event_type, const char* label) {
|
||||
ASSERT(label != NULL);
|
||||
state_ = 0;
|
||||
|
@ -607,7 +599,7 @@ void TimelineEvent::PrintJSON(JSONStream* stream) const {
|
|||
int64_t pid = OS::ProcessId();
|
||||
int64_t tid = OSThread::ThreadIdToIntPtr(thread_);
|
||||
obj.AddProperty("name", label_);
|
||||
obj.AddProperty("cat", category_);
|
||||
obj.AddProperty("cat", stream_ != NULL ? stream_->name() : NULL);
|
||||
obj.AddProperty64("tid", tid);
|
||||
obj.AddProperty64("pid", pid);
|
||||
obj.AddPropertyTimeMicros("ts", TimeOrigin());
|
||||
|
@ -738,11 +730,16 @@ int64_t TimelineEvent::ThreadCPUTimeDuration() const {
|
|||
return thread_timestamp1_ - thread_timestamp0_;
|
||||
}
|
||||
|
||||
TimelineStream::TimelineStream() : name_(NULL), enabled_(false) {}
|
||||
|
||||
void TimelineStream::Init(const char* name, bool enabled) {
|
||||
name_ = name;
|
||||
enabled_ = enabled;
|
||||
TimelineStream::TimelineStream(const char* name,
|
||||
const char* fuchsia_name,
|
||||
bool enabled)
|
||||
: name_(name),
|
||||
fuchsia_name_(fuchsia_name),
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
enabled_(true) { // For generated code.
|
||||
#else
|
||||
enabled_(enabled) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TimelineEvent* TimelineStream::StartEvent() {
|
||||
|
@ -1111,10 +1108,13 @@ void TimelineEventRecorder::WriteTo(const char* directory) {
|
|||
|
||||
int64_t TimelineEventRecorder::GetNextAsyncId() {
|
||||
// TODO(johnmccutchan): Gracefully handle wrap around.
|
||||
// TODO(rmacnak): Use TRACE_NONCE() on Fuchsia?
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
return trace_generate_nonce();
|
||||
#else
|
||||
uint32_t next =
|
||||
static_cast<uint32_t>(AtomicOperations::FetchAndIncrement(&async_id_));
|
||||
return static_cast<int64_t>(next);
|
||||
#endif
|
||||
}
|
||||
|
||||
void TimelineEventRecorder::FinishBlock(TimelineEventBlock* block) {
|
||||
|
|
|
@ -9,10 +9,16 @@
|
|||
|
||||
#include "vm/allocation.h"
|
||||
#include "vm/bitfield.h"
|
||||
#include "vm/globals.h"
|
||||
#include "vm/growable_array.h"
|
||||
#include "vm/os.h"
|
||||
#include "vm/os_thread.h"
|
||||
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
#include <trace-engine/context.h>
|
||||
#include <trace-engine/instrumentation.h>
|
||||
#endif
|
||||
|
||||
namespace dart {
|
||||
|
||||
class JSONArray;
|
||||
|
@ -30,29 +36,34 @@ class TimelineStream;
|
|||
class VirtualMemory;
|
||||
class Zone;
|
||||
|
||||
// (name, enabled by default for isolate).
|
||||
// (name, fuchsia_name).
|
||||
#define TIMELINE_STREAM_LIST(V) \
|
||||
V(API, false) \
|
||||
V(Compiler, false) \
|
||||
V(CompilerVerbose, false) \
|
||||
V(Dart, false) \
|
||||
V(Debugger, false) \
|
||||
V(Embedder, false) \
|
||||
V(GC, false) \
|
||||
V(Isolate, false) \
|
||||
V(VM, false)
|
||||
V(API, "dart:api") \
|
||||
V(Compiler, "dart:compiler") \
|
||||
V(CompilerVerbose, "dart:compiler.verbose") \
|
||||
V(Dart, "dart:dart") \
|
||||
V(Debugger, "dart:debugger") \
|
||||
V(Embedder, "dart:embedder") \
|
||||
V(GC, "dart:gc") \
|
||||
V(Isolate, "dart:isolate") \
|
||||
V(VM, "dart:vm")
|
||||
|
||||
// A stream of timeline events. A stream has a name and can be enabled or
|
||||
// disabled (globally and per isolate).
|
||||
class TimelineStream {
|
||||
public:
|
||||
TimelineStream();
|
||||
|
||||
void Init(const char* name, bool enabled);
|
||||
TimelineStream(const char* name, const char* fuchsia_name, bool enabled);
|
||||
|
||||
const char* name() const { return name_; }
|
||||
const char* fuchsia_name() const { return fuchsia_name_; }
|
||||
|
||||
bool enabled() const { return enabled_ != 0; }
|
||||
bool enabled() {
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
return trace_is_category_enabled(fuchsia_name_);
|
||||
#else
|
||||
return enabled_ != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; }
|
||||
|
||||
|
@ -66,12 +77,21 @@ class TimelineStream {
|
|||
return OFFSET_OF(TimelineStream, enabled_);
|
||||
}
|
||||
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
trace_site_t* trace_site() { return &trace_site_; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
const char* name_;
|
||||
const char* const name_;
|
||||
const char* const fuchsia_name_;
|
||||
|
||||
// This field is accessed by generated code (intrinsic) and expects to see
|
||||
// 0 or 1. If this becomes a BitField, the generated code must be updated.
|
||||
uintptr_t enabled_;
|
||||
|
||||
#if defined(HOST_OS_FUCHSIA)
|
||||
trace_site_t trace_site_ = {};
|
||||
#endif
|
||||
};
|
||||
|
||||
class Timeline : public AllStatic {
|
||||
|
@ -95,12 +115,12 @@ class Timeline : public AllStatic {
|
|||
static void PrintFlagsToJSON(JSONStream* json);
|
||||
#endif
|
||||
|
||||
#define TIMELINE_STREAM_ACCESSOR(name, not_used) \
|
||||
#define TIMELINE_STREAM_ACCESSOR(name, fuchsia_name) \
|
||||
static TimelineStream* Get##name##Stream() { return &stream_##name##_; }
|
||||
TIMELINE_STREAM_LIST(TIMELINE_STREAM_ACCESSOR)
|
||||
#undef TIMELINE_STREAM_ACCESSOR
|
||||
|
||||
#define TIMELINE_STREAM_FLAGS(name, not_used) \
|
||||
#define TIMELINE_STREAM_FLAGS(name, fuchsia_name) \
|
||||
static void SetStream##name##Enabled(bool enabled) { \
|
||||
stream_##name##_.set_enabled(enabled); \
|
||||
}
|
||||
|
@ -111,8 +131,7 @@ class Timeline : public AllStatic {
|
|||
static TimelineEventRecorder* recorder_;
|
||||
static MallocGrowableArray<char*>* enabled_streams_;
|
||||
|
||||
#define TIMELINE_STREAM_DECLARE(name, not_used) \
|
||||
static bool stream_##name##_enabled_; \
|
||||
#define TIMELINE_STREAM_DECLARE(name, fuchsia_name) \
|
||||
static TimelineStream stream_##name##_;
|
||||
TIMELINE_STREAM_LIST(TIMELINE_STREAM_DECLARE)
|
||||
#undef TIMELINE_STREAM_DECLARE
|
||||
|
@ -358,7 +377,7 @@ class TimelineEvent {
|
|||
intptr_t arguments_length() const { return arguments_.length(); }
|
||||
|
||||
private:
|
||||
void StreamInit(TimelineStream* stream);
|
||||
void StreamInit(TimelineStream* stream) { stream_ = stream; }
|
||||
void Init(EventType event_type, const char* label);
|
||||
|
||||
void set_event_type(EventType event_type) {
|
||||
|
@ -415,7 +434,7 @@ class TimelineEvent {
|
|||
TimelineEventArguments arguments_;
|
||||
uword state_;
|
||||
const char* label_;
|
||||
const char* category_;
|
||||
TimelineStream* stream_;
|
||||
ThreadId thread_;
|
||||
Dart_Port isolate_id_;
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ void TimelineEventFuchsiaRecorder::OnEvent(TimelineEvent* event) {
|
|||
if (event == NULL) {
|
||||
return;
|
||||
}
|
||||
TimelineStream* stream = event->stream_;
|
||||
trace_string_ref_t category;
|
||||
trace_context_t* context =
|
||||
trace_acquire_context_for_category("dart", &category);
|
||||
trace_context_t* context = trace_acquire_context_for_category_cached(
|
||||
stream->fuchsia_name(), stream->trace_site(), &category);
|
||||
if (context == NULL) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -100,8 +100,7 @@ class TimelineTestHelper : public AllStatic {
|
|||
|
||||
TEST_CASE(TimelineEventIsValid) {
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
TimelineEvent event;
|
||||
TimelineTestHelper::SetStream(&event, &stream);
|
||||
|
@ -120,8 +119,7 @@ TEST_CASE(TimelineEventIsValid) {
|
|||
|
||||
TEST_CASE(TimelineEventDuration) {
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
// Create a test event.
|
||||
TimelineEvent event;
|
||||
|
@ -136,8 +134,7 @@ TEST_CASE(TimelineEventDuration) {
|
|||
|
||||
TEST_CASE(TimelineEventDurationPrintJSON) {
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
// Create a test event.
|
||||
TimelineEvent event;
|
||||
|
@ -167,8 +164,7 @@ TEST_CASE(TimelineEventPrintSystrace) {
|
|||
char buffer[kBufferLength];
|
||||
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
// Create a test event.
|
||||
TimelineEvent event;
|
||||
|
@ -212,8 +208,7 @@ TEST_CASE(TimelineEventPrintSystrace) {
|
|||
|
||||
TEST_CASE(TimelineEventArguments) {
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
// Create a test event.
|
||||
TimelineEvent event;
|
||||
|
@ -233,8 +228,7 @@ TEST_CASE(TimelineEventArguments) {
|
|||
|
||||
TEST_CASE(TimelineEventArgumentsPrintJSON) {
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
// Create a test event.
|
||||
TimelineEvent event;
|
||||
|
@ -296,8 +290,7 @@ TEST_CASE(TimelineEventCallbackRecorderBasic) {
|
|||
}
|
||||
|
||||
// Create a test stream.
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
TimelineEvent* event = NULL;
|
||||
|
||||
|
@ -468,8 +461,7 @@ TEST_CASE(TimelineAnalysis_ThreadBlockCount) {
|
|||
}
|
||||
|
||||
TEST_CASE(TimelineRingRecorderJSONOrder) {
|
||||
TimelineStream stream;
|
||||
stream.Init("testStream", true);
|
||||
TimelineStream stream("testStream", "testStream", true);
|
||||
|
||||
TimelineEventRingRecorder* recorder =
|
||||
new TimelineEventRingRecorder(TimelineEventBlock::kBlockSize * 2);
|
||||
|
|
Loading…
Reference in a new issue