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

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_ = async_id;
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_ = async_id;
62 } 113 }
(...skipping 72 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
438 FinishGlobalBlock();
439
350 JSONStream js; 440 JSONStream js;
351 PrintJSON(&js); 441 TimelineEventFilter filter;
442 PrintJSON(&js, &filter);
352 443
353 const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json"; 444 const char* format = "%s/dart-timeline-%" Pd ".json";
354 intptr_t pid = OS::ProcessId(); 445 intptr_t pid = OS::ProcessId();
355 intptr_t len = OS::SNPrint(NULL, 0, format, 446 intptr_t len = OS::SNPrint(NULL, 0, format, directory, pid);
356 directory, pid, isolate->main_port()); 447 char* filename = reinterpret_cast<char*>(malloc(len + 1));
357 char* filename = Thread::Current()->zone()->Alloc<char>(len + 1); 448 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); 449 void* file = (*file_open)(filename, true);
361 if (file == NULL) { 450 if (file == NULL) {
362 OS::Print("Failed to write timeline file: %s\n", filename); 451 OS::Print("Failed to write timeline file: %s\n", filename);
452 free(filename);
363 return; 453 return;
364 } 454 }
455 free(filename);
365 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); 456 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
366 (*file_close)(file); 457 (*file_close)(file);
367 } 458 }
368 459
369 460
461 void TimelineEventRecorder::FinishGlobalBlock() {
462 MutexLocker ml(&lock_);
463 if (global_block_ != NULL) {
464 global_block_->Finish();
465 global_block_ = NULL;
466 }
467 }
468
469
470 int64_t TimelineEventRecorder::GetNextAsyncId() {
471 // TODO(johnmccutchan): Gracefully handle wrap around.
472 uint32_t next = static_cast<uint32_t>(
473 AtomicOperations::FetchAndIncrement(&async_id_));
474 return static_cast<int64_t>(next);
475 }
476
477
478 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() {
479 MutexLocker ml(&lock_);
480 return GetNewBlockLocked(Isolate::Current());
481 }
482
370 483
371 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) 484 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
372 : blocks_(NULL), 485 : blocks_(NULL),
373 event_objects_(Array::null()),
374 capacity_(capacity), 486 capacity_(capacity),
375 num_blocks_(0), 487 num_blocks_(0),
376 block_cursor_(0) { 488 block_cursor_(0) {
377 // Capacity must be a multiple of TimelineEventBlock::kBlockSize 489 // Capacity must be a multiple of TimelineEventBlock::kBlockSize
378 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); 490 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0);
379 // Allocate blocks array. 491 // Allocate blocks array.
380 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; 492 num_blocks_ = capacity / TimelineEventBlock::kBlockSize;
381 blocks_ = 493 blocks_ =
382 reinterpret_cast<TimelineEventBlock**>( 494 reinterpret_cast<TimelineEventBlock**>(
383 calloc(num_blocks_, sizeof(TimelineEventBlock*))); 495 calloc(num_blocks_, sizeof(TimelineEventBlock*)));
384 // Allocate each block. 496 // Allocate each block.
385 for (intptr_t i = 0; i < num_blocks_; i++) { 497 for (intptr_t i = 0; i < num_blocks_; i++) {
386 blocks_[i] = new TimelineEventBlock(i); 498 blocks_[i] = new TimelineEventBlock(i);
387 } 499 }
388 // Chain blocks together. 500 // Chain blocks together.
389 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { 501 for (intptr_t i = 0; i < num_blocks_ - 1; i++) {
390 blocks_[i]->set_next(blocks_[i + 1]); 502 blocks_[i]->set_next(blocks_[i + 1]);
391 } 503 }
392 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
393 event_objects_ = array.raw();
394 } 504 }
395 505
396 506
397 TimelineEventRingRecorder::~TimelineEventRingRecorder() { 507 TimelineEventRingRecorder::~TimelineEventRingRecorder() {
398 // Delete all blocks. 508 // Delete all blocks.
399 for (intptr_t i = 0; i < num_blocks_; i++) { 509 for (intptr_t i = 0; i < num_blocks_; i++) {
400 TimelineEventBlock* block = blocks_[i]; 510 TimelineEventBlock* block = blocks_[i];
401 delete block; 511 delete block;
402 } 512 }
403 free(blocks_); 513 free(blocks_);
404 event_objects_ = Array::null();
405 } 514 }
406 515
407 516
408 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { 517 void TimelineEventRingRecorder::PrintJSONEvents(
518 JSONArray* events,
519 TimelineEventFilter* filter) const {
409 intptr_t block_offset = FindOldestBlockIndex(); 520 intptr_t block_offset = FindOldestBlockIndex();
410 if (block_offset == -1) { 521 if (block_offset == -1) {
411 // All blocks are empty. 522 // All blocks are empty.
412 return; 523 return;
413 } 524 }
414 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 525 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
415 TimelineEventBlock* block = 526 TimelineEventBlock* block =
416 blocks_[(block_idx + block_offset) % num_blocks_]; 527 blocks_[(block_idx + block_offset) % num_blocks_];
417 if (block->IsEmpty()) { 528 if (!filter->IncludeBlock(block)) {
418 // Skip empty blocks.
419 continue; 529 continue;
420 } 530 }
421 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) { 531 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
422 TimelineEvent* event = block->At(event_idx); 532 TimelineEvent* event = block->At(event_idx);
423 if (event->IsValid()) { 533 if (filter->IncludeEvent(event)) {
424 events->AddValue(event); 534 events->AddValue(event);
425 } 535 }
426 } 536 }
427 } 537 }
428 } 538 }
429 539
430 540
431 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) { 541 void TimelineEventRingRecorder::PrintJSON(JSONStream* js,
542 TimelineEventFilter* filter) {
432 MutexLocker ml(&lock_); 543 MutexLocker ml(&lock_);
433 JSONObject topLevel(js); 544 JSONObject topLevel(js);
434 topLevel.AddProperty("type", "_Timeline"); 545 topLevel.AddProperty("type", "_Timeline");
435 { 546 {
436 JSONArray events(&topLevel, "traceEvents"); 547 JSONArray events(&topLevel, "traceEvents");
437 PrintJSONMeta(&events); 548 PrintJSONMeta(&events);
438 PrintJSONEvents(&events); 549 PrintJSONEvents(&events, filter);
439 } 550 }
440 } 551 }
441 552
442 553
443 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlock() { 554 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() {
444 MutexLocker ml(&lock_);
445 return GetNewBlockLocked();
446 }
447
448
449 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlock() {
450 return blocks_[0]; 555 return blocks_[0];
451 } 556 }
452 557
453 558
454 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { 559 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked(
560 Isolate* isolate) {
561 // TODO(johnmccutchan): This function should only hand out blocks
562 // which have been marked as finished.
455 if (block_cursor_ == num_blocks_) { 563 if (block_cursor_ == num_blocks_) {
456 block_cursor_ = 0; 564 block_cursor_ = 0;
457 } 565 }
458 TimelineEventBlock* block = blocks_[block_cursor_++]; 566 TimelineEventBlock* block = blocks_[block_cursor_++];
459 block->Reset(); 567 block->Reset();
568 block->Open(isolate);
460 return block; 569 return block;
461 } 570 }
462 571
463 572
464 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const { 573 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const {
465 int64_t earliest_time = kMaxInt64; 574 int64_t earliest_time = kMaxInt64;
466 intptr_t earliest_index = -1; 575 intptr_t earliest_index = -1;
467 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 576 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
468 TimelineEventBlock* block = blocks_[block_idx]; 577 TimelineEventBlock* block = blocks_[block_idx];
469 if (block->IsEmpty()) { 578 if (block->IsEmpty()) {
(...skipping 20 matching lines...) Expand all
490 599
491 600
492 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { 601 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
493 } 602 }
494 603
495 604
496 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { 605 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
497 } 606 }
498 607
499 608
500 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) { 609 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js,
610 TimelineEventFilter* filter) {
501 JSONObject topLevel(js); 611 JSONObject topLevel(js);
502 topLevel.AddProperty("type", "_Timeline"); 612 topLevel.AddProperty("type", "_Timeline");
503 { 613 {
504 JSONArray events(&topLevel, "traceEvents"); 614 JSONArray events(&topLevel, "traceEvents");
505 PrintJSONMeta(&events); 615 PrintJSONMeta(&events);
506 } 616 }
507 } 617 }
508 618
509 619
510 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { 620 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
511 TimelineEvent* event = new TimelineEvent(); 621 TimelineEvent* event = new TimelineEvent();
512 return event; 622 return event;
513 } 623 }
514 624
515 625
516 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { 626 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
517 StreamEvent(event); 627 StreamEvent(event);
518 delete event; 628 delete event;
519 } 629 }
520 630
521 631
522 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() 632 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
523 : head_(NULL), 633 : head_(NULL),
524 block_index_(0) { 634 block_index_(0) {
525 GetNewBlock(); 635 GetNewBlock();
526 } 636 }
527 637
528 638
529 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) { 639 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
640 TimelineEventFilter* filter) {
530 MutexLocker ml(&lock_); 641 MutexLocker ml(&lock_);
531 JSONObject topLevel(js); 642 JSONObject topLevel(js);
532 topLevel.AddProperty("type", "_Timeline"); 643 topLevel.AddProperty("type", "_Timeline");
533 { 644 {
534 JSONArray events(&topLevel, "traceEvents"); 645 JSONArray events(&topLevel, "traceEvents");
535 PrintJSONMeta(&events); 646 PrintJSONMeta(&events);
536 PrintJSONEvents(&events); 647 PrintJSONEvents(&events, filter);
537 } 648 }
538 } 649 }
539 650
540 651
541 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlock() { 652 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() {
542 MutexLocker ml(&lock_);
543 return GetNewBlockLocked();
544 }
545
546
547 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlock() {
548 return head_; 653 return head_;
549 } 654 }
550 655
551 656
552 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { 657 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() {
553 return ThreadBlockStartEvent(); 658 return ThreadBlockStartEvent();
554 } 659 }
555 660
556 661
557 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { 662 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) {
558 // no-op. 663 // no-op.
559 } 664 }
560 665
561 666
562 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { 667 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked(
668 Isolate* isolate) {
563 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); 669 TimelineEventBlock* block = new TimelineEventBlock(block_index_++);
564 block->set_next(head_); 670 block->set_next(head_);
671 block->Open(isolate);
565 head_ = block; 672 head_ = block;
566 return head_; 673 return head_;
567 } 674 }
568 675
569 676
570 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const { 677 void TimelineEventEndlessRecorder::PrintJSONEvents(
678 JSONArray* events,
679 TimelineEventFilter* filter) const {
571 TimelineEventBlock* current = head_; 680 TimelineEventBlock* current = head_;
681
572 while (current != NULL) { 682 while (current != NULL) {
683 if (!filter->IncludeBlock(current)) {
684 current = current->next();
685 continue;
686 }
573 intptr_t length = current->length(); 687 intptr_t length = current->length();
574 for (intptr_t i = 0; i < length; i++) { 688 for (intptr_t i = 0; i < length; i++) {
575 TimelineEvent* event = current->At(i); 689 TimelineEvent* event = current->At(i);
576 if (!event->IsValid()) { 690 if (!filter->IncludeEvent(event)) {
577 continue; 691 continue;
578 } 692 }
579 events->AddValue(event); 693 events->AddValue(event);
580 } 694 }
581 current = current->next(); 695 current = current->next();
582 } 696 }
583 } 697 }
584 698
585 699
586 void TimelineEventEndlessRecorder::Clear() { 700 void TimelineEventEndlessRecorder::Clear() {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 return true; 766 return true;
653 } 767 }
654 768
655 769
656 void TimelineEventBlock::Reset() { 770 void TimelineEventBlock::Reset() {
657 for (intptr_t i = 0; i < kBlockSize; i++) { 771 for (intptr_t i = 0; i < kBlockSize; i++) {
658 // Clear any extra data. 772 // Clear any extra data.
659 events_[i].Reset(); 773 events_[i].Reset();
660 } 774 }
661 length_ = 0; 775 length_ = 0;
776 isolate_ = NULL;
777 open_ = false;
662 } 778 }
663 779
664 780
781 void TimelineEventBlock::Open(Isolate* isolate) {
782 isolate_ = isolate;
783 open_ = true;
784 }
785
786
787 void TimelineEventBlock::Finish() {
788 open_ = false;
789 }
790
791
665 TimelineEventBlockIterator::TimelineEventBlockIterator( 792 TimelineEventBlockIterator::TimelineEventBlockIterator(
666 TimelineEventRecorder* recorder) 793 TimelineEventRecorder* recorder)
667 : current_(NULL), 794 : current_(NULL),
668 recorder_(NULL) { 795 recorder_(NULL) {
669 Reset(recorder); 796 Reset(recorder);
670 } 797 }
671 798
672 799
673 TimelineEventBlockIterator::~TimelineEventBlockIterator() { 800 TimelineEventBlockIterator::~TimelineEventBlockIterator() {
674 Reset(NULL); 801 Reset(NULL);
675 } 802 }
676 803
677 804
678 void TimelineEventBlockIterator::Reset(TimelineEventRecorder* recorder) { 805 void TimelineEventBlockIterator::Reset(TimelineEventRecorder* recorder) {
679 // Clear current. 806 // Clear current.
680 current_ = NULL; 807 current_ = NULL;
681 if (recorder_ != NULL) { 808 if (recorder_ != NULL) {
682 // Unlock old recorder. 809 // Unlock old recorder.
683 recorder_->lock_.Unlock(); 810 recorder_->lock_.Unlock();
684 } 811 }
685 recorder_ = recorder; 812 recorder_ = recorder;
686 if (recorder_ == NULL) { 813 if (recorder_ == NULL) {
687 return; 814 return;
688 } 815 }
689 // Lock new recorder. 816 // Lock new recorder.
690 recorder_->lock_.Lock(); 817 recorder_->lock_.Lock();
691 // Queue up first block. 818 // Queue up first block.
692 current_ = recorder_->GetHeadBlock(); 819 current_ = recorder_->GetHeadBlockLocked();
693 } 820 }
694 821
695 822
696 bool TimelineEventBlockIterator::HasNext() const { 823 bool TimelineEventBlockIterator::HasNext() const {
697 return current_ != NULL; 824 return current_ != NULL;
698 } 825 }
699 826
700 827
701 TimelineEventBlock* TimelineEventBlockIterator::Next() { 828 TimelineEventBlock* TimelineEventBlockIterator::Next() {
702 ASSERT(current_ != NULL); 829 ASSERT(current_ != NULL);
703 TimelineEventBlock* r = current_; 830 TimelineEventBlock* r = current_;
704 current_ = current_->next(); 831 current_ = current_->next();
705 return r; 832 return r;
706 } 833 }
707 834
708 } // namespace dart 835 } // namespace dart
OLDNEW
« runtime/vm/dart.cc ('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