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 "chrome/browser/metrics/profiler_metrics_provider.h"
10 #include "base/tracked_objects.h"
11 #include "components/metrics/metrics_log_base.h"
12 #include "components/nacl/common/nacl_process_type.h"
13 #include "content/public/common/process_type.h"
15 using metrics::MetricsLogBase
;
16 using metrics::ProfilerEventProto
;
17 using tracked_objects::ProcessDataSnapshot
;
21 ProfilerEventProto::TrackedObject::ProcessType
AsProtobufProcessType(
23 switch (process_type
) {
24 case content::PROCESS_TYPE_BROWSER
:
25 return ProfilerEventProto::TrackedObject::BROWSER
;
26 case content::PROCESS_TYPE_RENDERER
:
27 return ProfilerEventProto::TrackedObject::RENDERER
;
28 case content::PROCESS_TYPE_PLUGIN
:
29 return ProfilerEventProto::TrackedObject::PLUGIN
;
30 case content::PROCESS_TYPE_WORKER
:
31 return ProfilerEventProto::TrackedObject::WORKER
;
32 case content::PROCESS_TYPE_UTILITY
:
33 return ProfilerEventProto::TrackedObject::UTILITY
;
34 case content::PROCESS_TYPE_ZYGOTE
:
35 return ProfilerEventProto::TrackedObject::ZYGOTE
;
36 case content::PROCESS_TYPE_SANDBOX_HELPER
:
37 return ProfilerEventProto::TrackedObject::SANDBOX_HELPER
;
38 case content::PROCESS_TYPE_GPU
:
39 return ProfilerEventProto::TrackedObject::GPU
;
40 case content::PROCESS_TYPE_PPAPI_PLUGIN
:
41 return ProfilerEventProto::TrackedObject::PPAPI_PLUGIN
;
42 case content::PROCESS_TYPE_PPAPI_BROKER
:
43 return ProfilerEventProto::TrackedObject::PPAPI_BROKER
;
44 case PROCESS_TYPE_NACL_LOADER
:
45 return ProfilerEventProto::TrackedObject::NACL_LOADER
;
46 case PROCESS_TYPE_NACL_BROKER
:
47 return ProfilerEventProto::TrackedObject::NACL_BROKER
;
50 return ProfilerEventProto::TrackedObject::UNKNOWN
;
54 // Maps a thread name by replacing trailing sequence of digits with "*".
56 // 1. "BrowserBlockingWorker1/23857" => "BrowserBlockingWorker1/*"
57 // 2. "Chrome_IOThread" => "Chrome_IOThread"
58 std::string
MapThreadName(const std::string
& thread_name
) {
59 size_t i
= thread_name
.length();
61 while (i
> 0 && isdigit(thread_name
[i
- 1])) {
65 if (i
== thread_name
.length())
68 return thread_name
.substr(0, i
) + '*';
71 // Normalizes a source filename (which is platform- and build-method-dependent)
72 // by extracting the last component of the full file name.
73 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" =>
75 std::string
NormalizeFileName(const std::string
& file_name
) {
76 const size_t offset
= file_name
.find_last_of("\\/");
77 return offset
!= std::string::npos
? file_name
.substr(offset
+ 1) : file_name
;
80 void WriteProfilerData(const ProcessDataSnapshot
& profiler_data
,
82 ProfilerEventProto
* performance_profile
) {
83 for (std::vector
<tracked_objects::TaskSnapshot
>::const_iterator it
=
84 profiler_data
.tasks
.begin();
85 it
!= profiler_data
.tasks
.end();
87 const tracked_objects::DeathDataSnapshot
& death_data
= it
->death_data
;
88 ProfilerEventProto::TrackedObject
* tracked_object
=
89 performance_profile
->add_tracked_object();
90 tracked_object
->set_birth_thread_name_hash(
91 MetricsLogBase::Hash(MapThreadName(it
->birth
.thread_name
)));
92 tracked_object
->set_exec_thread_name_hash(
93 MetricsLogBase::Hash(MapThreadName(it
->death_thread_name
)));
94 tracked_object
->set_source_file_name_hash(
95 MetricsLogBase::Hash(NormalizeFileName(it
->birth
.location
.file_name
)));
96 tracked_object
->set_source_function_name_hash(
97 MetricsLogBase::Hash(it
->birth
.location
.function_name
));
98 tracked_object
->set_source_line_number(it
->birth
.location
.line_number
);
99 tracked_object
->set_exec_count(death_data
.count
);
100 tracked_object
->set_exec_time_total(death_data
.run_duration_sum
);
101 tracked_object
->set_exec_time_sampled(death_data
.run_duration_sample
);
102 tracked_object
->set_queue_time_total(death_data
.queue_duration_sum
);
103 tracked_object
->set_queue_time_sampled(death_data
.queue_duration_sample
);
104 tracked_object
->set_process_type(AsProtobufProcessType(process_type
));
105 tracked_object
->set_process_id(profiler_data
.process_id
);
111 ProfilerMetricsProvider::ProfilerMetricsProvider() : has_profiler_data_(false) {
114 ProfilerMetricsProvider::~ProfilerMetricsProvider() {
117 void ProfilerMetricsProvider::ProvideGeneralMetrics(
118 metrics::ChromeUserMetricsExtension
* uma_proto
) {
119 if (!has_profiler_data_
)
122 DCHECK_EQ(tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
,
123 tracked_objects::GetTimeSourceType());
125 DCHECK_EQ(0, uma_proto
->profiler_event_size());
126 ProfilerEventProto
* profile
= uma_proto
->add_profiler_event();
127 profile
->Swap(&profiler_event_cache_
);
128 has_profiler_data_
= false;
131 void ProfilerMetricsProvider::RecordProfilerData(
132 const tracked_objects::ProcessDataSnapshot
& process_data
,
134 if (tracked_objects::GetTimeSourceType() !=
135 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME
) {
136 // We currently only support the default time source, wall clock time.
140 has_profiler_data_
= true;
141 profiler_event_cache_
.set_profile_type(ProfilerEventProto::STARTUP_PROFILE
);
142 profiler_event_cache_
.set_time_source(ProfilerEventProto::WALL_CLOCK_TIME
);
143 WriteProfilerData(process_data
, process_type
, &profiler_event_cache_
);