OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/metrics/call_stack_profile_metrics_provider.h" | |
6 | |
7 #include <cstring> | |
8 #include <map> | |
9 #include <utility> | |
10 | |
11 #include "base/logging.h" | |
12 #include "base/macros.h" | |
13 #include "base/profiler/stack_sampling_profiler.h" | |
14 #include "components/metrics/metrics_hashes.h" | |
15 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" | |
16 | |
17 using base::StackSamplingProfiler; | |
18 | |
19 namespace metrics { | |
20 | |
21 namespace { | |
22 | |
23 // The protobuf expects the MD5 checksum prefix of the module name. | |
24 uint64 HashModuleFilename(const base::FilePath& filename) { | |
25 const base::FilePath::StringType basename = filename.BaseName().value(); | |
Ilya Sherman
2015/03/19 00:10:19
nit: Probably no need to make a copy here, right?
Mike Wittman
2015/03/19 00:56:58
Done.
Mike Wittman
2015/03/19 21:51:18
Actually, we do need to make a copy here. value()
Ilya Sherman
2015/03/19 22:00:11
Wait, really? Fascinating! If I'm understanding
| |
26 // Copy the bytes in basename into a string buffer. | |
27 std::string name_bytes(basename.size() * sizeof(base::FilePath::CharType), | |
28 '\0'); | |
29 memcpy(&name_bytes[0], &basename[0], | |
30 basename.size() * sizeof(base::FilePath::CharType)); | |
Ilya Sherman
2015/03/19 00:10:19
nit: Please cache this computation, rather than pe
Mike Wittman
2015/03/19 00:56:58
Done.
| |
31 return HashMetricName(name_bytes); | |
32 } | |
33 | |
34 // Transcode |sample| into |proto_sample|, using base addresses in |modules| to | |
35 // compute module instruction pointer offsets. | |
36 void CopySampleToProto( | |
37 const StackSamplingProfiler::Sample& sample, | |
38 const std::vector<StackSamplingProfiler::Module>& modules, | |
39 CallStackProfile::Sample* proto_sample) { | |
40 for (const StackSamplingProfiler::Frame& frame : sample) { | |
41 CallStackEntry* call_stack_entry = proto_sample->add_entry(); | |
42 // A frame may not have a valid module. If so we can't compute the | |
Ilya Sherman
2015/03/19 00:10:19
nit: "If so we can't" -> "If so, we can't"
Mike Wittman
2015/03/19 00:56:58
Done.
| |
43 // instruction pointer offset, and we don't want to send bare pointers, so | |
44 // leave call_stack_entry empty. | |
45 if (frame.module_index < 0) | |
46 continue; | |
47 int64 module_offset = | |
48 reinterpret_cast<const char*>(frame.instruction_pointer) - | |
49 reinterpret_cast<const char*>(modules[frame.module_index].base_address); | |
50 DCHECK_GE(module_offset, 0); | |
51 call_stack_entry->set_address(static_cast<uint64>(module_offset)); | |
52 call_stack_entry->set_module_id_index(frame.module_index); | |
53 } | |
54 } | |
55 | |
56 // Transcode |profile| into |proto_profile|. | |
57 void CopyProfileToProto( | |
58 const StackSamplingProfiler::Profile& profile, | |
59 CallStackProfile* proto_profile) { | |
60 if (profile.samples.empty()) | |
61 return; | |
62 | |
63 if (profile.preserve_sample_ordering) { | |
64 // Collapse only consecutive repeated samples together. | |
65 CallStackProfile::Sample* current_sample_proto = nullptr; | |
66 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | |
67 if (!current_sample_proto || *it != *(it - 1)) { | |
68 current_sample_proto = proto_profile->add_sample(); | |
69 CopySampleToProto(*it, profile.modules, current_sample_proto); | |
70 current_sample_proto->set_count(1); | |
71 } else { | |
72 current_sample_proto->set_count(current_sample_proto->count() + 1); | |
73 } | |
74 } | |
75 } else { | |
76 // Collapse all repeated samples together. | |
77 std::map<StackSamplingProfiler::Sample, int> sample_index; | |
78 for (auto it = profile.samples.begin(); it != profile.samples.end(); ++it) { | |
79 auto location = sample_index.find(*it); | |
80 if (location == sample_index.end()) { | |
81 CallStackProfile::Sample* sample_proto = proto_profile->add_sample(); | |
82 CopySampleToProto(*it, profile.modules, sample_proto); | |
83 sample_proto->set_count(1); | |
84 sample_index.insert( | |
85 std::make_pair( | |
86 *it, static_cast<int>(proto_profile->sample().size()) - 1)); | |
87 } else { | |
88 CallStackProfile::Sample* sample_proto = | |
89 proto_profile->mutable_sample()->Mutable(location->second); | |
90 sample_proto->set_count(sample_proto->count() + 1); | |
91 } | |
92 } | |
93 } | |
94 | |
95 for (const StackSamplingProfiler::Module& module : profile.modules) { | |
96 ModuleIdentifier* module_id = proto_profile->add_module_id(); | |
97 module_id->set_build_id(module.id); | |
98 module_id->set_name_md5_prefix(HashModuleFilename(module.filename)); | |
99 } | |
100 | |
101 proto_profile->set_profile_duration_ms( | |
102 profile.profile_duration.InMilliseconds()); | |
103 proto_profile->set_sampling_period_ms( | |
104 profile.sampling_period.InMilliseconds()); | |
105 } | |
106 } // namespace | |
107 | |
108 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() {} | |
109 | |
110 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() {} | |
111 | |
112 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( | |
113 ChromeUserMetricsExtension* uma_proto) { | |
114 std::vector<StackSamplingProfiler::Profile> profiles; | |
115 if (!source_profiles_for_test_.empty()) | |
116 profiles.swap(source_profiles_for_test_); | |
117 else | |
118 StackSamplingProfiler::GetPendingProfiles(&profiles); | |
119 | |
120 for (const StackSamplingProfiler::Profile& profile : profiles) { | |
121 CallStackProfile* call_stack_profile = | |
122 uma_proto->add_sampled_profile()->mutable_call_stack_profile(); | |
123 CopyProfileToProto(profile, call_stack_profile); | |
124 } | |
125 } | |
126 | |
127 void CallStackProfileMetricsProvider::SetSourceProfilesForTesting( | |
128 const std::vector<StackSamplingProfiler::Profile>& profiles) { | |
129 source_profiles_for_test_ = profiles; | |
130 } | |
131 | |
132 } // namespace metrics | |
OLD | NEW |