1 // Copyright 2014 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.
5 #include "components/metrics/profiler/profiler_metrics_provider.h"
11 #include "base/stl_util.h"
12 #include "base/tracked_objects.h"
13 #include "components/metrics/metrics_log.h"
14 #include "components/nacl/common/nacl_process_type.h"
20 ProfilerEventProto::TrackedObject::ProcessType
AsProtobufProcessType(
22 switch (process_type
) {
23 case content::PROCESS_TYPE_BROWSER
:
24 return ProfilerEventProto::TrackedObject::BROWSER
;
25 case content::PROCESS_TYPE_RENDERER
:
26 return ProfilerEventProto::TrackedObject::RENDERER
;
27 case content::PROCESS_TYPE_PLUGIN
:
28 return ProfilerEventProto::TrackedObject::PLUGIN
;
29 case content::PROCESS_TYPE_UTILITY
:
30 return ProfilerEventProto::TrackedObject::UTILITY
;
31 case content::PROCESS_TYPE_ZYGOTE
:
32 return ProfilerEventProto::TrackedObject::ZYGOTE
;
33 case content::PROCESS_TYPE_SANDBOX_HELPER
:
34 return ProfilerEventProto::TrackedObject::SANDBOX_HELPER
;
35 case content::PROCESS_TYPE_GPU
:
36 return ProfilerEventProto::TrackedObject::GPU
;
37 case content::PROCESS_TYPE_PPAPI_PLUGIN
:
38 return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN
;
39 case content::PROCESS_TYPE_PPAPI_BROKER
:
40 return ProfilerEventProto::TrackedObject::PPAPI_BROKER
;
41 case PROCESS_TYPE_NACL_LOADER
:
42 return ProfilerEventProto::TrackedObject::NACL_LOADER
;
43 case PROCESS_TYPE_NACL_BROKER
:
44 return ProfilerEventProto::TrackedObject::NACL_BROKER
;
47 return ProfilerEventProto::TrackedObject::UNKNOWN
;
51 // Maps a thread name by replacing trailing sequence of digits with "*".
53 // 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*"
54 // 2. "Chrome_IOThread" => "Chrome_IOThread"
55 std::string
MapThreadName(const std::string
& thread_name
) {
56 size_t i
= thread_name
.length();
58 while (i
> 0 && isdigit(thread_name
[i
- 1])) {
62 if (i
== thread_name
.length())
65 return thread_name
.substr(0, i
) + '*';
68 // Normalizes a source filename (which is platform- and build-method-dependent)
69 // by extracting the last component of the full file name.
70 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" =>
72 std::string
NormalizeFileName(const std::string
& file_name
) {
73 const size_t offset
= file_name
.find_last_of("\\/");
74 return offset
!= std::string::npos
? file_name
.substr(offset
+ 1) : file_name
;
77 void WriteProfilerData(
78 const tracked_objects::ProcessDataPhaseSnapshot
& process_data_phase
,
79 base::ProcessId process_id
,
80 content::ProcessType process_type
,
81 ProfilerEventProto
* performance_profile
) {
82 for (const auto& task
: process_data_phase
.tasks
) {
83 const tracked_objects::DeathDataSnapshot
& death_data
= task
.death_data
;
84 ProfilerEventProto::TrackedObject
* tracked_object
=
85 performance_profile
->add_tracked_object();
86 tracked_object
->set_birth_thread_name_hash(
87 MetricsLog::Hash(MapThreadName(task
.birth
.thread_name
)));
88 tracked_object
->set_exec_thread_name_hash(
89 MetricsLog::Hash(MapThreadName(task
.death_thread_name
)));
90 tracked_object
->set_source_file_name_hash(
91 MetricsLog::Hash(NormalizeFileName(task
.birth
.location
.file_name
)));
92 tracked_object
->set_source_function_name_hash(
93 MetricsLog::Hash(task
.birth
.location
.function_name
));
94 tracked_object
->set_source_line_number(task
.birth
.location
.line_number
);
95 tracked_object
->set_exec_count(death_data
.count
);
96 tracked_object
->set_exec_time_total(death_data
.run_duration_sum
);
97 tracked_object
->set_exec_time_sampled(death_data
.run_duration_sample
);
98 tracked_object
->set_queue_time_total(death_data
.queue_duration_sum
);
99 tracked_object
->set_queue_time_sampled(death_data
.queue_duration_sample
);
100 tracked_object
->set_process_type(AsProtobufProcessType(process_type
));
101 tracked_object
->set_process_id(process_id
);
107 ProfilerMetricsProvider::ProfilerMetricsProvider() {
110 ProfilerMetricsProvider::ProfilerMetricsProvider(
111 const base::Callback
<bool(void)>& cellular_callback
)
112 : cellular_callback_(cellular_callback
) {
115 ProfilerMetricsProvider::~ProfilerMetricsProvider() {
118 void ProfilerMetricsProvider::ProvideGeneralMetrics(
119 ChromeUserMetricsExtension
* uma_proto
) {
120 DCHECK_EQ(tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
,
121 tracked_objects::GetTimeSourceType());
123 DCHECK_EQ(0, uma_proto
->profiler_event_size());
125 for (auto& event
: profiler_events_cache_
) {
126 uma_proto
->add_profiler_event()->Swap(&event
.second
);
129 profiler_events_cache_
.clear();
132 void ProfilerMetricsProvider::RecordProfilerData(
133 const tracked_objects::ProcessDataPhaseSnapshot
& process_data_phase
,
134 base::ProcessId process_id
,
135 content::ProcessType process_type
,
137 base::TimeDelta phase_start
,
138 base::TimeDelta phase_finish
,
139 const ProfilerEvents
& past_events
) {
140 if (IsCellularLogicEnabled())
142 if (tracked_objects::GetTimeSourceType() !=
143 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
) {
144 // We currently only support the default time source, wall clock time.
148 const bool new_phase
= !ContainsKey(profiler_events_cache_
, profiling_phase
);
149 ProfilerEventProto
* profiler_event
= &profiler_events_cache_
[profiling_phase
];
152 profiler_event
->set_profile_version(
153 ProfilerEventProto::VERSION_SPLIT_PROFILE
);
154 profiler_event
->set_time_source(ProfilerEventProto::WALL_CLOCK_TIME
);
155 profiler_event
->set_profiling_start_ms(phase_start
.InMilliseconds());
156 profiler_event
->set_profiling_finish_ms(phase_finish
.InMilliseconds());
157 for (const auto& event
: past_events
) {
158 profiler_event
->add_past_session_event(event
);
162 WriteProfilerData(process_data_phase
, process_id
, process_type
,
166 bool ProfilerMetricsProvider::IsCellularLogicEnabled() {
167 // For android get current connection type if the callback exists.
168 #if defined(OS_ANDROID)
169 if (!cellular_callback_
.is_null())
170 return cellular_callback_
.Run();
175 } // namespace metrics