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

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

Issue 1525913002: Observatory: Include profiler samples in the timeline view. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: + unit test Created 5 years 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 "vm/profiler_service.h" 5 #include "vm/profiler_service.h"
6 6
7 #include "vm/growable_array.h" 7 #include "vm/growable_array.h"
8 #include "vm/native_symbol.h" 8 #include "vm/native_symbol.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/os.h" 10 #include "vm/os.h"
(...skipping 779 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 } 790 }
791 } 791 }
792 792
793 ZoneGrowableArray<ProfileCode*> table_; 793 ZoneGrowableArray<ProfileCode*> table_;
794 }; 794 };
795 795
796 796
797 ProfileTrieNode::ProfileTrieNode(intptr_t table_index) 797 ProfileTrieNode::ProfileTrieNode(intptr_t table_index)
798 : table_index_(table_index), 798 : table_index_(table_index),
799 count_(0), 799 count_(0),
800 children_(0) { 800 children_(0),
801 frame_id_(-1) {
801 ASSERT(table_index_ >= 0); 802 ASSERT(table_index_ >= 0);
802 } 803 }
803 804
804 805
805 ProfileTrieNode::~ProfileTrieNode() { 806 ProfileTrieNode::~ProfileTrieNode() {
806 } 807 }
807 808
808 809
809 void ProfileTrieNode::SortChildren() { 810 void ProfileTrieNode::SortChildren() {
810 children_.Sort(ProfileTrieNodeCompare); 811 children_.Sort(ProfileTrieNodeCompare);
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId); 1050 RegisterProfileCodeTag(VMTag::kInlineEndCodeTagId);
1050 } 1051 }
1051 1052
1052 void FilterSamples() { 1053 void FilterSamples() {
1053 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler); 1054 ScopeTimer sw("ProfileBuilder::FilterSamples", FLAG_trace_profiler);
1054 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 1055 SampleBuffer* sample_buffer = Profiler::sample_buffer();
1055 if (sample_buffer == NULL) { 1056 if (sample_buffer == NULL) {
1056 return; 1057 return;
1057 } 1058 }
1058 samples_ = sample_buffer->BuildProcessedSampleBuffer(filter_); 1059 samples_ = sample_buffer->BuildProcessedSampleBuffer(filter_);
1060 profile_->samples_ = samples_;
1059 profile_->sample_count_ = samples_->length(); 1061 profile_->sample_count_ = samples_->length();
1060 } 1062 }
1061 1063
1062 void UpdateMinMaxTimes(int64_t timestamp) { 1064 void UpdateMinMaxTimes(int64_t timestamp) {
1063 profile_->min_time_ = 1065 profile_->min_time_ =
1064 timestamp < profile_->min_time_ ? timestamp : profile_->min_time_; 1066 timestamp < profile_->min_time_ ? timestamp : profile_->min_time_;
1065 profile_->max_time_ = 1067 profile_->max_time_ =
1066 timestamp > profile_->max_time_ ? timestamp : profile_->max_time_; 1068 timestamp > profile_->max_time_ ? timestamp : profile_->max_time_;
1067 } 1069 }
1068 1070
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 current = AppendTruncatedTag(current); 1328 current = AppendTruncatedTag(current);
1327 } 1329 }
1328 1330
1329 // Walk the sampled PCs. 1331 // Walk the sampled PCs.
1330 for (intptr_t frame_index = sample->length() - 1; 1332 for (intptr_t frame_index = sample->length() - 1;
1331 frame_index >= 0; 1333 frame_index >= 0;
1332 frame_index--) { 1334 frame_index--) {
1333 ASSERT(sample->At(frame_index) != 0); 1335 ASSERT(sample->At(frame_index) != 0);
1334 current = ProcessFrame(current, sample_index, sample, frame_index); 1336 current = ProcessFrame(current, sample_index, sample, frame_index);
1335 } 1337 }
1338
1339 sample->set_timeline_trie(current);
1336 } 1340 }
1337 } 1341 }
1338 1342
1339 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) { 1343 void BuildExclusiveFunctionTrie(ProfileFunctionTrieNode* root) {
1340 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie", 1344 ScopeTimer sw("ProfileBuilder::BuildExclusiveFunctionTrie",
1341 FLAG_trace_profiler); 1345 FLAG_trace_profiler);
1342 ASSERT(tick_functions_); 1346 ASSERT(tick_functions_);
1343 for (intptr_t sample_index = 0; 1347 for (intptr_t sample_index = 0;
1344 sample_index < samples_->length(); 1348 sample_index < samples_->length();
1345 sample_index++) { 1349 sample_index++) {
(...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after
1966 bool tick_functions_; 1970 bool tick_functions_;
1967 bool inclusive_tree_; 1971 bool inclusive_tree_;
1968 1972
1969 ProcessedSampleBuffer* samples_; 1973 ProcessedSampleBuffer* samples_;
1970 ProfileInfoKind info_kind_; 1974 ProfileInfoKind info_kind_;
1971 }; // ProfileBuilder. 1975 }; // ProfileBuilder.
1972 1976
1973 1977
1974 Profile::Profile(Isolate* isolate) 1978 Profile::Profile(Isolate* isolate)
1975 : isolate_(isolate), 1979 : isolate_(isolate),
1980 zone_(Thread::Current()->zone()),
1981 samples_(NULL),
1976 live_code_(NULL), 1982 live_code_(NULL),
1977 dead_code_(NULL), 1983 dead_code_(NULL),
1978 tag_code_(NULL), 1984 tag_code_(NULL),
1979 functions_(NULL), 1985 functions_(NULL),
1980 dead_code_index_offset_(-1), 1986 dead_code_index_offset_(-1),
1981 tag_code_index_offset_(-1), 1987 tag_code_index_offset_(-1),
1982 min_time_(kMaxInt64), 1988 min_time_(kMaxInt64),
1983 max_time_(0) { 1989 max_time_(0) {
1984 ASSERT(isolate_ != NULL); 1990 ASSERT(isolate_ != NULL);
1985 for (intptr_t i = 0; i < kNumTrieKinds; i++) { 1991 for (intptr_t i = 0; i < kNumTrieKinds; i++) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2027 index -= tag_code_index_offset_; 2033 index -= tag_code_index_offset_;
2028 return tag_code_->At(index); 2034 return tag_code_->At(index);
2029 } 2035 }
2030 2036
2031 2037
2032 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) { 2038 ProfileTrieNode* Profile::GetTrieRoot(TrieKind trie_kind) {
2033 return roots_[static_cast<intptr_t>(trie_kind)]; 2039 return roots_[static_cast<intptr_t>(trie_kind)];
2034 } 2040 }
2035 2041
2036 2042
2037 void Profile::PrintJSON(JSONStream* stream) { 2043 void Profile::PrintTimelineFrameJSON(JSONObject* frames,
2038 ScopeTimer sw("Profile::PrintJSON", FLAG_trace_profiler); 2044 ProfileTrieNode* current,
2045 ProfileTrieNode* parent,
2046 intptr_t* next_id) {
2047 ASSERT(current->frame_id() == -1);
2048 intptr_t id = *next_id;
Cutch 2015/12/15 21:54:59 const intptr_t id = *next_id++;
rmacnak 2015/12/16 00:14:21 Doesn't mean the same thing. Led to the crashes.
2049 *next_id = id + 1;
2050 current->set_frame_id(id);
2051 ASSERT(current->frame_id() != -1);
2052
2053 {
2054 // The samples from many isolates may be merged into a single timeline,
2055 // so prefix frames id with the isolate.
2056 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2057 const char* key = zone_->PrintToString("f%" Pd "-%" Pd,
2058 isolate_id, current->frame_id());
2059 JSONObject frame(frames, key);
2060 frame.AddProperty("category", "Dart");
Cutch 2015/12/15 21:54:59 Do we need to emit a category for each stack frame
rmacnak 2015/12/16 00:14:20 The samples all have random looking colors if this
2061 ProfileFunction* func = GetFunction(current->table_index());
2062 frame.AddProperty("name", func->Name());
2063 if (parent != NULL) {
2064 ASSERT(parent->frame_id() != -1);
2065 frame.AddPropertyF("parent", "f%" Pd "-%" Pd,
2066 isolate_id, parent->frame_id());
2067 }
2068 }
2069
2070 for (intptr_t i = 0; i < current->NumChildren(); i++) {
2071 ProfileTrieNode* child = current->At(i);
2072 PrintTimelineFrameJSON(frames, child, current, next_id);
2073 }
2074 }
2075
2076
2077 void Profile::PrintTimelineJSON(JSONStream* stream) {
2078 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler);
2079 JSONObject obj(stream);
2080 obj.AddProperty("type", "_CpuProfileTimeline");
2081 obj.AddProperty("samplePeriod",
2082 static_cast<intptr_t>(FLAG_profile_period));
2083 obj.AddProperty("stackDepth",
Cutch 2015/12/15 21:54:59 Factor this out into a PrintProfileHeaderJson() an
2084 static_cast<intptr_t>(FLAG_max_profile_depth));
2085 obj.AddProperty("sampleCount", sample_count());
2086 obj.AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
2087 {
2088 JSONObject frames(&obj, "stackFrames");
2089 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction);
2090 intptr_t next_id = 0;
2091 PrintTimelineFrameJSON(&frames, root, NULL, &next_id);
2092 }
2093 {
2094 JSONArray events(&obj, "traceEvents");
2095 intptr_t pid = OS::ProcessId();
2096 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2097 for (intptr_t sample_index = 0;
2098 sample_index < samples_->length();
2099 sample_index++) {
2100 ProcessedSample* sample = samples_->At(sample_index);
2101 JSONObject event(&events);
2102 event.AddProperty("name", "DartSample");
Cutch 2015/12/15 21:54:59 Can we shorten the name to be "DS" or even drop it
rmacnak 2015/12/16 00:14:20 Works when dropped.
2103 event.AddProperty("ph", "P"); // kind = sample event
2104 event.AddProperty64("pid", pid);
2105 event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
2106 event.AddPropertyTimeMicros("ts", sample->timestamp());
2107 event.AddProperty("cat", VMTag::TagName(sample->vm_tag()));
Cutch 2015/12/15 21:54:59 cat should be hard coded to "Dart"
rmacnak 2015/12/16 00:14:20 Done.
2108
2109 ProfileTrieNode* trie = sample->timeline_trie();
2110 ASSERT(trie->frame_id() != -1);
2111 event.AddPropertyF("sf", "f%" Pd "-%" Pd,
2112 isolate_id, trie->frame_id());
2113 }
2114 }
2115 }
2116
2117
2118 void Profile::PrintProfileJSON(JSONStream* stream) {
2119 ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
2039 JSONObject obj(stream); 2120 JSONObject obj(stream);
2040 obj.AddProperty("type", "_CpuProfile"); 2121 obj.AddProperty("type", "_CpuProfile");
2041 obj.AddProperty("samplePeriod", 2122 obj.AddProperty("samplePeriod",
2042 static_cast<intptr_t>(FLAG_profile_period)); 2123 static_cast<intptr_t>(FLAG_profile_period));
2043 obj.AddProperty("stackDepth", 2124 obj.AddProperty("stackDepth",
2044 static_cast<intptr_t>(FLAG_max_profile_depth)); 2125 static_cast<intptr_t>(FLAG_max_profile_depth));
2045 obj.AddProperty("sampleCount", sample_count()); 2126 obj.AddProperty("sampleCount", sample_count());
2046 obj.AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan())); 2127 obj.AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
2047 { 2128 {
2048 JSONArray codes(&obj, "codes"); 2129 JSONArray codes(&obj, "codes");
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 intptr_t ProfileTrieWalker::SiblingCount() { 2270 intptr_t ProfileTrieWalker::SiblingCount() {
2190 ASSERT(parent_ != NULL); 2271 ASSERT(parent_ != NULL);
2191 return parent_->NumChildren(); 2272 return parent_->NumChildren();
2192 } 2273 }
2193 2274
2194 2275
2195 void ProfilerService::PrintJSONImpl(Thread* thread, 2276 void ProfilerService::PrintJSONImpl(Thread* thread,
2196 JSONStream* stream, 2277 JSONStream* stream,
2197 Profile::TagOrder tag_order, 2278 Profile::TagOrder tag_order,
2198 intptr_t extra_tags, 2279 intptr_t extra_tags,
2199 SampleFilter* filter) { 2280 SampleFilter* filter,
2281 bool as_timeline) {
2200 Isolate* isolate = thread->isolate(); 2282 Isolate* isolate = thread->isolate();
2201 // Disable thread interrupts while processing the buffer. 2283 // Disable thread interrupts while processing the buffer.
2202 DisableThreadInterruptsScope dtis(thread); 2284 DisableThreadInterruptsScope dtis(thread);
2203 2285
2204 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 2286 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2205 if (sample_buffer == NULL) { 2287 if (sample_buffer == NULL) {
2206 stream->PrintError(kFeatureDisabled, NULL); 2288 stream->PrintError(kFeatureDisabled, NULL);
2207 return; 2289 return;
2208 } 2290 }
2209 2291
2210 { 2292 {
2211 StackZone zone(thread); 2293 StackZone zone(thread);
2212 HANDLESCOPE(thread); 2294 HANDLESCOPE(thread);
2213 Profile profile(isolate); 2295 Profile profile(isolate);
2214 profile.Build(thread, filter, tag_order, extra_tags); 2296 profile.Build(thread, filter, tag_order, extra_tags);
2215 profile.PrintJSON(stream); 2297 if (as_timeline) {
2298 profile.PrintTimelineJSON(stream);
2299 } else {
2300 profile.PrintProfileJSON(stream);
2301 }
2216 } 2302 }
2217 } 2303 }
2218 2304
2219 2305
2220 class NoAllocationSampleFilter : public SampleFilter { 2306 class NoAllocationSampleFilter : public SampleFilter {
2221 public: 2307 public:
2222 explicit NoAllocationSampleFilter(Isolate* isolate) 2308 explicit NoAllocationSampleFilter(Isolate* isolate)
2223 : SampleFilter(isolate) { 2309 : SampleFilter(isolate) {
2224 } 2310 }
2225 2311
2226 bool FilterSample(Sample* sample) { 2312 bool FilterSample(Sample* sample) {
2227 return !sample->is_allocation_sample(); 2313 return !sample->is_allocation_sample();
2228 } 2314 }
2229 }; 2315 };
2230 2316
2231 2317
2232 void ProfilerService::PrintJSON(JSONStream* stream, 2318 void ProfilerService::PrintJSON(JSONStream* stream,
2233 Profile::TagOrder tag_order, 2319 Profile::TagOrder tag_order,
2234 intptr_t extra_tags) { 2320 intptr_t extra_tags) {
2235 Thread* thread = Thread::Current(); 2321 Thread* thread = Thread::Current();
2236 Isolate* isolate = thread->isolate(); 2322 Isolate* isolate = thread->isolate();
2237 NoAllocationSampleFilter filter(isolate); 2323 NoAllocationSampleFilter filter(isolate);
2238 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter); 2324 const bool as_timeline = false;
2325 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline);
2239 } 2326 }
2240 2327
2241 2328
2242 class ClassAllocationSampleFilter : public SampleFilter { 2329 class ClassAllocationSampleFilter : public SampleFilter {
2243 public: 2330 public:
2244 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) 2331 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls)
2245 : SampleFilter(isolate), 2332 : SampleFilter(isolate),
2246 cls_(Class::Handle(cls.raw())) { 2333 cls_(Class::Handle(cls.raw())) {
2247 ASSERT(!cls_.IsNull()); 2334 ASSERT(!cls_.IsNull());
2248 } 2335 }
2249 2336
2250 bool FilterSample(Sample* sample) { 2337 bool FilterSample(Sample* sample) {
2251 return sample->is_allocation_sample() && 2338 return sample->is_allocation_sample() &&
2252 (sample->allocation_cid() == cls_.id()); 2339 (sample->allocation_cid() == cls_.id());
2253 } 2340 }
2254 2341
2255 private: 2342 private:
2256 const Class& cls_; 2343 const Class& cls_;
2257 }; 2344 };
2258 2345
2259 2346
2260 void ProfilerService::PrintAllocationJSON(JSONStream* stream, 2347 void ProfilerService::PrintAllocationJSON(JSONStream* stream,
2261 Profile::TagOrder tag_order, 2348 Profile::TagOrder tag_order,
2262 const Class& cls) { 2349 const Class& cls) {
2263 Thread* thread = Thread::Current(); 2350 Thread* thread = Thread::Current();
2264 Isolate* isolate = thread->isolate(); 2351 Isolate* isolate = thread->isolate();
2265 ClassAllocationSampleFilter filter(isolate, cls); 2352 ClassAllocationSampleFilter filter(isolate, cls);
2266 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter); 2353 const bool as_timeline = false;
2354 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2267 } 2355 }
2268 2356
2269 2357
2358 void ProfilerService::PrintTimelineJSON(JSONStream* stream,
2359 Profile::TagOrder tag_order) {
2360 Thread* thread = Thread::Current();
2361 Isolate* isolate = thread->isolate();
2362 NoAllocationSampleFilter filter(isolate);
2363 const bool as_timeline = true;
2364 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2365 }
2366
2367
2270 void ProfilerService::ClearSamples() { 2368 void ProfilerService::ClearSamples() {
2271 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 2369 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2272 if (sample_buffer == NULL) { 2370 if (sample_buffer == NULL) {
2273 return; 2371 return;
2274 } 2372 }
2275 2373
2276 Thread* thread = Thread::Current(); 2374 Thread* thread = Thread::Current();
2277 Isolate* isolate = thread->isolate(); 2375 Isolate* isolate = thread->isolate();
2278 2376
2279 // Disable thread interrupts while processing the buffer. 2377 // Disable thread interrupts while processing the buffer.
2280 DisableThreadInterruptsScope dtis(thread); 2378 DisableThreadInterruptsScope dtis(thread);
2281 2379
2282 ClearProfileVisitor clear_profile(isolate); 2380 ClearProfileVisitor clear_profile(isolate);
2283 sample_buffer->VisitSamples(&clear_profile); 2381 sample_buffer->VisitSamples(&clear_profile);
2284 } 2382 }
2285 2383
2286 } // namespace dart 2384 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698