Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |profile| into |proto_profile|. | 248 // Transcode |profile| into |proto_profile|. |
| 249 void CopyProfileToProto( | 249 void CopyProfileToProto( |
| 250 const StackSamplingProfiler::CallStackProfile& profile, | 250 const StackSamplingProfiler::CallStackProfile& profile, |
| 251 CallStackProfileParams::SampleOrderingSpec ordering_spec, | 251 CallStackProfileParams::SampleOrderingSpec ordering_spec, |
| 252 CallStackProfile* proto_profile) { | 252 CallStackProfile* proto_profile) { |
| 253 if (profile.samples.empty()) | 253 if (profile.samples.empty()) |
| 254 return; | 254 return; |
| 255 | 255 |
| 256 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { | 256 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { |
| 257 // Collapse only consecutive repeated samples together. | 257 // Collapse only consecutive repeated samples together. |
| 258 CallStackProfile::Sample* current_sample_proto = nullptr; | 258 CallStackProfile::Sample* current_sample_proto = nullptr; |
| 259 uint32_t phases = 0; | |
| 260 uint32_t activities = 0; | |
| 259 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | 261 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { |
| 260 if (!current_sample_proto || *it != *(it - 1)) { | 262 if (!current_sample_proto || *it != *(it - 1)) { |
| 261 current_sample_proto = proto_profile->add_sample(); | 263 current_sample_proto = proto_profile->add_sample(); |
| 262 CopySampleToProto(*it, profile.modules, current_sample_proto); | 264 CopySampleToProto(*it, profile.modules, current_sample_proto); |
| 263 current_sample_proto->set_count(1); | 265 current_sample_proto->set_count(1); |
| 266 | |
| 267 // Phases are "set only" so current is always superset of last-seen. | |
|
Mike Wittman
2016/11/02 21:44:04
Also, this logic could stand to be extracted into
Mike Wittman
2016/11/02 21:44:04
The process phase/activities encoding should have
bcwhite
2016/11/03 18:29:50
OMG the existing tests are ugly! <shudder>
Done.
bcwhite
2016/11/03 18:29:50
Done.
| |
| 268 uint32_t bits = it->process_phases & ~phases; | |
| 269 for (size_t bit = 0; bits != 0 && bit < sizeof(phases) * 8; | |
| 270 ++bit, bits >>= 1) { | |
| 271 if (bits & 1) { | |
| 272 current_sample_proto->add_process_phase( | |
| 273 static_cast<metrics::ProcessPhase>(1 << bit)); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 // New activities can begin. | |
| 278 bits = it->current_activities & ~activities; | |
| 279 for (size_t bit = 0; bits != 0 && bit < sizeof(phases) * 8; | |
| 280 ++bit, bits >>= 1) { | |
| 281 if (bits & 1) { | |
| 282 current_sample_proto->add_activities_begun( | |
| 283 static_cast<metrics::ProcessActivity>(1 << bit)); | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 // And existing activities can end. | |
| 288 bits = activities & ~it->current_activities; | |
| 289 for (size_t bit = 0; bits != 0 && bit < sizeof(phases) * 8; | |
| 290 ++bit, bits >>= 1) { | |
| 291 if (bits & 1) { | |
| 292 current_sample_proto->add_activities_ended( | |
| 293 static_cast<metrics::ProcessActivity>(1 << bit)); | |
| 294 } | |
| 295 } | |
| 296 | |
| 297 phases = it->process_phases; | |
| 298 activities = it->current_activities; | |
| 264 } else { | 299 } else { |
| 265 current_sample_proto->set_count(current_sample_proto->count() + 1); | 300 current_sample_proto->set_count(current_sample_proto->count() + 1); |
| 266 } | 301 } |
| 267 } | 302 } |
| 268 } else { | 303 } else { |
| 269 // Collapse all repeated samples together. | 304 // Collapse all repeated samples together. |
| 270 std::map<StackSamplingProfiler::Sample, int> sample_index; | 305 std::map<StackSamplingProfiler::Sample, int> sample_index; |
| 271 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | 306 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { |
| 272 auto location = sample_index.find(*it); | 307 auto location = sample_index.find(*it); |
| 273 if (location == sample_index.end()) { | 308 if (location == sample_index.end()) { |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 | 484 |
| 450 // static | 485 // static |
| 451 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { | 486 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { |
| 452 const std::string group_name = base::FieldTrialList::FindFullName( | 487 const std::string group_name = base::FieldTrialList::FindFullName( |
| 453 CallStackProfileMetricsProvider::kFieldTrialName); | 488 CallStackProfileMetricsProvider::kFieldTrialName); |
| 454 return group_name == | 489 return group_name == |
| 455 CallStackProfileMetricsProvider::kReportProfilesGroupName; | 490 CallStackProfileMetricsProvider::kReportProfilesGroupName; |
| 456 } | 491 } |
| 457 | 492 |
| 458 } // namespace metrics | 493 } // namespace metrics |
| OLD | NEW |