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

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

Issue 1294023009: Switch to a VM wide timeline recorder (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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
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/isolate.h" 8 #include "vm/isolate.h"
8 #include "vm/json_stream.h" 9 #include "vm/json_stream.h"
9 #include "vm/lockers.h" 10 #include "vm/lockers.h"
10 #include "vm/object.h" 11 #include "vm/object.h"
11 #include "vm/thread.h" 12 #include "vm/thread.h"
12 #include "vm/timeline.h" 13 #include "vm/timeline.h"
13 14
14 namespace dart { 15 namespace dart {
15 16
16 DEFINE_FLAG(bool, trace_timeline, false, "Trace timeline backend"); 17 DEFINE_FLAG(bool, trace_timeline, false, "Trace timeline backend");
17 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline"); 18 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
18 19
20 DEFINE_FLAG(charp, timeline_dir, NULL,
21 "Enable all timeline trace streams and output VM global trace "
22 "into specified directory.");
23
24 void Timeline::InitOnce() {
25 ASSERT(recorder_ == NULL);
26 // Default to ring recorder being enabled.
27 const bool use_ring_recorder = true;
28 // Some flags require that we use the endless recorder.
29 const bool use_endless_recorder = (FLAG_timeline_dir != NULL);
30 if (use_endless_recorder) {
31 recorder_ = new TimelineEventEndlessRecorder();
32 } else if (use_ring_recorder) {
33 recorder_ = new TimelineEventRingRecorder();
34 }
35 vm_stream_ = new TimelineStream();
36 vm_stream_->Init("VM", EnableStreamByDefault("VM"));
37 }
38
39
40 void Timeline::Shutdown() {
41 ASSERT(recorder_ != NULL);
42 if (FLAG_timeline_dir != NULL) {
43 recorder_->WriteTo(FLAG_timeline_dir);
44 }
45 delete recorder_;
46 recorder_ = NULL;
47 delete vm_stream_;
48 vm_stream_ = NULL;
49 }
50
51
52 TimelineEventRecorder* Timeline::recorder() {
53 return recorder_;
54 }
55
56
57 bool Timeline::EnableStreamByDefault(const char* stream_name) {
58 // TODO(johnmccutchan): Allow for command line control over streams.
59 return FLAG_timeline_dir != NULL;
60 }
61
62
63 TimelineStream* Timeline::GetVMStream() {
64 ASSERT(vm_stream_ != NULL);
65 return vm_stream_;
66 }
67
68
69 TimelineEventRecorder* Timeline::recorder_ = NULL;
70 TimelineStream* Timeline::vm_stream_ = NULL;
71
19 TimelineEvent::TimelineEvent() 72 TimelineEvent::TimelineEvent()
20 : timestamp0_(0), 73 : timestamp0_(0),
21 timestamp1_(0), 74 timestamp1_(0),
22 arguments_(NULL), 75 arguments_(NULL),
23 arguments_length_(0), 76 arguments_length_(0),
24 state_(0), 77 state_(0),
25 label_(NULL), 78 label_(NULL),
26 stream_(NULL), 79 category_(""),
27 thread_(OSThread::kInvalidThreadId) { 80 thread_(OSThread::kInvalidThreadId) {
28 } 81 }
29 82
30 83
31 TimelineEvent::~TimelineEvent() { 84 TimelineEvent::~TimelineEvent() {
32 Reset(); 85 Reset();
33 } 86 }
34 87
35 88
36 void TimelineEvent::Reset() { 89 void TimelineEvent::Reset() {
37 set_event_type(kNone); 90 set_event_type(kNone);
38 thread_ = OSThread::kInvalidThreadId; 91 thread_ = OSThread::kInvalidThreadId;
39 stream_ = NULL; 92 isolate_ = NULL;
93 category_ = "";
40 label_ = NULL; 94 label_ = NULL;
41 FreeArguments(); 95 FreeArguments();
42 } 96 }
43 97
44 98
45 int64_t TimelineEvent::AsyncBegin(const char* label) { 99 void TimelineEvent::AsyncBegin(const char* label, int64_t async_id) {
46 Init(kAsyncBegin, label); 100 Init(kAsyncBegin, label);
47 timestamp0_ = OS::GetCurrentTimeMicros(); 101 timestamp0_ = OS::GetCurrentTimeMicros();
48 ASSERT(stream_ != NULL);
49 int64_t async_id = stream_->GetNextSeq();
50 // Overload timestamp1_ with the async_id. 102 // Overload timestamp1_ with the async_id.
51 timestamp1_ = async_id; 103 timestamp1_ = static_cast<int64_t>(async_id);
rmacnak 2015/08/18 21:09:00 Unnecessary cast
Cutch 2015/08/18 21:50:18 Done.
52 return async_id;
53 } 104 }
54 105
55 106
56 void TimelineEvent::AsyncInstant(const char* label, 107 void TimelineEvent::AsyncInstant(const char* label,
57 int64_t async_id) { 108 int64_t async_id) {
58 Init(kAsyncInstant, label); 109 Init(kAsyncInstant, label);
59 timestamp0_ = OS::GetCurrentTimeMicros(); 110 timestamp0_ = OS::GetCurrentTimeMicros();
60 // Overload timestamp1_ with the async_id. 111 // Overload timestamp1_ with the async_id.
61 timestamp1_ = async_id; 112 timestamp1_ = static_cast<int64_t>(async_id);;
rmacnak 2015/08/18 21:09:00 "
Cutch 2015/08/18 21:50:18 Done.
62 } 113 }
63 114
64 115
65 void TimelineEvent::AsyncEnd(const char* label, 116 void TimelineEvent::AsyncEnd(const char* label,
66 int64_t async_id) { 117 int64_t async_id) {
67 Init(kAsyncEnd, label); 118 Init(kAsyncEnd, label);
68 timestamp0_ = OS::GetCurrentTimeMicros(); 119 timestamp0_ = OS::GetCurrentTimeMicros();
69 // Overload timestamp1_ with the async_id. 120 // Overload timestamp1_ with the async_id.
70 timestamp1_ = async_id; 121 timestamp1_ = static_cast<int64_t>(async_id);;
rmacnak 2015/08/18 21:09:00 "
Cutch 2015/08/18 21:50:18 Done.
71 } 122 }
72 123
73 124
74 void TimelineEvent::DurationBegin(const char* label) { 125 void TimelineEvent::DurationBegin(const char* label) {
75 Init(kDuration, label); 126 Init(kDuration, label);
76 timestamp0_ = OS::GetCurrentTimeMicros(); 127 timestamp0_ = OS::GetCurrentTimeMicros();
77 } 128 }
78 129
79 130
80 void TimelineEvent::DurationEnd() { 131 void TimelineEvent::DurationEnd() {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 186
136 187
137 void TimelineEvent::CopyArgument(intptr_t i, 188 void TimelineEvent::CopyArgument(intptr_t i,
138 const char* name, 189 const char* name,
139 const char* argument) { 190 const char* argument) {
140 SetArgument(i, name, strdup(argument)); 191 SetArgument(i, name, strdup(argument));
141 } 192 }
142 193
143 194
144 void TimelineEvent::Complete() { 195 void TimelineEvent::Complete() {
145 stream_->CompleteEvent(this); 196 TimelineEventRecorder* recorder = Timeline::recorder();
197 if (recorder != NULL) {
198 recorder->CompleteEvent(this);
199 }
146 } 200 }
147 201
148 202
149 void TimelineEvent::FreeArguments() { 203 void TimelineEvent::FreeArguments() {
150 if (arguments_ == NULL) { 204 if (arguments_ == NULL) {
151 return; 205 return;
152 } 206 }
153 for (intptr_t i = 0; i < arguments_length_; i++) { 207 for (intptr_t i = 0; i < arguments_length_; i++) {
154 free(arguments_[i].value); 208 free(arguments_[i].value);
155 } 209 }
156 free(arguments_); 210 free(arguments_);
157 arguments_ = NULL; 211 arguments_ = NULL;
158 arguments_length_ = 0; 212 arguments_length_ = 0;
159 } 213 }
160 214
161 215
162 void TimelineEvent::StreamInit(TimelineStream* stream) { 216 void TimelineEvent::StreamInit(TimelineStream* stream) {
163 ASSERT(stream != NULL); 217 if (stream != NULL) {
164 stream_ = stream; 218 category_ = stream->name();
219 } else {
220 category_ = "";
221 }
165 } 222 }
166 223
167 224
168 void TimelineEvent::Init(EventType event_type, 225 void TimelineEvent::Init(EventType event_type,
169 const char* label) { 226 const char* label) {
170 ASSERT(label != NULL); 227 ASSERT(label != NULL);
171 set_event_type(event_type); 228 set_event_type(event_type);
172 timestamp0_ = 0; 229 timestamp0_ = 0;
173 timestamp1_ = 0; 230 timestamp1_ = 0;
174 thread_ = OSThread::GetCurrentThreadId(); 231 thread_ = OSThread::GetCurrentThreadId();
232 isolate_ = Isolate::Current();
175 label_ = label; 233 label_ = label;
176 FreeArguments(); 234 FreeArguments();
177 } 235 }
178 236
179 237
180 void TimelineEvent::PrintJSON(JSONStream* stream) const { 238 void TimelineEvent::PrintJSON(JSONStream* stream) const {
181 JSONObject obj(stream); 239 JSONObject obj(stream);
182 int64_t pid = OS::ProcessId(); 240 int64_t pid = OS::ProcessId();
183 int64_t tid = OSThread::ThreadIdToIntPtr(thread_); 241 int64_t tid = OSThread::ThreadIdToIntPtr(thread_);
184 obj.AddProperty("name", label_); 242 obj.AddProperty("name", label_);
185 obj.AddProperty("cat", stream_->name()); 243 obj.AddProperty("cat", category_);
186 obj.AddProperty64("tid", tid); 244 obj.AddProperty64("tid", tid);
187 obj.AddProperty64("pid", pid); 245 obj.AddProperty64("pid", pid);
188 obj.AddPropertyTimeMillis("ts", TimeOrigin()); 246 obj.AddPropertyTimeMillis("ts", TimeOrigin());
189 247
190 switch (event_type()) { 248 switch (event_type()) {
191 case kDuration: { 249 case kDuration: {
192 obj.AddProperty("ph", "X"); 250 obj.AddProperty("ph", "X");
193 obj.AddPropertyTimeMillis("dur", TimeDuration()); 251 obj.AddPropertyTimeMillis("dur", TimeDuration());
194 } 252 }
195 break; 253 break;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 int64_t TimelineEvent::TimeDuration() const { 297 int64_t TimelineEvent::TimeDuration() const {
240 if (timestamp1_ == 0) { 298 if (timestamp1_ == 0) {
241 // This duration is still open, use current time as end. 299 // This duration is still open, use current time as end.
242 return OS::GetCurrentTimeMicros() - timestamp0_; 300 return OS::GetCurrentTimeMicros() - timestamp0_;
243 } 301 }
244 return timestamp1_ - timestamp0_; 302 return timestamp1_ - timestamp0_;
245 } 303 }
246 304
247 305
248 TimelineStream::TimelineStream() 306 TimelineStream::TimelineStream()
249 : recorder_(NULL), 307 : name_(NULL),
250 name_(NULL), 308 enabled_(false) {
251 enabled_(false),
252 seq_(0) {
253 } 309 }
254 310
255 311
256 void TimelineStream::Init(const char* name, bool enabled) { 312 void TimelineStream::Init(const char* name, bool enabled) {
257 name_ = name; 313 name_ = name;
258 enabled_ = enabled; 314 enabled_ = enabled;
259 } 315 }
260 316
261 317
262 TimelineEvent* TimelineStream::StartEvent() { 318 TimelineEvent* TimelineStream::StartEvent() {
263 if (!enabled_ || (recorder_ == NULL)) { 319 TimelineEventRecorder* recorder = Timeline::recorder();
320 if (!enabled_ || (recorder == NULL)) {
264 return NULL; 321 return NULL;
265 } 322 }
266 ASSERT(name_ != NULL); 323 ASSERT(name_ != NULL);
267 TimelineEvent* event = recorder_->StartEvent(); 324 TimelineEvent* event = recorder->StartEvent();
268 if (event != NULL) { 325 if (event != NULL) {
269 event->StreamInit(this); 326 event->StreamInit(this);
270 } 327 }
271 return event; 328 return event;
272 } 329 }
273 330
274 331
275 void TimelineStream::CompleteEvent(TimelineEvent* event) {
276 if (!enabled_ || (recorder_ == NULL)) {
277 return;
278 }
279 recorder_->CompleteEvent(event);
280 }
281
282
283 int64_t TimelineStream::GetNextSeq() {
284 seq_++;
285 if (seq_ < 0) {
286 seq_ = 0;
287 }
288 return seq_;
289 }
290
291
292 void TimelineDurationScope::FormatArgument(intptr_t i, 332 void TimelineDurationScope::FormatArgument(intptr_t i,
293 const char* name, 333 const char* name,
294 const char* fmt, ...) { 334 const char* fmt, ...) {
295 if (event_ == NULL) { 335 if (event_ == NULL) {
296 return; 336 return;
297 } 337 }
298 va_list args; 338 va_list args;
299 va_start(args, fmt); 339 va_start(args, fmt);
300 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args); 340 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
301 va_end(args); 341 va_end(args);
302 342
303 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); 343 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
304 va_list args2; 344 va_list args2;
305 va_start(args2, fmt); 345 va_start(args2, fmt);
306 OS::VSNPrint(buffer, (len + 1), fmt, args2); 346 OS::VSNPrint(buffer, (len + 1), fmt, args2);
307 va_end(args2); 347 va_end(args2);
308 348
309 event_->SetArgument(i, name, buffer); 349 event_->SetArgument(i, name, buffer);
310 } 350 }
311 351
312 352
313 TimelineEventRecorder::TimelineEventRecorder() { 353 TimelineEventFilter::TimelineEventFilter() {
314 } 354 }
315 355
316 356
357 TimelineEventFilter::~TimelineEventFilter() {
358 }
359
360
361 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate)
362 : isolate_(isolate) {
363 }
364
365
366 TimelineEventRecorder::TimelineEventRecorder()
367 : global_block_(NULL),
368 async_id_(0) {
369 }
370
371
317 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { 372 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
318 } 373 }
319 374
320 375
321 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { 376 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() {
322 // Grab the thread's timeline event block. 377 // Grab the thread's timeline event block.
323 Thread* thread = Thread::Current(); 378 Thread* thread = Thread::Current();
379 ASSERT(thread != NULL);
380
381 if (thread->isolate() == NULL) {
382 // Non-isolate thread case. This should be infrequent.
383 return GlobalBlockStartEvent();
384 }
385
324 TimelineEventBlock* thread_block = thread->timeline_block(); 386 TimelineEventBlock* thread_block = thread->timeline_block();
325 if ((thread_block == NULL) || thread_block->IsFull()) { 387
326 // If it is full, request a new block. 388 if ((thread_block != NULL) && thread_block->IsFull()) {
327 thread_block = GetNewBlock(); 389 MutexLocker ml(&lock_);
390 // Thread has a block and it is full:
391 // 1) Mark it as finished.
392 thread_block->Finish();
393 // 2) Allocate a new block.
394 thread_block = GetNewBlockLocked(thread->isolate());
395 thread->set_timeline_block(thread_block);
396 } else if (thread_block == NULL) {
397 MutexLocker ml(&lock_);
398 // Thread has no block. Attempt to allocate one.
399 thread_block = GetNewBlockLocked(thread->isolate());
328 thread->set_timeline_block(thread_block); 400 thread->set_timeline_block(thread_block);
329 } 401 }
330 if (thread_block == NULL) { 402 if (thread_block != NULL) {
331 // Could not allocate block. 403 ASSERT(!thread_block->IsFull());
332 return NULL; 404 return thread_block->StartEvent();
333 } 405 }
334 ASSERT(thread_block != NULL); 406 return NULL;
335 ASSERT(!thread_block->IsFull()); 407 }
336 return thread_block->StartEvent(); 408
409
410
411 TimelineEvent* TimelineEventRecorder::GlobalBlockStartEvent() {
412 MutexLocker ml(&lock_);
413 if ((global_block_ != NULL) && global_block_->IsFull()) {
414 // Global block is full.
415 global_block_->Finish();
416 global_block_ = NULL;
417 }
418 if (global_block_ == NULL) {
419 // Allocate a new block.
420 global_block_ = GetNewBlockLocked(NULL);
421 }
422 if (global_block_ != NULL) {
423 ASSERT(!global_block_->IsFull());
424 return global_block_->StartEvent();
425 }
426 return NULL;
337 } 427 }
338 428
339 429
340 void TimelineEventRecorder::WriteTo(const char* directory) { 430 void TimelineEventRecorder::WriteTo(const char* directory) {
341 Isolate* isolate = Isolate::Current();
342
343 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 431 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
344 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); 432 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
345 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); 433 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
346 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { 434 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
347 return; 435 return;
348 } 436 }
349 437
350 JSONStream js; 438 JSONStream js;
351 PrintJSON(&js); 439 TimelineEventFilter filter;
440 PrintJSON(&js, &filter);
352 441
353 const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json"; 442 const char* format = "%s/dart-timeline-%" Pd ".json";
354 intptr_t pid = OS::ProcessId(); 443 intptr_t pid = OS::ProcessId();
355 intptr_t len = OS::SNPrint(NULL, 0, format, 444 intptr_t len = OS::SNPrint(NULL, 0, format, directory, pid);
356 directory, pid, isolate->main_port()); 445 char* filename = reinterpret_cast<char*>(malloc(len + 1));
357 char* filename = Thread::Current()->zone()->Alloc<char>(len + 1); 446 OS::SNPrint(filename, len + 1, format, directory, pid);
358 OS::SNPrint(filename, len + 1, format,
359 directory, pid, isolate->main_port());
360 void* file = (*file_open)(filename, true); 447 void* file = (*file_open)(filename, true);
361 if (file == NULL) { 448 if (file == NULL) {
362 OS::Print("Failed to write timeline file: %s\n", filename); 449 OS::Print("Failed to write timeline file: %s\n", filename);
450 free(filename);
363 return; 451 return;
364 } 452 }
453 free(filename);
365 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); 454 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
366 (*file_close)(file); 455 (*file_close)(file);
367 } 456 }
368 457
369 458
459 int64_t TimelineEventRecorder::GetNextAsyncId() {
460 // TODO(johnmccutchan): Gracefully handle wrap around.
461 uint32_t next = static_cast<uint32_t>(
462 AtomicOperations::FetchAndIncrement(&async_id_));
463 return static_cast<int64_t>(next);
464 }
465
466
467 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() {
468 MutexLocker ml(&lock_);
469 return GetNewBlockLocked(Isolate::Current());
470 }
471
370 472
371 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) 473 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
372 : blocks_(NULL), 474 : blocks_(NULL),
373 event_objects_(Array::null()),
374 capacity_(capacity), 475 capacity_(capacity),
375 num_blocks_(0), 476 num_blocks_(0),
376 block_cursor_(0) { 477 block_cursor_(0) {
377 // Capacity must be a multiple of TimelineEventBlock::kBlockSize 478 // Capacity must be a multiple of TimelineEventBlock::kBlockSize
378 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); 479 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0);
379 // Allocate blocks array. 480 // Allocate blocks array.
380 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; 481 num_blocks_ = capacity / TimelineEventBlock::kBlockSize;
381 blocks_ = 482 blocks_ =
382 reinterpret_cast<TimelineEventBlock**>( 483 reinterpret_cast<TimelineEventBlock**>(
383 calloc(num_blocks_, sizeof(TimelineEventBlock*))); 484 calloc(num_blocks_, sizeof(TimelineEventBlock*)));
384 // Allocate each block. 485 // Allocate each block.
385 for (intptr_t i = 0; i < num_blocks_; i++) { 486 for (intptr_t i = 0; i < num_blocks_; i++) {
386 blocks_[i] = new TimelineEventBlock(i); 487 blocks_[i] = new TimelineEventBlock(i);
387 } 488 }
388 // Chain blocks together. 489 // Chain blocks together.
389 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { 490 for (intptr_t i = 0; i < num_blocks_ - 1; i++) {
390 blocks_[i]->set_next(blocks_[i + 1]); 491 blocks_[i]->set_next(blocks_[i + 1]);
391 } 492 }
392 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
393 event_objects_ = array.raw();
394 } 493 }
395 494
396 495
397 TimelineEventRingRecorder::~TimelineEventRingRecorder() { 496 TimelineEventRingRecorder::~TimelineEventRingRecorder() {
398 // Delete all blocks. 497 // Delete all blocks.
399 for (intptr_t i = 0; i < num_blocks_; i++) { 498 for (intptr_t i = 0; i < num_blocks_; i++) {
400 TimelineEventBlock* block = blocks_[i]; 499 TimelineEventBlock* block = blocks_[i];
401 delete block; 500 delete block;
402 } 501 }
403 free(blocks_); 502 free(blocks_);
404 event_objects_ = Array::null();
405 } 503 }
406 504
407 505
408 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { 506 void TimelineEventRingRecorder::PrintJSONEvents(
507 JSONArray* events,
508 TimelineEventFilter* filter) const {
409 intptr_t block_offset = FindOldestBlockIndex(); 509 intptr_t block_offset = FindOldestBlockIndex();
410 if (block_offset == -1) { 510 if (block_offset == -1) {
411 // All blocks are empty. 511 // All blocks are empty.
412 return; 512 return;
413 } 513 }
414 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 514 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
415 TimelineEventBlock* block = 515 TimelineEventBlock* block =
416 blocks_[(block_idx + block_offset) % num_blocks_]; 516 blocks_[(block_idx + block_offset) % num_blocks_];
417 if (block->IsEmpty()) { 517 if (block->IsEmpty()) {
418 // Skip empty blocks. 518 // Skip empty blocks.
419 continue; 519 continue;
420 } 520 }
421 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) { 521 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
422 TimelineEvent* event = block->At(event_idx); 522 TimelineEvent* event = block->At(event_idx);
423 if (event->IsValid()) { 523 if (event->IsValid()) {
424 events->AddValue(event); 524 events->AddValue(event);
425 } 525 }
426 } 526 }
427 } 527 }
428 } 528 }
429 529
430 530
431 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) { 531 void TimelineEventRingRecorder::PrintJSON(JSONStream* js,
532 TimelineEventFilter* filter) {
432 MutexLocker ml(&lock_); 533 MutexLocker ml(&lock_);
433 JSONObject topLevel(js); 534 JSONObject topLevel(js);
434 topLevel.AddProperty("type", "_Timeline"); 535 topLevel.AddProperty("type", "_Timeline");
435 { 536 {
436 JSONArray events(&topLevel, "traceEvents"); 537 JSONArray events(&topLevel, "traceEvents");
437 PrintJSONMeta(&events); 538 PrintJSONMeta(&events);
438 PrintJSONEvents(&events); 539 PrintJSONEvents(&events, filter);
439 } 540 }
440 } 541 }
441 542
442 543
443 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlock() { 544 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() {
444 MutexLocker ml(&lock_);
445 return GetNewBlockLocked();
446 }
447
448
449 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlock() {
450 return blocks_[0]; 545 return blocks_[0];
451 } 546 }
452 547
453 548
454 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { 549 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked(
550 Isolate* isolate) {
551 // TODO(johnmccutchan): This function should only hand out blocks
552 // which have been marked as finished.
455 if (block_cursor_ == num_blocks_) { 553 if (block_cursor_ == num_blocks_) {
456 block_cursor_ = 0; 554 block_cursor_ = 0;
457 } 555 }
458 TimelineEventBlock* block = blocks_[block_cursor_++]; 556 TimelineEventBlock* block = blocks_[block_cursor_++];
459 block->Reset(); 557 block->Reset();
558 block->Open(isolate);
460 return block; 559 return block;
461 } 560 }
462 561
463 562
464 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const { 563 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const {
465 int64_t earliest_time = kMaxInt64; 564 int64_t earliest_time = kMaxInt64;
466 intptr_t earliest_index = -1; 565 intptr_t earliest_index = -1;
467 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 566 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
468 TimelineEventBlock* block = blocks_[block_idx]; 567 TimelineEventBlock* block = blocks_[block_idx];
469 if (block->IsEmpty()) { 568 if (block->IsEmpty()) {
(...skipping 20 matching lines...) Expand all
490 589
491 590
492 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { 591 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
493 } 592 }
494 593
495 594
496 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { 595 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
497 } 596 }
498 597
499 598
500 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) { 599 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js,
600 TimelineEventFilter* filter) {
501 JSONObject topLevel(js); 601 JSONObject topLevel(js);
502 topLevel.AddProperty("type", "_Timeline"); 602 topLevel.AddProperty("type", "_Timeline");
503 { 603 {
504 JSONArray events(&topLevel, "traceEvents"); 604 JSONArray events(&topLevel, "traceEvents");
505 PrintJSONMeta(&events); 605 PrintJSONMeta(&events);
506 } 606 }
507 } 607 }
508 608
509 609
510 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { 610 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
511 TimelineEvent* event = new TimelineEvent(); 611 TimelineEvent* event = new TimelineEvent();
512 return event; 612 return event;
513 } 613 }
514 614
515 615
516 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { 616 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
517 StreamEvent(event); 617 StreamEvent(event);
518 delete event; 618 delete event;
519 } 619 }
520 620
521 621
522 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() 622 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
523 : head_(NULL), 623 : head_(NULL),
524 block_index_(0) { 624 block_index_(0) {
525 GetNewBlock(); 625 GetNewBlock();
526 } 626 }
527 627
528 628
529 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) { 629 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
630 TimelineEventFilter* filter) {
530 MutexLocker ml(&lock_); 631 MutexLocker ml(&lock_);
531 JSONObject topLevel(js); 632 JSONObject topLevel(js);
532 topLevel.AddProperty("type", "_Timeline"); 633 topLevel.AddProperty("type", "_Timeline");
533 { 634 {
534 JSONArray events(&topLevel, "traceEvents"); 635 JSONArray events(&topLevel, "traceEvents");
535 PrintJSONMeta(&events); 636 PrintJSONMeta(&events);
536 PrintJSONEvents(&events); 637 PrintJSONEvents(&events, filter);
537 } 638 }
538 } 639 }
539 640
540 641
541 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlock() { 642 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() {
542 MutexLocker ml(&lock_);
543 return GetNewBlockLocked();
544 }
545
546
547 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlock() {
548 return head_; 643 return head_;
549 } 644 }
550 645
551 646
552 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { 647 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() {
553 return ThreadBlockStartEvent(); 648 return ThreadBlockStartEvent();
554 } 649 }
555 650
556 651
557 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { 652 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) {
558 // no-op. 653 // no-op.
559 } 654 }
560 655
561 656
562 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { 657 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked(
658 Isolate* isolate) {
563 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); 659 TimelineEventBlock* block = new TimelineEventBlock(block_index_++);
564 block->set_next(head_); 660 block->set_next(head_);
661 block->Open(isolate);
565 head_ = block; 662 head_ = block;
566 return head_; 663 return head_;
567 } 664 }
568 665
569 666
570 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const { 667 void TimelineEventEndlessRecorder::PrintJSONEvents(
668 JSONArray* events,
669 TimelineEventFilter* filter) const {
571 TimelineEventBlock* current = head_; 670 TimelineEventBlock* current = head_;
671
572 while (current != NULL) { 672 while (current != NULL) {
573 intptr_t length = current->length(); 673 intptr_t length = current->length();
574 for (intptr_t i = 0; i < length; i++) { 674 for (intptr_t i = 0; i < length; i++) {
575 TimelineEvent* event = current->At(i); 675 TimelineEvent* event = current->At(i);
576 if (!event->IsValid()) { 676 if (!event->IsValid()) {
577 continue; 677 continue;
578 } 678 }
579 events->AddValue(event); 679 events->AddValue(event);
580 } 680 }
581 current = current->next(); 681 current = current->next();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 return true; 752 return true;
653 } 753 }
654 754
655 755
656 void TimelineEventBlock::Reset() { 756 void TimelineEventBlock::Reset() {
657 for (intptr_t i = 0; i < kBlockSize; i++) { 757 for (intptr_t i = 0; i < kBlockSize; i++) {
658 // Clear any extra data. 758 // Clear any extra data.
659 events_[i].Reset(); 759 events_[i].Reset();
660 } 760 }
661 length_ = 0; 761 length_ = 0;
762 isolate_ = NULL;
763 open_ = false;
662 } 764 }
663 765
664 766
767 void TimelineEventBlock::Open(Isolate* isolate) {
768 isolate_ = isolate;
769 open_ = true;
770 }
771
772
773 void TimelineEventBlock::Finish() {
774 open_ = false;
775 }
776
777
665 TimelineEventBlockIterator::TimelineEventBlockIterator( 778 TimelineEventBlockIterator::TimelineEventBlockIterator(
666 TimelineEventRecorder* recorder) 779 TimelineEventRecorder* recorder)
667 : current_(NULL), 780 : current_(NULL),
668 recorder_(NULL) { 781 recorder_(NULL) {
669 Reset(recorder); 782 Reset(recorder);
670 } 783 }
671 784
672 785
673 TimelineEventBlockIterator::~TimelineEventBlockIterator() { 786 TimelineEventBlockIterator::~TimelineEventBlockIterator() {
674 Reset(NULL); 787 Reset(NULL);
675 } 788 }
676 789
677 790
678 void TimelineEventBlockIterator::Reset(TimelineEventRecorder* recorder) { 791 void TimelineEventBlockIterator::Reset(TimelineEventRecorder* recorder) {
679 // Clear current. 792 // Clear current.
680 current_ = NULL; 793 current_ = NULL;
681 if (recorder_ != NULL) { 794 if (recorder_ != NULL) {
682 // Unlock old recorder. 795 // Unlock old recorder.
683 recorder_->lock_.Unlock(); 796 recorder_->lock_.Unlock();
684 } 797 }
685 recorder_ = recorder; 798 recorder_ = recorder;
686 if (recorder_ == NULL) { 799 if (recorder_ == NULL) {
687 return; 800 return;
688 } 801 }
689 // Lock new recorder. 802 // Lock new recorder.
690 recorder_->lock_.Lock(); 803 recorder_->lock_.Lock();
691 // Queue up first block. 804 // Queue up first block.
692 current_ = recorder_->GetHeadBlock(); 805 current_ = recorder_->GetHeadBlockLocked();
693 } 806 }
694 807
695 808
696 bool TimelineEventBlockIterator::HasNext() const { 809 bool TimelineEventBlockIterator::HasNext() const {
697 return current_ != NULL; 810 return current_ != NULL;
698 } 811 }
699 812
700 813
701 TimelineEventBlock* TimelineEventBlockIterator::Next() { 814 TimelineEventBlock* TimelineEventBlockIterator::Next() {
702 ASSERT(current_ != NULL); 815 ASSERT(current_ != NULL);
703 TimelineEventBlock* r = current_; 816 TimelineEventBlock* r = current_;
704 current_ = current_->next(); 817 current_ = current_->next();
705 return r; 818 return r;
706 } 819 }
707 820
708 } // namespace dart 821 } // namespace dart
OLDNEW
« runtime/vm/timeline.h ('K') | « runtime/vm/timeline.h ('k') | runtime/vm/timeline_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698