| 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 15 matching lines...) Expand all Loading... |
| 26 #include "base/threading/thread_task_runner_handle.h" | 26 #include "base/threading/thread_task_runner_handle.h" |
| 27 #include "base/time/time.h" | 27 #include "base/time/time.h" |
| 28 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" | 28 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" |
| 29 | 29 |
| 30 using base::StackSamplingProfiler; | 30 using base::StackSamplingProfiler; |
| 31 | 31 |
| 32 namespace metrics { | 32 namespace metrics { |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // Provide a mapping from the C++ "enum" definition of various process phases | 36 // Provide a mapping from the C++ "enum" definition of various process mile- |
| 37 // to the equivalent protobuf "enum" definition. This table-lookup conversion | 37 // stones to the equivalent protobuf "enum" definition. This table-lookup |
| 38 // allows for the implementation to evolve and still be compatible with the | 38 // conversion allows for the implementation to evolve and still be compatible |
| 39 // protobuf -- even if there are ever more than 32 defined proto values, though | 39 // with the protobuf -- even if there are ever more than 32 defined proto |
| 40 // never more than 32 could be in-use in a given C++ version of the code. | 40 // values, though never more than 32 could be in-use in a given C++ version |
| 41 // of the code. |
| 41 const ProcessPhase | 42 const ProcessPhase |
| 42 kProtoPhases[CallStackProfileMetricsProvider::PHASES_MAX_VALUE] = { | 43 kProtoPhases[CallStackProfileMetricsProvider::MILESTONES_MAX_VALUE] = { |
| 43 ProcessPhase::MAIN_LOOP_START, | 44 ProcessPhase::MAIN_LOOP_START, |
| 44 ProcessPhase::MAIN_NAVIGATION_START, | 45 ProcessPhase::MAIN_NAVIGATION_START, |
| 45 ProcessPhase::MAIN_NAVIGATION_FINISHED, | 46 ProcessPhase::MAIN_NAVIGATION_FINISHED, |
| 46 ProcessPhase::FIRST_NONEMPTY_PAINT, | 47 ProcessPhase::FIRST_NONEMPTY_PAINT, |
| 47 | 48 |
| 48 ProcessPhase::SHUTDOWN_START, | 49 ProcessPhase::SHUTDOWN_START, |
| 49 }; | 50 }; |
| 50 | 51 |
| 51 // ProfilesState -------------------------------------------------------------- | 52 // ProfilesState -------------------------------------------------------------- |
| 52 | 53 |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 entry->set_address(static_cast<uint64_t>(module_offset)); | 253 entry->set_address(static_cast<uint64_t>(module_offset)); |
| 253 entry->set_module_id_index(frame.module_index); | 254 entry->set_module_id_index(frame.module_index); |
| 254 } | 255 } |
| 255 } | 256 } |
| 256 | 257 |
| 257 // Transcode Sample annotations into protobuf fields. The C++ code uses a bit- | 258 // Transcode Sample annotations into protobuf fields. The C++ code uses a bit- |
| 258 // field with each bit corresponding to an entry in an enumeration while the | 259 // field with each bit corresponding to an entry in an enumeration while the |
| 259 // protobuf uses a repeated field of individual values. Conversion tables | 260 // protobuf uses a repeated field of individual values. Conversion tables |
| 260 // allow for arbitrary mapping, though no more than 32 in any given version | 261 // allow for arbitrary mapping, though no more than 32 in any given version |
| 261 // of the code. | 262 // of the code. |
| 262 void CopyAnnotationsToProto(uint32_t new_phases, | 263 void CopyAnnotationsToProto(uint32_t new_milestones, |
| 263 CallStackProfile::Sample* sample_proto) { | 264 CallStackProfile::Sample* sample_proto) { |
| 264 for (size_t bit = 0; new_phases != 0 && bit < sizeof(new_phases) * 8; ++bit) { | 265 for (size_t bit = 0; new_milestones != 0 && bit < sizeof(new_milestones) * 8; |
| 266 ++bit) { |
| 265 const uint32_t flag = 1U << bit; | 267 const uint32_t flag = 1U << bit; |
| 266 if (new_phases & flag) { | 268 if (new_milestones & flag) { |
| 267 if (bit >= arraysize(kProtoPhases)) { | 269 if (bit >= arraysize(kProtoPhases)) { |
| 268 NOTREACHED(); | 270 NOTREACHED(); |
| 269 continue; | 271 continue; |
| 270 } | 272 } |
| 271 sample_proto->add_process_phase(kProtoPhases[bit]); | 273 sample_proto->add_process_phase(kProtoPhases[bit]); |
| 272 new_phases ^= flag; // Bit is set so XOR will clear it. | 274 new_milestones ^= flag; // Bit is set so XOR will clear it. |
| 273 } | 275 } |
| 274 } | 276 } |
| 275 } | 277 } |
| 276 | 278 |
| 277 // Transcode |profile| into |proto_profile|. | 279 // Transcode |profile| into |proto_profile|. |
| 278 void CopyProfileToProto( | 280 void CopyProfileToProto( |
| 279 const StackSamplingProfiler::CallStackProfile& profile, | 281 const StackSamplingProfiler::CallStackProfile& profile, |
| 280 CallStackProfileParams::SampleOrderingSpec ordering_spec, | 282 CallStackProfileParams::SampleOrderingSpec ordering_spec, |
| 281 CallStackProfile* proto_profile) { | 283 CallStackProfile* proto_profile) { |
| 282 if (profile.samples.empty()) | 284 if (profile.samples.empty()) |
| 283 return; | 285 return; |
| 284 | 286 |
| 285 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { | 287 if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { |
| 286 // Collapse only consecutive repeated samples together. | 288 // Collapse only consecutive repeated samples together. |
| 287 CallStackProfile::Sample* current_sample_proto = nullptr; | 289 CallStackProfile::Sample* current_sample_proto = nullptr; |
| 288 uint32_t phases = 0; | 290 uint32_t milestones = 0; |
| 289 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | 291 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { |
| 290 // Check if the sample is different than the previous one. Samples match | 292 // Check if the sample is different than the previous one. Samples match |
| 291 // if the frame and all annotations are the same. | 293 // if the frame and all annotations are the same. |
| 292 if (!current_sample_proto || *it != *(it - 1)) { | 294 if (!current_sample_proto || *it != *(it - 1)) { |
| 293 current_sample_proto = proto_profile->add_sample(); | 295 current_sample_proto = proto_profile->add_sample(); |
| 294 CopySampleToProto(*it, profile.modules, current_sample_proto); | 296 CopySampleToProto(*it, profile.modules, current_sample_proto); |
| 295 current_sample_proto->set_count(1); | 297 current_sample_proto->set_count(1); |
| 296 CopyAnnotationsToProto(it->process_phases & ~phases, | 298 CopyAnnotationsToProto(it->process_milestones & ~milestones, |
| 297 current_sample_proto); | 299 current_sample_proto); |
| 298 phases = it->process_phases; | 300 milestones = it->process_milestones; |
| 299 } else { | 301 } else { |
| 300 current_sample_proto->set_count(current_sample_proto->count() + 1); | 302 current_sample_proto->set_count(current_sample_proto->count() + 1); |
| 301 } | 303 } |
| 302 } | 304 } |
| 303 } else { | 305 } else { |
| 304 // Collapse all repeated samples together. | 306 // Collapse all repeated samples together. |
| 305 std::map<StackSamplingProfiler::Sample, int> sample_index; | 307 std::map<StackSamplingProfiler::Sample, int> sample_index; |
| 306 uint32_t phases = 0; | 308 uint32_t milestones = 0; |
| 307 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | 309 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { |
| 308 // Check for a sample already seen. Samples match if the frame and all | 310 // Check for a sample already seen. Samples match if the frame and all |
| 309 // annotations are the same. | 311 // annotations are the same. |
| 310 auto location = sample_index.find(*it); | 312 auto location = sample_index.find(*it); |
| 311 if (location == sample_index.end()) { | 313 if (location == sample_index.end()) { |
| 312 CallStackProfile::Sample* sample_proto = proto_profile->add_sample(); | 314 CallStackProfile::Sample* sample_proto = proto_profile->add_sample(); |
| 313 CopySampleToProto(*it, profile.modules, sample_proto); | 315 CopySampleToProto(*it, profile.modules, sample_proto); |
| 314 sample_proto->set_count(1); | 316 sample_proto->set_count(1); |
| 315 CopyAnnotationsToProto(it->process_phases & ~phases, sample_proto); | 317 CopyAnnotationsToProto(it->process_milestones & ~milestones, |
| 318 sample_proto); |
| 316 sample_index.insert( | 319 sample_index.insert( |
| 317 std::make_pair( | 320 std::make_pair( |
| 318 *it, static_cast<int>(proto_profile->sample().size()) - 1)); | 321 *it, static_cast<int>(proto_profile->sample().size()) - 1)); |
| 319 phases = it->process_phases; | 322 milestones = it->process_milestones; |
| 320 } else { | 323 } else { |
| 321 CallStackProfile::Sample* sample_proto = | 324 CallStackProfile::Sample* sample_proto = |
| 322 proto_profile->mutable_sample()->Mutable(location->second); | 325 proto_profile->mutable_sample()->Mutable(location->second); |
| 323 sample_proto->set_count(sample_proto->count() + 1); | 326 sample_proto->set_count(sample_proto->count() + 1); |
| 324 } | 327 } |
| 325 } | 328 } |
| 326 } | 329 } |
| 327 | 330 |
| 328 for (const StackSamplingProfiler::Module& module : profile.modules) { | 331 for (const StackSamplingProfiler::Module& module : profile.modules) { |
| 329 CallStackProfile::ModuleIdentifier* module_id = | 332 CallStackProfile::ModuleIdentifier* module_id = |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 | 492 |
| 490 // static | 493 // static |
| 491 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { | 494 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { |
| 492 const std::string group_name = base::FieldTrialList::FindFullName( | 495 const std::string group_name = base::FieldTrialList::FindFullName( |
| 493 CallStackProfileMetricsProvider::kFieldTrialName); | 496 CallStackProfileMetricsProvider::kFieldTrialName); |
| 494 return group_name == | 497 return group_name == |
| 495 CallStackProfileMetricsProvider::kReportProfilesGroupName; | 498 CallStackProfileMetricsProvider::kReportProfilesGroupName; |
| 496 } | 499 } |
| 497 | 500 |
| 498 } // namespace metrics | 501 } // namespace metrics |
| OLD | NEW |