Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(446)

Side by Side Diff: runtime/vm/timeline.cc

Issue 1690333002: Add fine grained command line and service protocol control over timeline streams recording (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/timeline.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <cstdlib> 5 #include <cstdlib>
6 6
7 #include "vm/atomic.h" 7 #include "vm/atomic.h"
8 #include "vm/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/json_stream.h" 9 #include "vm/json_stream.h"
10 #include "vm/lockers.h" 10 #include "vm/lockers.h"
11 #include "vm/log.h" 11 #include "vm/log.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/thread.h" 13 #include "vm/thread.h"
14 #include "vm/timeline.h" 14 #include "vm/timeline.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 #ifndef PRODUCT 18 #ifndef PRODUCT
19 19
20 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline"); 20 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
21 DEFINE_FLAG(bool, trace_timeline, false, 21 DEFINE_FLAG(bool, trace_timeline, false,
22 "Trace timeline backend"); 22 "Trace timeline backend");
23 DEFINE_FLAG(bool, trace_timeline_analysis, false, 23 DEFINE_FLAG(bool, trace_timeline_analysis, false,
24 "Trace timeline analysis backend"); 24 "Trace timeline analysis backend");
25 DEFINE_FLAG(bool, timing, false, 25 DEFINE_FLAG(bool, timing, false,
26 "Dump isolate timing information from timeline."); 26 "Dump isolate timing information from timeline.");
27 DEFINE_FLAG(charp, timeline_dir, NULL, 27 DEFINE_FLAG(charp, timeline_dir, NULL,
28 "Enable all timeline trace streams and output VM global trace " 28 "Enable all timeline trace streams and output VM global trace "
29 "into specified directory."); 29 "into specified directory.");
30 DEFINE_FLAG(charp, timeline_streams, NULL,
31 "Comma separated list of timeline streams to record. "
32 "Valid values: all, api, compiler, dart, debugger, embedder, "
33 "gc, isolate, and vm.");
30 34
31 // Implementation notes: 35 // Implementation notes:
32 // 36 //
33 // Writing events: 37 // Writing events:
34 // |TimelineEvent|s are written into |TimelineEventBlock|s. Each |Thread| caches 38 // |TimelineEvent|s are written into |TimelineEventBlock|s. Each |Thread| caches
35 // a |TimelineEventBlock| object so that it can write events without 39 // a |TimelineEventBlock| object so that it can write events without
36 // synchronizing with other threads in the system. Even though the |Thread| owns 40 // synchronizing with other threads in the system. Even though the |Thread| owns
37 // the |TimelineEventBlock| the block may need to be reclaimed by the reporting 41 // the |TimelineEventBlock| the block may need to be reclaimed by the reporting
38 // system. To support that, a |Thread| must hold its |timeline_block_lock_| 42 // system. To support that, a |Thread| must hold its |timeline_block_lock_|
39 // when operating on the |TimelineEventBlock|. This lock will only ever be 43 // when operating on the |TimelineEventBlock|. This lock will only ever be
(...skipping 23 matching lines...) Expand all
63 // cached block is being operated on. 67 // cached block is being operated on.
64 // - |Thread::thread_list_lock_| This lock is held when iterating over 68 // - |Thread::thread_list_lock_| This lock is held when iterating over
65 // |Thread|s. 69 // |Thread|s.
66 // 70 //
67 // Locks must always be taken in the following order: 71 // Locks must always be taken in the following order:
68 // |Thread::thread_list_lock_| 72 // |Thread::thread_list_lock_|
69 // |Thread::timeline_block_lock_| 73 // |Thread::timeline_block_lock_|
70 // |TimelineEventRecorder::lock_| 74 // |TimelineEventRecorder::lock_|
71 // 75 //
72 76
77
78 // Returns a caller freed array of stream names in FLAG_timeline_streams.
79 static MallocGrowableArray<char*>* GetEnabledByDefaultTimelineStreams() {
80 MallocGrowableArray<char*>* result = new MallocGrowableArray<char*>();
81 if (FLAG_timeline_streams == NULL) {
82 // Nothing set.
83 return result;
84 }
85 char* save_ptr; // Needed for strtok_r.
86 // strtok modifies arg 1 so we make a copy of it.
87 char* streams = strdup(FLAG_timeline_streams);
88 char* token = strtok_r(streams, ",", &save_ptr);
89 while (token != NULL) {
90 result->Add(strdup(token));
91 token = strtok_r(NULL, ",", &save_ptr);
92 }
93 free(streams);
94 return result;
95 }
96
97
98 // Frees the result of |GetEnabledByDefaultTimelineStreams|.
99 static void FreeEnabledByDefaultTimelineStreams(
100 MallocGrowableArray<char*>* streams) {
101 if (streams == NULL) {
102 return;
103 }
104 for (intptr_t i = 0; i < streams->length(); i++) {
105 free((*streams)[i]);
106 }
107 delete streams;
108 }
109
110
111 // Returns true if |streams| contains |stream| or "all". Not case sensitive.
112 static bool HasStream(MallocGrowableArray<char*>* streams, const char* stream) {
113 if ((FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline) {
114 return true;
115 }
116 for (intptr_t i = 0; i < streams->length(); i++) {
117 const char* checked_stream = (*streams)[i];
118 if ((strcasestr(checked_stream, "all") != NULL) ||
119 (strcasestr(checked_stream, stream) != NULL)) {
120 return true;
121 }
122 }
123 return false;
124 }
125
126
73 void Timeline::InitOnce() { 127 void Timeline::InitOnce() {
74 ASSERT(recorder_ == NULL); 128 ASSERT(recorder_ == NULL);
75 // Default to ring recorder being enabled. 129 // Default to ring recorder being enabled.
76 const bool use_ring_recorder = true; 130 const bool use_ring_recorder = true;
77 // Some flags require that we use the endless recorder. 131 // Some flags require that we use the endless recorder.
78 const bool use_endless_recorder = 132 const bool use_endless_recorder =
79 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline; 133 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
80 if (use_endless_recorder) { 134 if (use_endless_recorder) {
81 recorder_ = new TimelineEventEndlessRecorder(); 135 recorder_ = new TimelineEventEndlessRecorder();
82 } else if (use_ring_recorder) { 136 } else if (use_ring_recorder) {
83 recorder_ = new TimelineEventRingRecorder(); 137 recorder_ = new TimelineEventRingRecorder();
84 } 138 }
85 vm_stream_.Init("VM", EnableStreamByDefault("VM"), NULL); 139 enabled_streams_ = GetEnabledByDefaultTimelineStreams();
140 vm_stream_.Init("VM", HasStream(enabled_streams_, "VM"), NULL);
86 vm_api_stream_.Init("API", 141 vm_api_stream_.Init("API",
87 EnableStreamByDefault("API"), 142 HasStream(enabled_streams_, "API"),
88 &stream_API_enabled_); 143 &stream_API_enabled_);
89 // Global overrides. 144 // Global overrides.
90 #define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \ 145 #define ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
91 stream_##name##_enabled_ = EnableStreamByDefault(#name); 146 stream_##name##_enabled_ = HasStream(enabled_streams_, #name);
92 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT) 147 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT)
93 #undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT 148 #undef ISOLATE_TIMELINE_STREAM_FLAG_DEFAULT
94 } 149 }
95 150
96 151
152 void Timeline::SetVMStreamEnabled(bool enabled) {
153 vm_stream_.set_enabled(enabled);
154 }
155
156
97 void Timeline::Shutdown() { 157 void Timeline::Shutdown() {
98 ASSERT(recorder_ != NULL); 158 ASSERT(recorder_ != NULL);
99 if (FLAG_timeline_dir != NULL) { 159 if (FLAG_timeline_dir != NULL) {
100 recorder_->WriteTo(FLAG_timeline_dir); 160 recorder_->WriteTo(FLAG_timeline_dir);
101 } 161 }
102 // Disable global streams. 162 // Disable global streams.
103 vm_stream_.set_enabled(false); 163 vm_stream_.set_enabled(false);
104 vm_api_stream_.set_enabled(false); 164 vm_api_stream_.set_enabled(false);
105 #define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used) \ 165 #define ISOLATE_TIMELINE_STREAM_DISABLE(name, not_used) \
106 stream_##name##_enabled_ = false; 166 stream_##name##_enabled_ = false;
107 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE) 167 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DISABLE)
108 #undef ISOLATE_TIMELINE_STREAM_DISABLE 168 #undef ISOLATE_TIMELINE_STREAM_DISABLE
109 delete recorder_; 169 delete recorder_;
110 recorder_ = NULL; 170 recorder_ = NULL;
171 if (enabled_streams_ != NULL) {
172 FreeEnabledByDefaultTimelineStreams(enabled_streams_);
173 enabled_streams_ = NULL;
174 }
111 } 175 }
112 176
113 177
114 TimelineEventRecorder* Timeline::recorder() { 178 TimelineEventRecorder* Timeline::recorder() {
115 return recorder_; 179 return recorder_;
116 } 180 }
117 181
118 182
119 bool Timeline::EnableStreamByDefault(const char* stream_name) { 183 void Timeline::SetupIsolateStreams(Isolate* isolate) {
120 // TODO(johnmccutchan): Allow for command line control over streams. 184 #define ISOLATE_TIMELINE_STREAM_INIT(name, enabled_by_default) \
121 return (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline; 185 isolate->Get##name##Stream()->Init( \
186 #name, \
187 (enabled_by_default || HasStream(enabled_streams_, #name)), \
188 Timeline::Stream##name##EnabledFlag());
189 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_INIT);
190 #undef ISOLATE_TIMELINE_STREAM_INIT
122 } 191 }
123 192
124 193
125 TimelineStream* Timeline::GetVMStream() { 194 TimelineStream* Timeline::GetVMStream() {
126 return &vm_stream_; 195 return &vm_stream_;
127 } 196 }
128 197
129 198
130 TimelineStream* Timeline::GetVMApiStream() { 199 TimelineStream* Timeline::GetVMApiStream() {
131 return &vm_api_stream_; 200 return &vm_api_stream_;
(...skipping 15 matching lines...) Expand all
147 TimelineEventBlock* block = thread->timeline_block(); 216 TimelineEventBlock* block = thread->timeline_block();
148 thread->set_timeline_block(NULL); 217 thread->set_timeline_block(NULL);
149 // TODO(johnmccutchan): Consider dropping the timeline_block_lock here 218 // TODO(johnmccutchan): Consider dropping the timeline_block_lock here
150 // if we can do it everywhere. This would simplify the lock ordering 219 // if we can do it everywhere. This would simplify the lock ordering
151 // requirements. 220 // requirements.
152 recorder->FinishBlock(block); 221 recorder->FinishBlock(block);
153 } 222 }
154 } 223 }
155 224
156 225
226 void Timeline::PrintFlagsToJSON(JSONStream* js) {
227 JSONObject obj(js);
228 obj.AddProperty("type", "TimelineFlags");
229 TimelineEventRecorder* recorder = Timeline::recorder();
230 if (recorder == NULL) {
231 obj.AddProperty("recorderName", "null");
232 } else {
233 obj.AddProperty("recorderName", recorder->name());
234 }
235 {
236 JSONArray availableStreams(&obj, "availableStreams");
237 #define ADD_STREAM_NAME(name, not_used) \
238 availableStreams.AddValue(#name);
239 ISOLATE_TIMELINE_STREAM_LIST(ADD_STREAM_NAME);
240 #undef ADD_STREAM_NAME
241 availableStreams.AddValue("VM");
242 }
243 {
244 JSONArray recordedStreams(&obj, "recordedStreams");
245 #define ADD_RECORDED_STREAM_NAME(name, not_used) \
246 if (stream_##name##_enabled_) { \
247 recordedStreams.AddValue(#name); \
248 }
249 ISOLATE_TIMELINE_STREAM_LIST(ADD_RECORDED_STREAM_NAME);
250 #undef ADD_RECORDED_STREAM_NAME
251 if (vm_stream_.enabled()) {
252 recordedStreams.AddValue("VM");
253 }
254 }
255 }
256
257
157 void Timeline::Clear() { 258 void Timeline::Clear() {
158 TimelineEventRecorder* recorder = Timeline::recorder(); 259 TimelineEventRecorder* recorder = Timeline::recorder();
159 if (recorder == NULL) { 260 if (recorder == NULL) {
160 return; 261 return;
161 } 262 }
162 ReclaimCachedBlocksFromThreads(); 263 ReclaimCachedBlocksFromThreads();
163 recorder->Clear(); 264 recorder->Clear();
164 } 265 }
165 266
166 267
167 TimelineEventRecorder* Timeline::recorder_ = NULL; 268 TimelineEventRecorder* Timeline::recorder_ = NULL;
168 TimelineStream Timeline::vm_stream_; 269 TimelineStream Timeline::vm_stream_;
169 TimelineStream Timeline::vm_api_stream_; 270 TimelineStream Timeline::vm_api_stream_;
271 MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
170 272
171 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \ 273 #define ISOLATE_TIMELINE_STREAM_DEFINE_FLAG(name, enabled_by_default) \
172 bool Timeline::stream_##name##_enabled_ = enabled_by_default; 274 bool Timeline::stream_##name##_enabled_ = enabled_by_default;
173 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG) 275 ISOLATE_TIMELINE_STREAM_LIST(ISOLATE_TIMELINE_STREAM_DEFINE_FLAG)
174 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG 276 #undef ISOLATE_TIMELINE_STREAM_DEFINE_FLAG
175 277
176 TimelineEvent::TimelineEvent() 278 TimelineEvent::TimelineEvent()
177 : timestamp0_(0), 279 : timestamp0_(0),
178 timestamp1_(0), 280 timestamp1_(0),
179 arguments_(NULL), 281 arguments_(NULL),
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 TimelineEventBlock* TimelineEventBlockIterator::Next() { 1504 TimelineEventBlock* TimelineEventBlockIterator::Next() {
1403 ASSERT(current_ != NULL); 1505 ASSERT(current_ != NULL);
1404 TimelineEventBlock* r = current_; 1506 TimelineEventBlock* r = current_;
1405 current_ = current_->next(); 1507 current_ = current_->next();
1406 return r; 1508 return r;
1407 } 1509 }
1408 1510
1409 #endif // !PRODUCT 1511 #endif // !PRODUCT
1410 1512
1411 } // namespace dart 1513 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/timeline.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698