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

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

Issue 2984603002: Special-case Timeline.{start,finish}Sync for Fuchsia (Closed)
Patch Set: Address comments Created 3 years, 5 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') | runtime/vm/timeline_android.cc » ('j') | 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 "platform/globals.h" 5 #include "platform/globals.h"
6 #ifndef PRODUCT 6 #ifndef PRODUCT
7 7
8 #include "vm/timeline.h"
9
8 #include <errno.h> 10 #include <errno.h>
9 #include <fcntl.h> 11 #include <fcntl.h>
10 #include <cstdlib> 12 #include <cstdlib>
11 13
12 #if defined(HOST_OS_FUCHSIA)
13 #include "apps/tracing/lib/trace/cwriter.h"
14 #include "apps/tracing/lib/trace/event.h"
15 #endif
16
17 #include "vm/atomic.h" 14 #include "vm/atomic.h"
18 #include "vm/isolate.h" 15 #include "vm/isolate.h"
19 #include "vm/json_stream.h" 16 #include "vm/json_stream.h"
20 #include "vm/lockers.h" 17 #include "vm/lockers.h"
21 #include "vm/log.h" 18 #include "vm/log.h"
22 #include "vm/object.h" 19 #include "vm/object.h"
23 #include "vm/service_event.h" 20 #include "vm/service_event.h"
24 #include "vm/thread.h" 21 #include "vm/thread.h"
25 #include "vm/timeline.h"
26 22
27 namespace dart { 23 namespace dart {
28 24
29 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline"); 25 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
30 DEFINE_FLAG(bool, startup_timeline, false, "Record the startup timeline"); 26 DEFINE_FLAG(bool, startup_timeline, false, "Record the startup timeline");
31 DEFINE_FLAG( 27 DEFINE_FLAG(
32 bool, 28 bool,
33 systrace_timeline, 29 systrace_timeline,
34 false, 30 false,
35 "Record the timeline to the platform's tracing service if there is one"); 31 "Record the timeline to the platform's tracing service if there is one");
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 const bool use_startup_recorder = FLAG_startup_timeline; 105 const bool use_startup_recorder = FLAG_startup_timeline;
110 const bool use_systrace_recorder = FLAG_systrace_timeline; 106 const bool use_systrace_recorder = FLAG_systrace_timeline;
111 107
112 const char* flag = FLAG_timeline_recorder; 108 const char* flag = FLAG_timeline_recorder;
113 109
114 if (use_systrace_recorder || (flag != NULL)) { 110 if (use_systrace_recorder || (flag != NULL)) {
115 if (use_systrace_recorder || (strcmp("systrace", flag) == 0)) { 111 if (use_systrace_recorder || (strcmp("systrace", flag) == 0)) {
116 if (FLAG_trace_timeline) { 112 if (FLAG_trace_timeline) {
117 THR_Print("Using the Systrace timeline recorder.\n"); 113 THR_Print("Using the Systrace timeline recorder.\n");
118 } 114 }
119 #if defined(HOST_OS_FUCHSIA) 115 return TimelineEventPlatformRecorder::CreatePlatformRecorder();
120 return new TimelineEventFuchsiaRecorder();
121 #else
122 return new TimelineEventSystraceRecorder();
123 #endif
124 } 116 }
125 } 117 }
126 118
127 if (use_endless_recorder || (flag != NULL)) { 119 if (use_endless_recorder || (flag != NULL)) {
128 if (use_endless_recorder || (strcmp("endless", flag) == 0)) { 120 if (use_endless_recorder || (strcmp("endless", flag) == 0)) {
129 if (FLAG_trace_timeline) { 121 if (FLAG_trace_timeline) {
130 THR_Print("Using the endless timeline recorder.\n"); 122 THR_Print("Using the endless timeline recorder.\n");
131 } 123 }
132 return new TimelineEventEndlessRecorder(); 124 return new TimelineEventEndlessRecorder();
133 } 125 }
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 const char* argument) { 510 const char* argument) {
519 SetArgument(i, name, strdup(argument)); 511 SetArgument(i, name, strdup(argument));
520 } 512 }
521 513
522 void TimelineEvent::StealArguments(intptr_t arguments_length, 514 void TimelineEvent::StealArguments(intptr_t arguments_length,
523 TimelineEventArgument* arguments) { 515 TimelineEventArgument* arguments) {
524 arguments_length_ = arguments_length; 516 arguments_length_ = arguments_length;
525 arguments_ = arguments; 517 arguments_ = arguments;
526 } 518 }
527 519
528 #if defined(HOST_OS_FUCHSIA)
529 // TODO(zra): The functions below emit Dart's timeline events all as category
530 // "dart". Instead, we could have finer-grained categories that make use of
531 // the name of the timeline stream, e.g. "VM", "GC", etc.
532
533 void TimelineEvent::EmitFuchsiaEvent() {
534 if (!ctrace_is_enabled()) {
535 return;
536 }
537 auto writer = ctrace_writer_acquire();
538
539 // XXX: use ctrace_register_category_string();
540 ctrace_stringref_t category;
541 ctrace_register_string(writer, "dart", &category);
542
543 ctrace_stringref_t name;
544 ctrace_register_string(writer, label_, &name);
545
546 ctrace_threadref_t thread;
547 ctrace_register_current_thread(writer, &thread);
548
549 ctrace_argspec_t args[2];
550 ctrace_arglist_t arglist = {0, args};
551
552 if (arguments_length_ >= 1) {
553 args[0].type = CTRACE_ARGUMENT_STRING;
554 args[0].name = arguments_[0].name;
555 args[0].u.s = arguments_[0].value;
556 arglist.n_args += 1;
557 }
558 if (arguments_length_ >= 2) {
559 args[1].type = CTRACE_ARGUMENT_STRING;
560 args[1].name = arguments_[1].name;
561 args[1].u.s = arguments_[1].value;
562 arglist.n_args += 1;
563 }
564
565 const uint64_t time_scale = mx_ticks_per_second() / kMicrosecondsPerSecond;
566 const uint64_t start_time = LowTime() * time_scale;
567 const uint64_t end_time = HighTime() * time_scale;
568
569 switch (event_type()) {
570 case kBegin:
571 ctrace_write_duration_begin_event_record(writer, start_time, &thread,
572 &category, &name, &arglist);
573 break;
574 case kEnd:
575 ctrace_write_duration_end_event_record(writer, end_time, &thread,
576 &category, &name, &arglist);
577 break;
578 case kInstant:
579 ctrace_write_instant_event_record(writer, start_time, &thread, &category,
580 &name, CTRACE_SCOPE_THREAD, &arglist);
581 break;
582 case kAsyncBegin:
583 ctrace_write_async_begin_event_record(
584 writer, start_time, &thread, &category, &name, AsyncId(), &arglist);
585 break;
586 case kAsyncEnd:
587 ctrace_write_async_end_event_record(writer, end_time, &thread, &category,
588 &name, AsyncId(), &arglist);
589 break;
590 case kAsyncInstant:
591 ctrace_write_async_instant_event_record(
592 writer, start_time, &thread, &category, &name, AsyncId(), &arglist);
593 break;
594 case kDuration:
595 ctrace_write_duration_event_record(writer, start_time, end_time, &thread,
596 &category, &name, &arglist);
597 break;
598 case kFlowBegin:
599 ctrace_write_flow_begin_event_record(
600 writer, start_time, &thread, &category, &name, AsyncId(), &arglist);
601 break;
602 case kFlowStep:
603 ctrace_write_flow_step_event_record(
604 writer, start_time, &thread, &category, &name, AsyncId(), &arglist);
605 break;
606 case kFlowEnd:
607 ctrace_write_flow_end_event_record(writer, start_time, &thread, &category,
608 &name, AsyncId(), &arglist);
609 break;
610 default:
611 // TODO(zra): Figure out what to do with kCounter and kMetadata.
612 break;
613 }
614 ctrace_writer_release(writer);
615 }
616 #endif
617
618 intptr_t TimelineEvent::PrintSystrace(char* buffer, intptr_t buffer_size) {
619 ASSERT(buffer != NULL);
620 ASSERT(buffer_size > 0);
621 buffer[0] = '\0';
622 intptr_t length = 0;
623 int64_t pid = OS::ProcessId();
624 switch (event_type()) {
625 case kBegin: {
626 length = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid, label());
627 } break;
628 case kEnd: {
629 length = OS::SNPrint(buffer, buffer_size, "E");
630 } break;
631 case kCounter: {
632 if (arguments_length_ > 0) {
633 // We only report the first counter value.
634 length = OS::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
635 label(), arguments_[0].value);
636 }
637 }
638 default:
639 // Ignore event types that we cannot serialize to the Systrace format.
640 break;
641 }
642 return length;
643 }
644
645 void TimelineEvent::Complete() { 520 void TimelineEvent::Complete() {
646 TimelineEventRecorder* recorder = Timeline::recorder(); 521 TimelineEventRecorder* recorder = Timeline::recorder();
647 if (recorder != NULL) { 522 if (recorder != NULL) {
648 recorder->CompleteEvent(this); 523 recorder->CompleteEvent(this);
649 } 524 }
650 } 525 }
651 526
652 void TimelineEvent::FreeArguments() { 527 void TimelineEvent::FreeArguments() {
653 if (arguments_ == NULL) { 528 if (arguments_ == NULL) {
654 return; 529 return;
(...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after
1417 return ThreadBlockStartEvent(); 1292 return ThreadBlockStartEvent();
1418 } 1293 }
1419 1294
1420 void TimelineEventFixedBufferRecorder::CompleteEvent(TimelineEvent* event) { 1295 void TimelineEventFixedBufferRecorder::CompleteEvent(TimelineEvent* event) {
1421 if (event == NULL) { 1296 if (event == NULL) {
1422 return; 1297 return;
1423 } 1298 }
1424 ThreadBlockCompleteEvent(event); 1299 ThreadBlockCompleteEvent(event);
1425 } 1300 }
1426 1301
1427 TimelineEventSystraceRecorder::TimelineEventSystraceRecorder(intptr_t capacity)
1428 : TimelineEventFixedBufferRecorder(capacity), systrace_fd_(-1) {
1429 #if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
1430 const char* kSystracePath = "/sys/kernel/debug/tracing/trace_marker";
1431 systrace_fd_ = open(kSystracePath, O_WRONLY);
1432 if ((systrace_fd_ < 0) && FLAG_trace_timeline) {
1433 OS::PrintErr("TimelineEventSystraceRecorder: Could not open `%s`\n",
1434 kSystracePath);
1435 }
1436 #else
1437 OS::PrintErr(
1438 "Warning: The systrace timeline recorder is equivalent to the"
1439 "ring recorder on this platform.");
1440 #endif
1441 }
1442
1443 TimelineEventSystraceRecorder::~TimelineEventSystraceRecorder() {
1444 #if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
1445 if (systrace_fd_ >= 0) {
1446 close(systrace_fd_);
1447 }
1448 #endif
1449 }
1450
1451 TimelineEventBlock* TimelineEventSystraceRecorder::GetNewBlockLocked() {
1452 // TODO(johnmccutchan): This function should only hand out blocks
1453 // which have been marked as finished.
1454 if (block_cursor_ == num_blocks_) {
1455 block_cursor_ = 0;
1456 }
1457 TimelineEventBlock* block = blocks_[block_cursor_++];
1458 block->Reset();
1459 block->Open();
1460 return block;
1461 }
1462
1463 void TimelineEventSystraceRecorder::CompleteEvent(TimelineEvent* event) {
1464 if (event == NULL) {
1465 return;
1466 }
1467 #if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX)
1468 if (systrace_fd_ >= 0) {
1469 // Serialize to the systrace format.
1470 const intptr_t kBufferLength = 1024;
1471 char buffer[kBufferLength];
1472 const intptr_t event_length =
1473 event->PrintSystrace(&buffer[0], kBufferLength);
1474 if (event_length > 0) {
1475 ssize_t __result;
1476 // Repeatedly attempt the write while we are being interrupted.
1477 do {
1478 __result = write(systrace_fd_, buffer, event_length);
1479 } while ((__result == -1L) && (errno == EINTR));
1480 }
1481 }
1482 #endif
1483 ThreadBlockCompleteEvent(event);
1484 }
1485
1486 #if defined(HOST_OS_FUCHSIA)
1487 TimelineEventFuchsiaRecorder::TimelineEventFuchsiaRecorder(intptr_t capacity)
1488 : TimelineEventFixedBufferRecorder(capacity) {}
1489
1490
1491 TimelineEventBlock* TimelineEventFuchsiaRecorder::GetNewBlockLocked() {
1492 // TODO(johnmccutchan): This function should only hand out blocks
1493 // which have been marked as finished.
1494 if (block_cursor_ == num_blocks_) {
1495 block_cursor_ = 0;
1496 }
1497 TimelineEventBlock* block = blocks_[block_cursor_++];
1498 block->Reset();
1499 block->Open();
1500 return block;
1501 }
1502
1503 void TimelineEventFuchsiaRecorder::CompleteEvent(TimelineEvent* event) {
1504 if (event == NULL) {
1505 return;
1506 }
1507 event->EmitFuchsiaEvent();
1508 ThreadBlockCompleteEvent(event);
1509 }
1510 #endif // defined(HOST_OS_FUCHSIA)
1511
1512 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { 1302 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() {
1513 // TODO(johnmccutchan): This function should only hand out blocks 1303 // TODO(johnmccutchan): This function should only hand out blocks
1514 // which have been marked as finished. 1304 // which have been marked as finished.
1515 if (block_cursor_ == num_blocks_) { 1305 if (block_cursor_ == num_blocks_) {
1516 block_cursor_ = 0; 1306 block_cursor_ = 0;
1517 } 1307 }
1518 TimelineEventBlock* block = blocks_[block_cursor_++]; 1308 TimelineEventBlock* block = blocks_[block_cursor_++];
1519 block->Reset(); 1309 block->Reset();
1520 block->Open(); 1310 block->Open();
1521 return block; 1311 return block;
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1815 return current_ != NULL; 1605 return current_ != NULL;
1816 } 1606 }
1817 1607
1818 TimelineEventBlock* TimelineEventBlockIterator::Next() { 1608 TimelineEventBlock* TimelineEventBlockIterator::Next() {
1819 ASSERT(current_ != NULL); 1609 ASSERT(current_ != NULL);
1820 TimelineEventBlock* r = current_; 1610 TimelineEventBlock* r = current_;
1821 current_ = current_->next(); 1611 current_ = current_->next();
1822 return r; 1612 return r;
1823 } 1613 }
1824 1614
1615 void DartCommonTimelineEventHelpers::ReportTaskEvent(Thread* thread,
1616 Zone* zone,
1617 TimelineEvent* event,
1618 int64_t start,
1619 int64_t id,
1620 const char* phase,
1621 const char* category,
1622 const char* name,
1623 const char* args) {
1624 const int64_t pid = OS::ProcessId();
1625 OSThread* os_thread = thread->os_thread();
1626 ASSERT(os_thread != NULL);
1627 const int64_t tid = OSThread::ThreadIdToIntPtr(os_thread->trace_id());
1628 ASSERT(phase != NULL);
1629 ASSERT((phase[0] == 'n') || (phase[0] == 'b') || (phase[0] == 'e'));
1630 ASSERT(phase[1] == '\0');
1631 char* json = OS::SCreate(
1632 zone,
1633 "{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64 ",\"pid\":%" Pd64
1634 ","
1635 "\"ts\":%" Pd64 ",\"ph\":\"%s\",\"id\":%" Pd64 ", \"args\":%s}",
1636 name, category, tid, pid, start, phase, id, args);
1637 switch (phase[0]) {
1638 case 'n':
1639 event->AsyncInstant("", id, start);
1640 break;
1641 case 'b':
1642 event->AsyncBegin("", id, start);
1643 break;
1644 case 'e':
1645 event->AsyncEnd("", id, start);
1646 break;
1647 default:
1648 UNREACHABLE();
1649 }
1650
1651 // json was allocated in the zone and a copy will be stored in event.
1652 event->CompleteWithPreSerializedJSON(json);
1653 }
1654
1655 void DartCommonTimelineEventHelpers::ReportCompleteEvent(Thread* thread,
1656 Zone* zone,
1657 TimelineEvent* event,
1658 int64_t start,
1659 int64_t start_cpu,
1660 const char* category,
1661 const char* name,
1662 const char* args) {
1663 const int64_t end = OS::GetCurrentMonotonicMicros();
1664 const int64_t end_cpu = OS::GetCurrentThreadCPUMicros();
1665 const int64_t duration = end - start;
1666 const int64_t duration_cpu = end_cpu - start_cpu;
1667 const int64_t pid = OS::ProcessId();
1668 OSThread* os_thread = thread->os_thread();
1669 ASSERT(os_thread != NULL);
1670 const int64_t tid = OSThread::ThreadIdToIntPtr(os_thread->trace_id());
1671
1672 char* json = NULL;
1673 if ((start_cpu != -1) && (end_cpu != -1)) {
1674 json = OS::SCreate(
1675 zone,
1676 "{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64 ",\"pid\":%" Pd64
1677 ","
1678 "\"ts\":%" Pd64 ",\"ph\":\"X\",\"dur\":%" Pd64
1679 ","
1680 "\"tdur\":%" Pd64 ",\"args\":%s}",
1681 name, category, tid, pid, start, duration, duration_cpu, args);
1682 } else {
1683 json = OS::SCreate(
1684 zone,
1685 "{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64 ",\"pid\":%" Pd64
1686 ","
1687 "\"ts\":%" Pd64 ",\"ph\":\"X\",\"dur\":%" Pd64 ",\"args\":%s}",
1688 name, category, tid, pid, start, duration, args);
1689 }
1690 ASSERT(json != NULL);
1691
1692 event->Duration("", start, end, start_cpu, end_cpu);
1693 // json was allocated in the zone and a copy will be stored in event.
1694 event->CompleteWithPreSerializedJSON(json);
1695 }
1696
1697 void DartCommonTimelineEventHelpers::ReportInstantEvent(Thread* thread,
1698 Zone* zone,
1699 TimelineEvent* event,
1700 int64_t start,
1701 const char* category,
1702 const char* name,
1703 const char* args) {
1704 const int64_t pid = OS::ProcessId();
1705 OSThread* os_thread = thread->os_thread();
1706 ASSERT(os_thread != NULL);
1707 const int64_t tid = OSThread::ThreadIdToIntPtr(os_thread->trace_id());
1708
1709 char* json = OS::SCreate(zone,
1710 "{\"name\":\"%s\",\"cat\":\"%s\",\"tid\":%" Pd64
1711 ",\"pid\":%" Pd64
1712 ","
1713 "\"ts\":%" Pd64 ",\"ph\":\"I\",\"args\":%s}",
1714 name, category, tid, pid, start, args);
1715
1716 event->Instant("", start);
1717 // json was allocated in the zone and a copy will be stored in event.
1718 event->CompleteWithPreSerializedJSON(json);
1719 }
1720
1825 } // namespace dart 1721 } // namespace dart
1826 1722
1827 #endif // !PRODUCT 1723 #endif // !PRODUCT
OLDNEW
« no previous file with comments | « runtime/vm/timeline.h ('k') | runtime/vm/timeline_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698