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

Side by Side Diff: components/metrics/call_stack_profile_metrics_provider.cc

Issue 2444143002: Add process lifetime annotations to stack samples. (Closed)
Patch Set: addressed review comments and added test Created 4 years, 1 month 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/metrics/call_stack_profile_metrics_provider.h" 5 #include "components/metrics/call_stack_profile_metrics_provider.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 memcpy(&name_bytes[0], &basename[0], basename_length_in_bytes); 222 memcpy(&name_bytes[0], &basename[0], basename_length_in_bytes);
223 return base::HashMetricName(name_bytes); 223 return base::HashMetricName(name_bytes);
224 } 224 }
225 225
226 // Transcode |sample| into |proto_sample|, using base addresses in |modules| to 226 // Transcode |sample| into |proto_sample|, using base addresses in |modules| to
227 // compute module instruction pointer offsets. 227 // compute module instruction pointer offsets.
228 void CopySampleToProto( 228 void CopySampleToProto(
229 const StackSamplingProfiler::Sample& sample, 229 const StackSamplingProfiler::Sample& sample,
230 const std::vector<StackSamplingProfiler::Module>& modules, 230 const std::vector<StackSamplingProfiler::Module>& modules,
231 CallStackProfile::Sample* proto_sample) { 231 CallStackProfile::Sample* proto_sample) {
232 for (const StackSamplingProfiler::Frame& frame : sample) { 232 for (const StackSamplingProfiler::Frame& frame : sample.frames) {
233 CallStackProfile::Entry* entry = proto_sample->add_entry(); 233 CallStackProfile::Entry* entry = proto_sample->add_entry();
234 // A frame may not have a valid module. If so, we can't compute the 234 // A frame may not have a valid module. If so, we can't compute the
235 // instruction pointer offset, and we don't want to send bare pointers, so 235 // instruction pointer offset, and we don't want to send bare pointers, so
236 // leave call_stack_entry empty. 236 // leave call_stack_entry empty.
237 if (frame.module_index == StackSamplingProfiler::Frame::kUnknownModuleIndex) 237 if (frame.module_index == StackSamplingProfiler::Frame::kUnknownModuleIndex)
238 continue; 238 continue;
239 int64_t module_offset = 239 int64_t module_offset =
240 reinterpret_cast<const char*>(frame.instruction_pointer) - 240 reinterpret_cast<const char*>(frame.instruction_pointer) -
241 reinterpret_cast<const char*>(modules[frame.module_index].base_address); 241 reinterpret_cast<const char*>(modules[frame.module_index].base_address);
242 DCHECK_GE(module_offset, 0); 242 DCHECK_GE(module_offset, 0);
243 entry->set_address(static_cast<uint64_t>(module_offset)); 243 entry->set_address(static_cast<uint64_t>(module_offset));
244 entry->set_module_id_index(frame.module_index); 244 entry->set_module_id_index(frame.module_index);
245 } 245 }
246 } 246 }
247 247
248 // Transcode Sample annotations into protobuf fields.
249 void CopyAnnotationsToProto(uint32_t new_phases,
250 uint32_t activities_begun,
251 uint32_t activities_ended,
252 CallStackProfile::Sample* sample_proto) {
253 for (size_t bit = 0; new_phases != 0 && bit < sizeof(new_phases) * 8;
254 ++bit, new_phases >>= 1) {
255 if (new_phases & 1) {
256 sample_proto->add_process_phase(
257 static_cast<metrics::ProcessPhase>(bit));
258 }
259 }
260
261 for (size_t bit = 0;
262 activities_begun != 0 && bit < sizeof(activities_begun) * 8;
263 ++bit, activities_begun >>= 1) {
264 if (activities_begun & 1) {
265 sample_proto->add_activities_begun(
266 static_cast<metrics::ProcessActivity>(bit));
267 }
268 }
269
270 for (size_t bit = 0;
271 activities_ended != 0 && bit < sizeof(activities_ended) * 8;
272 ++bit, activities_ended >>= 1) {
273 if (activities_ended & 1) {
274 sample_proto->add_activities_ended(
275 static_cast<metrics::ProcessActivity>(bit));
276 }
277 }
278 }
279
248 // Transcode |profile| into |proto_profile|. 280 // Transcode |profile| into |proto_profile|.
249 void CopyProfileToProto( 281 void CopyProfileToProto(
250 const StackSamplingProfiler::CallStackProfile& profile, 282 const StackSamplingProfiler::CallStackProfile& profile,
251 CallStackProfileParams::SampleOrderingSpec ordering_spec, 283 CallStackProfileParams::SampleOrderingSpec ordering_spec,
252 CallStackProfile* proto_profile) { 284 CallStackProfile* proto_profile) {
253 if (profile.samples.empty()) 285 if (profile.samples.empty())
254 return; 286 return;
255 287
256 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { 288 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) {
257 // Collapse only consecutive repeated samples together. 289 // Collapse only consecutive repeated samples together.
258 CallStackProfile::Sample* current_sample_proto = nullptr; 290 CallStackProfile::Sample* current_sample_proto = nullptr;
291 uint32_t phases = 0;
292 uint32_t activities = 0;
259 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { 293 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) {
260 if (!current_sample_proto || *it != *(it - 1)) { 294 if (!current_sample_proto || *it != *(it - 1)) {
261 current_sample_proto = proto_profile->add_sample(); 295 current_sample_proto = proto_profile->add_sample();
262 CopySampleToProto(*it, profile.modules, current_sample_proto); 296 CopySampleToProto(*it, profile.modules, current_sample_proto);
263 current_sample_proto->set_count(1); 297 current_sample_proto->set_count(1);
298 CopyAnnotationsToProto(
299 it->process_phases & ~phases, // Phases are "set only".
300 it->current_activities & ~activities, // Activities can begin
301 activities & ~it->current_activities, // and end.
302 current_sample_proto);
303 phases = it->process_phases;
304 activities = it->current_activities;
264 } else { 305 } else {
265 current_sample_proto->set_count(current_sample_proto->count() + 1); 306 current_sample_proto->set_count(current_sample_proto->count() + 1);
266 } 307 }
267 } 308 }
268 } else { 309 } else {
269 // Collapse all repeated samples together. 310 // Collapse all repeated samples together.
270 std::map<StackSamplingProfiler::Sample, int> sample_index; 311 std::map<StackSamplingProfiler::Sample, int> sample_index;
271 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { 312 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) {
272 auto location = sample_index.find(*it); 313 auto location = sample_index.find(*it);
273 if (location == sample_index.end()) { 314 if (location == sample_index.end()) {
274 CallStackProfile::Sample* sample_proto = proto_profile->add_sample(); 315 CallStackProfile::Sample* sample_proto = proto_profile->add_sample();
275 CopySampleToProto(*it, profile.modules, sample_proto); 316 CopySampleToProto(*it, profile.modules, sample_proto);
276 sample_proto->set_count(1); 317 sample_proto->set_count(1);
318 CopyAnnotationsToProto(it->process_phases, it->current_activities, 0,
319 sample_proto);
277 sample_index.insert( 320 sample_index.insert(
278 std::make_pair( 321 std::make_pair(
279 *it, static_cast<int>(proto_profile->sample().size()) - 1)); 322 *it, static_cast<int>(proto_profile->sample().size()) - 1));
280 } else { 323 } else {
281 CallStackProfile::Sample* sample_proto = 324 CallStackProfile::Sample* sample_proto =
282 proto_profile->mutable_sample()->Mutable(location->second); 325 proto_profile->mutable_sample()->Mutable(location->second);
283 sample_proto->set_count(sample_proto->count() + 1); 326 sample_proto->set_count(sample_proto->count() + 1);
284 } 327 }
285 } 328 }
286 } 329 }
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 492
450 // static 493 // static
451 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { 494 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() {
452 const std::string group_name = base::FieldTrialList::FindFullName( 495 const std::string group_name = base::FieldTrialList::FindFullName(
453 CallStackProfileMetricsProvider::kFieldTrialName); 496 CallStackProfileMetricsProvider::kFieldTrialName);
454 return group_name == 497 return group_name ==
455 CallStackProfileMetricsProvider::kReportProfilesGroupName; 498 CallStackProfileMetricsProvider::kReportProfilesGroupName;
456 } 499 }
457 500
458 } // namespace metrics 501 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698