Chromium Code Reviews| Index: components/metrics/call_stack_profile_metrics_provider.cc |
| diff --git a/components/metrics/call_stack_profile_metrics_provider.cc b/components/metrics/call_stack_profile_metrics_provider.cc |
| index 9f323fdc28a48f2708826ddd768e1a8118dc8367..60aeeca6227ad326b283190d959a7a1fe4184668 100644 |
| --- a/components/metrics/call_stack_profile_metrics_provider.cc |
| +++ b/components/metrics/call_stack_profile_metrics_provider.cc |
| @@ -33,6 +33,22 @@ namespace metrics { |
| namespace { |
| +const ProcessPhase |
|
Alexei Svitkine (slow)
2016/11/07 23:22:07
Please document these mappings with a comment abov
bcwhite
2016/11/08 01:02:36
Done.
|
| + kProtoPhases[CallStackProfileMetricsProvider::PHASES_MAX_VALUE] = { |
| + ProcessPhase::MAIN_LOOP_START, |
| + ProcessPhase::MAIN_NAVIGATION_START, |
| + ProcessPhase::FIRST_NONEMPTY_PAINT, |
| + ProcessPhase::FIRST_CONTENTFUL_PAINT, |
| + |
| + ProcessPhase::SHUTDOWN_START, |
| +}; |
| + |
| +const ProcessActivity |
| + kProtoActivities[CallStackProfileMetricsProvider::ACTIVITIES_MAX_VALUE] = { |
| + ProcessActivity::COLLECTING_METRICS, |
| + ProcessActivity::WRITING_PROFILES_STATE, |
| +}; |
| + |
| // ProfilesState -------------------------------------------------------------- |
| // A set of profiles and the CallStackProfileMetricsProvider state associated |
| @@ -229,7 +245,7 @@ void CopySampleToProto( |
| const StackSamplingProfiler::Sample& sample, |
| const std::vector<StackSamplingProfiler::Module>& modules, |
| CallStackProfile::Sample* proto_sample) { |
| - for (const StackSamplingProfiler::Frame& frame : sample) { |
| + for (const StackSamplingProfiler::Frame& frame : sample.frames) { |
| CallStackProfile::Entry* entry = proto_sample->add_entry(); |
| // A frame may not have a valid module. If so, we can't compute the |
| // instruction pointer offset, and we don't want to send bare pointers, so |
| @@ -245,6 +261,47 @@ void CopySampleToProto( |
| } |
| } |
| +// Transcode Sample annotations into protobuf fields. |
|
Alexei Svitkine (slow)
2016/11/07 23:22:07
Maybe expand the comment for the motivation - that
bcwhite
2016/11/08 01:02:36
Done.
|
| +void CopyAnnotationsToProto(uint32_t new_phases, |
| + uint32_t activities_begun, |
| + uint32_t activities_ended, |
| + CallStackProfile::Sample* sample_proto) { |
| + for (size_t bit = 0; new_phases != 0 && bit < sizeof(new_phases) * 8; |
| + ++bit, new_phases >>= 1) { |
|
Alexei Svitkine (slow)
2016/11/07 23:22:07
Instead of new_phases >>= 1 logic, I'd actually ju
bcwhite
2016/11/08 01:02:36
That will be two extra instructions (complement an
Alexei Svitkine (slow)
2016/11/14 18:26:39
It will only do those instructions when the bit is
bcwhite
2016/11/16 18:27:44
I think it's perfectly clear this way. But done.
|
| + if (new_phases & 1) { |
| + if (bit >= arraysize(kProtoPhases)) { |
| + NOTREACHED(); |
| + continue; |
| + } |
| + sample_proto->add_process_phase(kProtoPhases[bit]); |
| + } |
| + } |
| + |
| + for (size_t bit = 0; |
| + activities_begun != 0 && bit < sizeof(activities_begun) * 8; |
| + ++bit, activities_begun >>= 1) { |
| + if (activities_begun & 1) { |
| + if (bit >= arraysize(kProtoActivities)) { |
| + NOTREACHED(); |
| + continue; |
| + } |
| + sample_proto->add_activity_begun(kProtoActivities[bit]); |
| + } |
| + } |
| + |
| + for (size_t bit = 0; |
| + activities_ended != 0 && bit < sizeof(activities_ended) * 8; |
| + ++bit, activities_ended >>= 1) { |
| + if (activities_ended & 1) { |
| + if (bit >= arraysize(kProtoActivities)) { |
| + NOTREACHED(); |
| + continue; |
| + } |
| + sample_proto->add_activity_ended(kProtoActivities[bit]); |
| + } |
| + } |
| +} |
| + |
| // Transcode |profile| into |proto_profile|. |
| void CopyProfileToProto( |
| const StackSamplingProfiler::CallStackProfile& profile, |
| @@ -256,11 +313,20 @@ void CopyProfileToProto( |
| if (ordering_spec == CallStackProfileParams::PRESERVE_ORDER) { |
| // Collapse only consecutive repeated samples together. |
| CallStackProfile::Sample* current_sample_proto = nullptr; |
| + uint32_t phases = 0; |
| + uint32_t activities = 0; |
| for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { |
| if (!current_sample_proto || *it != *(it - 1)) { |
| current_sample_proto = proto_profile->add_sample(); |
| CopySampleToProto(*it, profile.modules, current_sample_proto); |
| current_sample_proto->set_count(1); |
| + CopyAnnotationsToProto( |
| + it->process_phases & ~phases, // Phases are "set only". |
| + it->current_activities & ~activities, // Activities can begin |
| + activities & ~it->current_activities, // and end. |
| + current_sample_proto); |
| + phases = it->process_phases; |
| + activities = it->current_activities; |
| } else { |
| current_sample_proto->set_count(current_sample_proto->count() + 1); |
| } |
| @@ -274,6 +340,8 @@ void CopyProfileToProto( |
| CallStackProfile::Sample* sample_proto = proto_profile->add_sample(); |
| CopySampleToProto(*it, profile.modules, sample_proto); |
| sample_proto->set_count(1); |
| + CopyAnnotationsToProto(it->process_phases, it->current_activities, 0, |
| + sample_proto); |
| sample_index.insert( |
| std::make_pair( |
| *it, static_cast<int>(proto_profile->sample().size()) - 1)); |