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

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

Issue 1834383002: Add a timeline recorder that drops new events after its buffer is full. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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/service_event.h" 13 #include "vm/service_event.h"
14 #include "vm/thread.h" 14 #include "vm/thread.h"
15 #include "vm/timeline.h" 15 #include "vm/timeline.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 #ifndef PRODUCT 19 #ifndef PRODUCT
20 20
21 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline"); 21 DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
22 DEFINE_FLAG(bool, startup_timeline, false, "Record the startup timeline");
22 DEFINE_FLAG(bool, trace_timeline, false, 23 DEFINE_FLAG(bool, trace_timeline, false,
23 "Trace timeline backend"); 24 "Trace timeline backend");
24 DEFINE_FLAG(bool, trace_timeline_analysis, false, 25 DEFINE_FLAG(bool, trace_timeline_analysis, false,
25 "Trace timeline analysis backend"); 26 "Trace timeline analysis backend");
26 DEFINE_FLAG(bool, timing, false, 27 DEFINE_FLAG(bool, timing, false,
27 "Dump isolate timing information from timeline."); 28 "Dump isolate timing information from timeline.");
28 DEFINE_FLAG(charp, timeline_dir, NULL, 29 DEFINE_FLAG(charp, timeline_dir, NULL,
29 "Enable all timeline trace streams and output VM global trace " 30 "Enable all timeline trace streams and output VM global trace "
30 "into specified directory."); 31 "into specified directory.");
31 DEFINE_FLAG(charp, timeline_streams, NULL, 32 DEFINE_FLAG(charp, timeline_streams, NULL,
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 } 105 }
105 for (intptr_t i = 0; i < streams->length(); i++) { 106 for (intptr_t i = 0; i < streams->length(); i++) {
106 free((*streams)[i]); 107 free((*streams)[i]);
107 } 108 }
108 delete streams; 109 delete streams;
109 } 110 }
110 111
111 112
112 // Returns true if |streams| contains |stream| or "all". Not case sensitive. 113 // Returns true if |streams| contains |stream| or "all". Not case sensitive.
113 static bool HasStream(MallocGrowableArray<char*>* streams, const char* stream) { 114 static bool HasStream(MallocGrowableArray<char*>* streams, const char* stream) {
114 if ((FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline) { 115 if ((FLAG_timeline_dir != NULL) ||
116 FLAG_timing || FLAG_complete_timeline || FLAG_startup_timeline) {
115 return true; 117 return true;
116 } 118 }
117 for (intptr_t i = 0; i < streams->length(); i++) { 119 for (intptr_t i = 0; i < streams->length(); i++) {
118 const char* checked_stream = (*streams)[i]; 120 const char* checked_stream = (*streams)[i];
119 if ((strstr(checked_stream, "all") != NULL) || 121 if ((strstr(checked_stream, "all") != NULL) ||
120 (strstr(checked_stream, stream) != NULL)) { 122 (strstr(checked_stream, stream) != NULL)) {
121 return true; 123 return true;
122 } 124 }
123 } 125 }
124 return false; 126 return false;
125 } 127 }
126 128
127 129
128 void Timeline::InitOnce() { 130 void Timeline::InitOnce() {
129 ASSERT(recorder_ == NULL); 131 ASSERT(recorder_ == NULL);
130 // Default to ring recorder being enabled. 132 // Default to ring recorder being enabled.
131 const bool use_ring_recorder = true; 133 const bool use_ring_recorder = true;
132 // Some flags require that we use the endless recorder. 134 // Some flags require that we use the endless recorder.
133 const bool use_endless_recorder = 135 const bool use_endless_recorder =
134 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline; 136 (FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
135 if (use_endless_recorder) { 137 if (use_endless_recorder) {
136 recorder_ = new TimelineEventEndlessRecorder(); 138 recorder_ = new TimelineEventEndlessRecorder();
139 } else if (FLAG_startup_timeline) {
140 recorder_ = new TimelineEventStartupRecorder();
137 } else if (use_ring_recorder) { 141 } else if (use_ring_recorder) {
138 recorder_ = new TimelineEventRingRecorder(); 142 recorder_ = new TimelineEventRingRecorder();
139 } 143 }
140 enabled_streams_ = GetEnabledByDefaultTimelineStreams(); 144 enabled_streams_ = GetEnabledByDefaultTimelineStreams();
141 // Global overrides. 145 // Global overrides.
142 #define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \ 146 #define TIMELINE_STREAM_FLAG_DEFAULT(name, not_used) \
143 stream_##name##_enabled_ = HasStream(enabled_streams_, #name); \ 147 stream_##name##_enabled_ = HasStream(enabled_streams_, #name); \
144 stream_##name##_.Init(#name, \ 148 stream_##name##_.Init(#name, \
145 stream_##name##_enabled_, \ 149 stream_##name##_enabled_, \
146 &stream_##name##_enabled_); 150 &stream_##name##_enabled_);
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after
1047 block->Finish(); 1051 block->Finish();
1048 } 1052 }
1049 1053
1050 1054
1051 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() { 1055 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() {
1052 MutexLocker ml(&lock_); 1056 MutexLocker ml(&lock_);
1053 return GetNewBlockLocked(); 1057 return GetNewBlockLocked();
1054 } 1058 }
1055 1059
1056 1060
1057 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) 1061 TimelineEventFixedBufferRecorder::TimelineEventFixedBufferRecorder(
1062 intptr_t capacity)
1058 : blocks_(NULL), 1063 : blocks_(NULL),
1059 capacity_(capacity), 1064 capacity_(capacity),
1060 num_blocks_(0), 1065 num_blocks_(0),
1061 block_cursor_(0) { 1066 block_cursor_(0) {
1062 // Capacity must be a multiple of TimelineEventBlock::kBlockSize 1067 // Capacity must be a multiple of TimelineEventBlock::kBlockSize
1063 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); 1068 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0);
1064 // Allocate blocks array. 1069 // Allocate blocks array.
1065 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; 1070 num_blocks_ = capacity / TimelineEventBlock::kBlockSize;
1066 blocks_ = 1071 blocks_ =
1067 reinterpret_cast<TimelineEventBlock**>( 1072 reinterpret_cast<TimelineEventBlock**>(
1068 calloc(num_blocks_, sizeof(TimelineEventBlock*))); 1073 calloc(num_blocks_, sizeof(TimelineEventBlock*)));
1069 // Allocate each block. 1074 // Allocate each block.
1070 for (intptr_t i = 0; i < num_blocks_; i++) { 1075 for (intptr_t i = 0; i < num_blocks_; i++) {
1071 blocks_[i] = new TimelineEventBlock(i); 1076 blocks_[i] = new TimelineEventBlock(i);
1072 } 1077 }
1073 // Chain blocks together. 1078 // Chain blocks together.
1074 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { 1079 for (intptr_t i = 0; i < num_blocks_ - 1; i++) {
1075 blocks_[i]->set_next(blocks_[i + 1]); 1080 blocks_[i]->set_next(blocks_[i + 1]);
1076 } 1081 }
1077 } 1082 }
1078 1083
1079 1084
1080 TimelineEventRingRecorder::~TimelineEventRingRecorder() { 1085 TimelineEventFixedBufferRecorder::~TimelineEventFixedBufferRecorder() {
1081 // Delete all blocks. 1086 // Delete all blocks.
1082 for (intptr_t i = 0; i < num_blocks_; i++) { 1087 for (intptr_t i = 0; i < num_blocks_; i++) {
1083 TimelineEventBlock* block = blocks_[i]; 1088 TimelineEventBlock* block = blocks_[i];
1084 delete block; 1089 delete block;
1085 } 1090 }
1086 free(blocks_); 1091 free(blocks_);
1087 } 1092 }
1088 1093
1089 1094
1090 void TimelineEventRingRecorder::PrintJSONEvents( 1095 void TimelineEventFixedBufferRecorder::PrintJSONEvents(
1091 JSONArray* events, 1096 JSONArray* events,
1092 TimelineEventFilter* filter) { 1097 TimelineEventFilter* filter) {
1093 if (!FLAG_support_service) { 1098 if (!FLAG_support_service) {
1094 return; 1099 return;
1095 } 1100 }
1096 MutexLocker ml(&lock_); 1101 MutexLocker ml(&lock_);
1097 intptr_t block_offset = FindOldestBlockIndex(); 1102 intptr_t block_offset = FindOldestBlockIndex();
1098 if (block_offset == -1) { 1103 if (block_offset == -1) {
1099 // All blocks are empty. 1104 // All blocks are empty.
1100 return; 1105 return;
1101 } 1106 }
1102 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 1107 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
1103 TimelineEventBlock* block = 1108 TimelineEventBlock* block =
1104 blocks_[(block_idx + block_offset) % num_blocks_]; 1109 blocks_[(block_idx + block_offset) % num_blocks_];
1105 if (!filter->IncludeBlock(block)) { 1110 if (!filter->IncludeBlock(block)) {
1106 continue; 1111 continue;
1107 } 1112 }
1108 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) { 1113 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
1109 TimelineEvent* event = block->At(event_idx); 1114 TimelineEvent* event = block->At(event_idx);
1110 if (filter->IncludeEvent(event) && 1115 if (filter->IncludeEvent(event) &&
1111 event->Within(filter->time_origin_micros(), 1116 event->Within(filter->time_origin_micros(),
1112 filter->time_extent_micros())) { 1117 filter->time_extent_micros())) {
1113 events->AddValue(event); 1118 events->AddValue(event);
1114 } 1119 }
1115 } 1120 }
1116 } 1121 }
1117 } 1122 }
1118 1123
1119 1124
1120 void TimelineEventRingRecorder::PrintJSON(JSONStream* js, 1125 void TimelineEventFixedBufferRecorder::PrintJSON(JSONStream* js,
1121 TimelineEventFilter* filter) { 1126 TimelineEventFilter* filter) {
1122 if (!FLAG_support_service) { 1127 if (!FLAG_support_service) {
1123 return; 1128 return;
1124 } 1129 }
1125 JSONObject topLevel(js); 1130 JSONObject topLevel(js);
1126 topLevel.AddProperty("type", "_Timeline"); 1131 topLevel.AddProperty("type", "_Timeline");
1127 { 1132 {
1128 JSONArray events(&topLevel, "traceEvents"); 1133 JSONArray events(&topLevel, "traceEvents");
1129 PrintJSONMeta(&events); 1134 PrintJSONMeta(&events);
1130 PrintJSONEvents(&events, filter); 1135 PrintJSONEvents(&events, filter);
1131 } 1136 }
1132 } 1137 }
1133 1138
1134 1139
1135 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, 1140 void TimelineEventFixedBufferRecorder::PrintTraceEvent(
1136 TimelineEventFilter* filter) { 1141 JSONStream* js,
1142 TimelineEventFilter* filter) {
1137 if (!FLAG_support_service) { 1143 if (!FLAG_support_service) {
1138 return; 1144 return;
1139 } 1145 }
1140 JSONArray events(js); 1146 JSONArray events(js);
1141 PrintJSONEvents(&events, filter); 1147 PrintJSONEvents(&events, filter);
1142 } 1148 }
1143 1149
1144 1150
1145 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { 1151 TimelineEventBlock* TimelineEventFixedBufferRecorder::GetHeadBlockLocked() {
1146 return blocks_[0]; 1152 return blocks_[0];
1147 } 1153 }
1148 1154
1149 1155
1150 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() { 1156 void TimelineEventFixedBufferRecorder::Clear() {
1151 // TODO(johnmccutchan): This function should only hand out blocks
1152 // which have been marked as finished.
1153 if (block_cursor_ == num_blocks_) {
1154 block_cursor_ = 0;
1155 }
1156 TimelineEventBlock* block = blocks_[block_cursor_++];
1157 block->Reset();
1158 block->Open();
1159 return block;
1160 }
1161
1162
1163 void TimelineEventRingRecorder::Clear() {
1164 MutexLocker ml(&lock_); 1157 MutexLocker ml(&lock_);
1165 for (intptr_t i = 0; i < num_blocks_; i++) { 1158 for (intptr_t i = 0; i < num_blocks_; i++) {
1166 TimelineEventBlock* block = blocks_[i]; 1159 TimelineEventBlock* block = blocks_[i];
1167 block->Reset(); 1160 block->Reset();
1168 } 1161 }
1169 } 1162 }
1170 1163
1171 1164
1172 intptr_t TimelineEventRingRecorder::FindOldestBlockIndex() const { 1165 intptr_t TimelineEventFixedBufferRecorder::FindOldestBlockIndex() const {
1173 int64_t earliest_time = kMaxInt64; 1166 int64_t earliest_time = kMaxInt64;
1174 intptr_t earliest_index = -1; 1167 intptr_t earliest_index = -1;
1175 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) { 1168 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
1176 TimelineEventBlock* block = blocks_[block_idx]; 1169 TimelineEventBlock* block = blocks_[block_idx];
1177 if (block->IsEmpty()) { 1170 if (block->IsEmpty()) {
1178 // Skip empty blocks. 1171 // Skip empty blocks.
1179 continue; 1172 continue;
1180 } 1173 }
1181 if (block->LowerTimeBound() < earliest_time) { 1174 if (block->LowerTimeBound() < earliest_time) {
1182 earliest_time = block->LowerTimeBound(); 1175 earliest_time = block->LowerTimeBound();
1183 earliest_index = block_idx; 1176 earliest_index = block_idx;
1184 } 1177 }
1185 } 1178 }
1186 return earliest_index; 1179 return earliest_index;
1187 } 1180 }
1188 1181
1189 1182
1190 TimelineEvent* TimelineEventRingRecorder::StartEvent() { 1183 TimelineEvent* TimelineEventFixedBufferRecorder::StartEvent() {
1191 return ThreadBlockStartEvent(); 1184 return ThreadBlockStartEvent();
1192 } 1185 }
1193 1186
1194 1187
1195 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { 1188 void TimelineEventFixedBufferRecorder::CompleteEvent(TimelineEvent* event) {
1196 if (event == NULL) { 1189 if (event == NULL) {
1197 return; 1190 return;
1198 } 1191 }
1199 ThreadBlockCompleteEvent(event); 1192 ThreadBlockCompleteEvent(event);
1200 } 1193 }
1201 1194
1202 1195
1196 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() {
1197 // TODO(johnmccutchan): This function should only hand out blocks
1198 // which have been marked as finished.
1199 if (block_cursor_ == num_blocks_) {
1200 block_cursor_ = 0;
1201 }
1202 TimelineEventBlock* block = blocks_[block_cursor_++];
1203 block->Reset();
1204 block->Open();
1205 return block;
1206 }
1207
1208
1209 TimelineEventBlock* TimelineEventStartupRecorder::GetNewBlockLocked() {
1210 if (block_cursor_ == num_blocks_) {
1211 return NULL;
1212 }
1213 TimelineEventBlock* block = blocks_[block_cursor_++];
1214 block->Reset();
1215 block->Open();
1216 return block;
1217 }
1218
1219
1203 TimelineEventCallbackRecorder::TimelineEventCallbackRecorder() { 1220 TimelineEventCallbackRecorder::TimelineEventCallbackRecorder() {
1204 } 1221 }
1205 1222
1206 1223
1207 TimelineEventCallbackRecorder::~TimelineEventCallbackRecorder() { 1224 TimelineEventCallbackRecorder::~TimelineEventCallbackRecorder() {
1208 } 1225 }
1209 1226
1210 1227
1211 void TimelineEventCallbackRecorder::PrintJSON(JSONStream* js, 1228 void TimelineEventCallbackRecorder::PrintJSON(JSONStream* js,
1212 TimelineEventFilter* filter) { 1229 TimelineEventFilter* filter) {
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 TimelineEventBlock* TimelineEventBlockIterator::Next() { 1521 TimelineEventBlock* TimelineEventBlockIterator::Next() {
1505 ASSERT(current_ != NULL); 1522 ASSERT(current_ != NULL);
1506 TimelineEventBlock* r = current_; 1523 TimelineEventBlock* r = current_;
1507 current_ = current_->next(); 1524 current_ = current_->next();
1508 return r; 1525 return r;
1509 } 1526 }
1510 1527
1511 #endif // !PRODUCT 1528 #endif // !PRODUCT
1512 1529
1513 } // namespace dart 1530 } // 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