blob: d8c07b346d0b50bb99bc9330e51d651e6a3ba30e [file] [log] [blame]
[email protected]702a12d2012-02-10 19:43:421// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]33047f12011-12-01 23:20:202// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/profiler_controller_impl.h"
6
7#include "base/bind.h"
[email protected]42a3ff572014-06-13 02:44:468#include "base/process/process_handle.h"
[email protected]1cb05db2012-04-13 00:39:269#include "base/tracked_objects.h"
[email protected]33047f12011-12-01 23:20:2010#include "content/common/child_process_messages.h"
[email protected]4967f792012-01-20 22:14:4011#include "content/public/browser/browser_child_process_host_iterator.h"
[email protected]33047f12011-12-01 23:20:2012#include "content/public/browser/browser_thread.h"
[email protected]4967f792012-01-20 22:14:4013#include "content/public/browser/child_process_data.h"
[email protected]33047f12011-12-01 23:20:2014#include "content/public/browser/profiler_subscriber.h"
15#include "content/public/browser/render_process_host.h"
[email protected]33047f12011-12-01 23:20:2016
[email protected]33047f12011-12-01 23:20:2017namespace content {
18
[email protected]46488322012-10-30 03:22:2019ProfilerController* ProfilerController::GetInstance() {
[email protected]33047f12011-12-01 23:20:2020 return ProfilerControllerImpl::GetInstance();
21}
22
23ProfilerControllerImpl* ProfilerControllerImpl::GetInstance() {
olli.raula36aa8be2015-09-10 11:14:2224 return base::Singleton<ProfilerControllerImpl>::get();
[email protected]33047f12011-12-01 23:20:2025}
26
27ProfilerControllerImpl::ProfilerControllerImpl() : subscriber_(NULL) {
28}
29
30ProfilerControllerImpl::~ProfilerControllerImpl() {
31}
32
33void ProfilerControllerImpl::OnPendingProcesses(int sequence_number,
34 int pending_processes,
35 bool end) {
mostynb4c27d042015-03-18 21:47:4736 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]33047f12011-12-01 23:20:2037 if (subscriber_)
38 subscriber_->OnPendingProcesses(sequence_number, pending_processes, end);
39}
40
41void ProfilerControllerImpl::OnProfilerDataCollected(
42 int sequence_number,
[email protected]1cb05db2012-04-13 00:39:2643 const tracked_objects::ProcessDataSnapshot& profiler_data,
vadimt379d7fe2015-04-01 00:09:3544 content::ProcessType process_type) {
[email protected]33047f12011-12-01 23:20:2045 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
46 BrowserThread::PostTask(
47 BrowserThread::UI, FROM_HERE,
48 base::Bind(&ProfilerControllerImpl::OnProfilerDataCollected,
49 base::Unretained(this),
50 sequence_number,
[email protected]1cb05db2012-04-13 00:39:2651 profiler_data,
52 process_type));
[email protected]33047f12011-12-01 23:20:2053 return;
54 }
55
mostynb4c27d042015-03-18 21:47:4756 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]1cb05db2012-04-13 00:39:2657 if (subscriber_) {
58 subscriber_->OnProfilerDataCollected(sequence_number, profiler_data,
59 process_type);
60 }
[email protected]33047f12011-12-01 23:20:2061}
62
63void ProfilerControllerImpl::Register(ProfilerSubscriber* subscriber) {
mostynb4c27d042015-03-18 21:47:4764 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]33047f12011-12-01 23:20:2065 DCHECK(!subscriber_);
66 subscriber_ = subscriber;
67}
68
[email protected]1cb05db2012-04-13 00:39:2669void ProfilerControllerImpl::Unregister(const ProfilerSubscriber* subscriber) {
70 DCHECK_EQ(subscriber_, subscriber);
71 subscriber_ = NULL;
[email protected]33047f12011-12-01 23:20:2072}
73
74void ProfilerControllerImpl::GetProfilerDataFromChildProcesses(
vadimte2de4732015-04-27 21:43:0275 int sequence_number,
76 int current_profiling_phase) {
mostynb4c27d042015-03-18 21:47:4777 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]33047f12011-12-01 23:20:2078
79 int pending_processes = 0;
[email protected]4967f792012-01-20 22:14:4080 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]42a3ff572014-06-13 02:44:4681 // In some cases, there may be no child process of the given type (for
82 // example, the GPU process may not exist and there may instead just be a
83 // GPU thread in the browser process). If that's the case, then the process
84 // handle will be base::kNullProcessHandle and we shouldn't ask it for data.
85 if (iter.GetData().handle == base::kNullProcessHandle)
[email protected]6b690322013-07-19 08:39:3486 continue;
[email protected]6b690322013-07-19 08:39:3487
[email protected]33047f12011-12-01 23:20:2088 ++pending_processes;
vadimte2de4732015-04-27 21:43:0289 if (!iter.Send(new ChildProcessMsg_GetChildProfilerData(
90 sequence_number, current_profiling_phase))) {
[email protected]33047f12011-12-01 23:20:2091 --pending_processes;
vadimte2de4732015-04-27 21:43:0292 }
[email protected]33047f12011-12-01 23:20:2093 }
94
95 BrowserThread::PostTask(
96 BrowserThread::UI,
97 FROM_HERE,
98 base::Bind(
99 &ProfilerControllerImpl::OnPendingProcesses,
100 base::Unretained(this),
101 sequence_number,
102 pending_processes,
103 true));
104}
105
vadimte2de4732015-04-27 21:43:02106// static
107void ProfilerControllerImpl::NotifyChildProcessesOfProfilingPhaseCompletion(
108 int profiling_phase) {
109 DCHECK_CURRENTLY_ON(BrowserThread::IO);
110
111 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
112 // In some cases, there may be no child process of the given type (for
113 // example, the GPU process may not exist and there may instead just be a
114 // GPU thread in the browser process). If that's the case, then the process
115 // handle will be base::kNullProcessHandle and we shouldn't send it a
116 // message.
117 if (iter.GetData().handle == base::kNullProcessHandle)
118 continue;
119
120 iter.Send(new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase));
121 }
122}
123
124void ProfilerControllerImpl::GetProfilerData(int sequence_number,
125 int current_profiling_phase) {
mostynb4c27d042015-03-18 21:47:47126 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]33047f12011-12-01 23:20:20127
vadimte2de4732015-04-27 21:43:02128 // Iterates through renderers in UI thread, and through other child processes
129 // in IO thread, and send them GetChildProfilerData message. Renderers have to
130 // be contacted from UI thread, and other processes - from IO thread.
[email protected]33047f12011-12-01 23:20:20131 int pending_processes = 0;
[email protected]33047f12011-12-01 23:20:20132 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
133 !it.IsAtEnd(); it.Advance()) {
134 ++pending_processes;
vadimte2de4732015-04-27 21:43:02135 if (!it.GetCurrentValue()->Send(new ChildProcessMsg_GetChildProfilerData(
136 sequence_number, current_profiling_phase))) {
[email protected]33047f12011-12-01 23:20:20137 --pending_processes;
138 }
139 }
140 OnPendingProcesses(sequence_number, pending_processes, false);
141
142 BrowserThread::PostTask(
vadimte2de4732015-04-27 21:43:02143 BrowserThread::IO, FROM_HERE,
[email protected]33047f12011-12-01 23:20:20144 base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses,
vadimte2de4732015-04-27 21:43:02145 base::Unretained(this), sequence_number,
146 current_profiling_phase));
147}
148
149void ProfilerControllerImpl::OnProfilingPhaseCompleted(int profiling_phase) {
150 DCHECK_CURRENTLY_ON(BrowserThread::UI);
151
152 // Iterates through renderers in UI thread, and through other child processes
153 // in IO thread, and send them OnProfilingPhase message. Renderers have to be
154 // contacted from UI thread, and other processes - from IO thread.
155 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
156 !it.IsAtEnd(); it.Advance()) {
157 it.GetCurrentValue()->Send(
158 new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase));
159 }
160
161 BrowserThread::PostTask(
162 BrowserThread::IO, FROM_HERE,
163 base::Bind(&ProfilerControllerImpl::
164 NotifyChildProcessesOfProfilingPhaseCompletion,
165 profiling_phase));
[email protected]33047f12011-12-01 23:20:20166}
167
[email protected]33047f12011-12-01 23:20:20168} // namespace content