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

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: 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
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | runtime/vm/service.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 "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::PrintHeaderJSON(JSONObject* obj) {
2038 ScopeTimer sw("Profile::PrintJSON", FLAG_trace_profiler); 2044 obj->AddProperty("samplePeriod",
2045 static_cast<intptr_t>(FLAG_profile_period));
2046 obj->AddProperty("stackDepth",
2047 static_cast<intptr_t>(FLAG_max_profile_depth));
2048 obj->AddProperty("sampleCount", sample_count());
2049 obj->AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
2050 }
2051
2052
2053 void Profile::PrintTimelineFrameJSON(JSONObject* frames,
2054 ProfileTrieNode* current,
2055 ProfileTrieNode* parent,
2056 intptr_t* next_id) {
2057 ASSERT(current->frame_id() == -1);
2058 const intptr_t id = *next_id;
2059 *next_id = id + 1;
2060 current->set_frame_id(id);
2061 ASSERT(current->frame_id() != -1);
2062
2063 {
2064 // The samples from many isolates may be merged into a single timeline,
2065 // so prefix frames id with the isolate.
2066 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2067 const char* key = zone_->PrintToString("%" Pd "-%" Pd,
2068 isolate_id, current->frame_id());
2069 JSONObject frame(frames, key);
2070 frame.AddProperty("category", "Dart");
2071 ProfileFunction* func = GetFunction(current->table_index());
2072 frame.AddProperty("name", func->Name());
2073 if (parent != NULL) {
2074 ASSERT(parent->frame_id() != -1);
2075 frame.AddPropertyF("parent", "%" Pd "-%" Pd,
2076 isolate_id, parent->frame_id());
2077 }
2078 }
2079
2080 for (intptr_t i = 0; i < current->NumChildren(); i++) {
2081 ProfileTrieNode* child = current->At(i);
2082 PrintTimelineFrameJSON(frames, child, current, next_id);
2083 }
2084 }
2085
2086
2087 void Profile::PrintTimelineJSON(JSONStream* stream) {
2088 ScopeTimer sw("Profile::PrintTimelineJSON", FLAG_trace_profiler);
2089 JSONObject obj(stream);
2090 obj.AddProperty("type", "_CpuProfileTimeline");
2091 PrintHeaderJSON(&obj);
2092 {
2093 JSONObject frames(&obj, "stackFrames");
2094 ProfileTrieNode* root = GetTrieRoot(kInclusiveFunction);
2095 intptr_t next_id = 0;
2096 PrintTimelineFrameJSON(&frames, root, NULL, &next_id);
2097 }
2098 {
2099 JSONArray events(&obj, "traceEvents");
2100 intptr_t pid = OS::ProcessId();
2101 intptr_t isolate_id = reinterpret_cast<intptr_t>(isolate_);
2102 for (intptr_t sample_index = 0;
2103 sample_index < samples_->length();
2104 sample_index++) {
2105 ProcessedSample* sample = samples_->At(sample_index);
2106 JSONObject event(&events);
2107 event.AddProperty("ph", "P"); // kind = sample event
2108 event.AddProperty64("pid", pid);
2109 event.AddProperty64("tid", OSThread::ThreadIdToIntPtr(sample->tid()));
2110 event.AddPropertyTimeMicros("ts", sample->timestamp());
2111 event.AddProperty("cat", "Dart");
2112
2113 ProfileTrieNode* trie = sample->timeline_trie();
2114 ASSERT(trie->frame_id() != -1);
2115 event.AddPropertyF("sf", "%" Pd "-%" Pd,
2116 isolate_id, trie->frame_id());
2117 }
2118 }
2119 }
2120
2121
2122 void Profile::PrintProfileJSON(JSONStream* stream) {
2123 ScopeTimer sw("Profile::PrintProfileJSON", FLAG_trace_profiler);
2039 JSONObject obj(stream); 2124 JSONObject obj(stream);
2040 obj.AddProperty("type", "_CpuProfile"); 2125 obj.AddProperty("type", "_CpuProfile");
2041 obj.AddProperty("samplePeriod", 2126 PrintHeaderJSON(&obj);
2042 static_cast<intptr_t>(FLAG_profile_period));
2043 obj.AddProperty("stackDepth",
2044 static_cast<intptr_t>(FLAG_max_profile_depth));
2045 obj.AddProperty("sampleCount", sample_count());
2046 obj.AddProperty("timeSpan", MicrosecondsToSeconds(GetTimeSpan()));
2047 { 2127 {
2048 JSONArray codes(&obj, "codes"); 2128 JSONArray codes(&obj, "codes");
2049 for (intptr_t i = 0; i < live_code_->length(); i++) { 2129 for (intptr_t i = 0; i < live_code_->length(); i++) {
2050 ProfileCode* code = live_code_->At(i); 2130 ProfileCode* code = live_code_->At(i);
2051 ASSERT(code != NULL); 2131 ASSERT(code != NULL);
2052 code->PrintToJSONArray(&codes); 2132 code->PrintToJSONArray(&codes);
2053 } 2133 }
2054 for (intptr_t i = 0; i < dead_code_->length(); i++) { 2134 for (intptr_t i = 0; i < dead_code_->length(); i++) {
2055 ProfileCode* code = dead_code_->At(i); 2135 ProfileCode* code = dead_code_->At(i);
2056 ASSERT(code != NULL); 2136 ASSERT(code != NULL);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 intptr_t ProfileTrieWalker::SiblingCount() { 2269 intptr_t ProfileTrieWalker::SiblingCount() {
2190 ASSERT(parent_ != NULL); 2270 ASSERT(parent_ != NULL);
2191 return parent_->NumChildren(); 2271 return parent_->NumChildren();
2192 } 2272 }
2193 2273
2194 2274
2195 void ProfilerService::PrintJSONImpl(Thread* thread, 2275 void ProfilerService::PrintJSONImpl(Thread* thread,
2196 JSONStream* stream, 2276 JSONStream* stream,
2197 Profile::TagOrder tag_order, 2277 Profile::TagOrder tag_order,
2198 intptr_t extra_tags, 2278 intptr_t extra_tags,
2199 SampleFilter* filter) { 2279 SampleFilter* filter,
2280 bool as_timeline) {
2200 Isolate* isolate = thread->isolate(); 2281 Isolate* isolate = thread->isolate();
2201 // Disable thread interrupts while processing the buffer. 2282 // Disable thread interrupts while processing the buffer.
2202 DisableThreadInterruptsScope dtis(thread); 2283 DisableThreadInterruptsScope dtis(thread);
2203 2284
2204 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 2285 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2205 if (sample_buffer == NULL) { 2286 if (sample_buffer == NULL) {
2206 stream->PrintError(kFeatureDisabled, NULL); 2287 stream->PrintError(kFeatureDisabled, NULL);
2207 return; 2288 return;
2208 } 2289 }
2209 2290
2210 { 2291 {
2211 StackZone zone(thread); 2292 StackZone zone(thread);
2212 HANDLESCOPE(thread); 2293 HANDLESCOPE(thread);
2213 Profile profile(isolate); 2294 Profile profile(isolate);
2214 profile.Build(thread, filter, tag_order, extra_tags); 2295 profile.Build(thread, filter, tag_order, extra_tags);
2215 profile.PrintJSON(stream); 2296 if (as_timeline) {
2297 profile.PrintTimelineJSON(stream);
2298 } else {
2299 profile.PrintProfileJSON(stream);
2300 }
2216 } 2301 }
2217 } 2302 }
2218 2303
2219 2304
2220 class NoAllocationSampleFilter : public SampleFilter { 2305 class NoAllocationSampleFilter : public SampleFilter {
2221 public: 2306 public:
2222 explicit NoAllocationSampleFilter(Isolate* isolate) 2307 explicit NoAllocationSampleFilter(Isolate* isolate)
2223 : SampleFilter(isolate) { 2308 : SampleFilter(isolate) {
2224 } 2309 }
2225 2310
2226 bool FilterSample(Sample* sample) { 2311 bool FilterSample(Sample* sample) {
2227 return !sample->is_allocation_sample(); 2312 return !sample->is_allocation_sample();
2228 } 2313 }
2229 }; 2314 };
2230 2315
2231 2316
2232 void ProfilerService::PrintJSON(JSONStream* stream, 2317 void ProfilerService::PrintJSON(JSONStream* stream,
2233 Profile::TagOrder tag_order, 2318 Profile::TagOrder tag_order,
2234 intptr_t extra_tags) { 2319 intptr_t extra_tags) {
2235 Thread* thread = Thread::Current(); 2320 Thread* thread = Thread::Current();
2236 Isolate* isolate = thread->isolate(); 2321 Isolate* isolate = thread->isolate();
2237 NoAllocationSampleFilter filter(isolate); 2322 NoAllocationSampleFilter filter(isolate);
2238 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter); 2323 const bool as_timeline = false;
2324 PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter, as_timeline);
2239 } 2325 }
2240 2326
2241 2327
2242 class ClassAllocationSampleFilter : public SampleFilter { 2328 class ClassAllocationSampleFilter : public SampleFilter {
2243 public: 2329 public:
2244 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls) 2330 ClassAllocationSampleFilter(Isolate* isolate, const Class& cls)
2245 : SampleFilter(isolate), 2331 : SampleFilter(isolate),
2246 cls_(Class::Handle(cls.raw())) { 2332 cls_(Class::Handle(cls.raw())) {
2247 ASSERT(!cls_.IsNull()); 2333 ASSERT(!cls_.IsNull());
2248 } 2334 }
2249 2335
2250 bool FilterSample(Sample* sample) { 2336 bool FilterSample(Sample* sample) {
2251 return sample->is_allocation_sample() && 2337 return sample->is_allocation_sample() &&
2252 (sample->allocation_cid() == cls_.id()); 2338 (sample->allocation_cid() == cls_.id());
2253 } 2339 }
2254 2340
2255 private: 2341 private:
2256 const Class& cls_; 2342 const Class& cls_;
2257 }; 2343 };
2258 2344
2259 2345
2260 void ProfilerService::PrintAllocationJSON(JSONStream* stream, 2346 void ProfilerService::PrintAllocationJSON(JSONStream* stream,
2261 Profile::TagOrder tag_order, 2347 Profile::TagOrder tag_order,
2262 const Class& cls) { 2348 const Class& cls) {
2263 Thread* thread = Thread::Current(); 2349 Thread* thread = Thread::Current();
2264 Isolate* isolate = thread->isolate(); 2350 Isolate* isolate = thread->isolate();
2265 ClassAllocationSampleFilter filter(isolate, cls); 2351 ClassAllocationSampleFilter filter(isolate, cls);
2266 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter); 2352 const bool as_timeline = false;
2353 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2267 } 2354 }
2268 2355
2269 2356
2357 void ProfilerService::PrintTimelineJSON(JSONStream* stream,
2358 Profile::TagOrder tag_order) {
2359 Thread* thread = Thread::Current();
2360 Isolate* isolate = thread->isolate();
2361 NoAllocationSampleFilter filter(isolate);
2362 const bool as_timeline = true;
2363 PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline);
2364 }
2365
2366
2270 void ProfilerService::ClearSamples() { 2367 void ProfilerService::ClearSamples() {
2271 SampleBuffer* sample_buffer = Profiler::sample_buffer(); 2368 SampleBuffer* sample_buffer = Profiler::sample_buffer();
2272 if (sample_buffer == NULL) { 2369 if (sample_buffer == NULL) {
2273 return; 2370 return;
2274 } 2371 }
2275 2372
2276 Thread* thread = Thread::Current(); 2373 Thread* thread = Thread::Current();
2277 Isolate* isolate = thread->isolate(); 2374 Isolate* isolate = thread->isolate();
2278 2375
2279 // Disable thread interrupts while processing the buffer. 2376 // Disable thread interrupts while processing the buffer.
2280 DisableThreadInterruptsScope dtis(thread); 2377 DisableThreadInterruptsScope dtis(thread);
2281 2378
2282 ClearProfileVisitor clear_profile(isolate); 2379 ClearProfileVisitor clear_profile(isolate);
2283 sample_buffer->VisitSamples(&clear_profile); 2380 sample_buffer->VisitSamples(&clear_profile);
2284 } 2381 }
2285 2382
2286 } // namespace dart 2383 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler_service.h ('k') | runtime/vm/service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698