| 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 |