ExtensionSyncService: listen for relevant changes instead of being explicitly called...
[chromium-blink-merge.git] / chrome / browser / task_management / sampling / task_manager_impl.cc
blob32fc31adf73b8346c7a4dd6e5b673b0a1cb4dcaf
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.
5 #include "chrome/browser/task_management/sampling/task_manager_impl.h"
7 #include "base/stl_util.h"
8 #include "chrome/browser/task_management/providers/browser_process_task_provider.h"
9 #include "chrome/browser/task_management/providers/child_process_task_provider.h"
10 #include "chrome/browser/task_management/providers/web_contents/web_contents_task_provider.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "content/public/browser/gpu_data_manager.h"
14 namespace task_management {
16 namespace {
18 inline scoped_refptr<base::SequencedTaskRunner> GetBlockingPoolRunner() {
19 base::SequencedWorkerPool* blocking_pool =
20 content::BrowserThread::GetBlockingPool();
21 base::SequencedWorkerPool::SequenceToken token =
22 blocking_pool->GetSequenceToken();
24 DCHECK(token.IsValid());
26 return blocking_pool->GetSequencedTaskRunner(token);
29 base::LazyInstance<TaskManagerImpl> lazy_task_manager_instance =
30 LAZY_INSTANCE_INITIALIZER;
32 } // namespace
34 TaskManagerImpl::TaskManagerImpl()
35 : blocking_pool_runner_(GetBlockingPoolRunner()),
36 is_running_(false) {
37 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
39 task_providers_.push_back(new BrowserProcessTaskProvider());
40 task_providers_.push_back(new ChildProcessTaskProvider());
41 task_providers_.push_back(new WebContentsTaskProvider());
43 content::GpuDataManager::GetInstance()->AddObserver(this);
46 TaskManagerImpl::~TaskManagerImpl() {
47 content::GpuDataManager::GetInstance()->RemoveObserver(this);
49 STLDeleteValues(&task_groups_by_proc_id_);
52 // static
53 TaskManagerImpl* TaskManagerImpl::GetInstance() {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
56 return lazy_task_manager_instance.Pointer();
59 void TaskManagerImpl::ActivateTask(TaskId task_id) {
60 GetTaskByTaskId(task_id)->Activate();
63 double TaskManagerImpl::GetCpuUsage(TaskId task_id) const {
64 return GetTaskGroupByTaskId(task_id)->cpu_usage();
67 int64 TaskManagerImpl::GetPhysicalMemoryUsage(TaskId task_id) const {
68 return GetTaskGroupByTaskId(task_id)->physical_bytes();
71 int64 TaskManagerImpl::GetPrivateMemoryUsage(TaskId task_id) const {
72 return GetTaskGroupByTaskId(task_id)->private_bytes();
75 int64 TaskManagerImpl::GetSharedMemoryUsage(TaskId task_id) const {
76 return GetTaskGroupByTaskId(task_id)->shared_bytes();
79 int64 TaskManagerImpl::GetGpuMemoryUsage(TaskId task_id,
80 bool* has_duplicates) const {
81 const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
82 if (has_duplicates)
83 *has_duplicates = task_group->gpu_memory_has_duplicates();
84 return task_group->gpu_memory();
87 int TaskManagerImpl::GetIdleWakeupsPerSecond(TaskId task_id) const {
88 return GetTaskGroupByTaskId(task_id)->idle_wakeups_per_second();
91 int TaskManagerImpl::GetNaClDebugStubPort(TaskId task_id) const {
92 #if !defined(DISABLE_NACL)
93 return GetTaskGroupByTaskId(task_id)->nacl_debug_stub_port();
94 #else
95 return -1;
96 #endif // !defined(DISABLE_NACL)
99 void TaskManagerImpl::GetGDIHandles(TaskId task_id,
100 int64* current,
101 int64* peak) const {
102 #if defined(OS_WIN)
103 const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
104 *current = task_group->gdi_current_handles();
105 *peak = task_group->gdi_peak_handles();
106 #else
107 *current = -1;
108 *peak = -1;
109 #endif // defined(OS_WIN)
112 void TaskManagerImpl::GetUSERHandles(TaskId task_id,
113 int64* current,
114 int64* peak) const {
115 #if defined(OS_WIN)
116 const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
117 *current = task_group->user_current_handles();
118 *peak = task_group->user_peak_handles();
119 #else
120 *current = -1;
121 *peak = -1;
122 #endif // defined(OS_WIN)
125 const base::string16& TaskManagerImpl::GetTitle(TaskId task_id) const {
126 return GetTaskByTaskId(task_id)->title();
129 base::string16 TaskManagerImpl::GetProfileName(TaskId task_id) const {
130 return GetTaskByTaskId(task_id)->GetProfileName();
133 const gfx::ImageSkia& TaskManagerImpl::GetIcon(TaskId task_id) const {
134 return GetTaskByTaskId(task_id)->icon();
137 const base::ProcessHandle& TaskManagerImpl::GetProcessHandle(
138 TaskId task_id) const {
139 return GetTaskGroupByTaskId(task_id)->process_handle();
142 const base::ProcessId& TaskManagerImpl::GetProcessId(TaskId task_id) const {
143 return GetTaskGroupByTaskId(task_id)->process_id();
146 Task::Type TaskManagerImpl::GetType(TaskId task_id) const {
147 return GetTaskByTaskId(task_id)->GetType();
150 int64 TaskManagerImpl::GetNetworkUsage(TaskId task_id) const {
151 return GetTaskByTaskId(task_id)->network_usage();
154 int64 TaskManagerImpl::GetSqliteMemoryUsed(TaskId task_id) const {
155 return GetTaskByTaskId(task_id)->GetSqliteMemoryUsed();
158 bool TaskManagerImpl::GetV8Memory(TaskId task_id,
159 int64* allocated,
160 int64* used) const {
161 const Task* task = GetTaskByTaskId(task_id);
162 if (!task->ReportsV8Memory())
163 return false;
165 *allocated = task->GetV8MemoryAllocated();
166 *used = task->GetV8MemoryUsed();
168 return true;
171 bool TaskManagerImpl::GetWebCacheStats(
172 TaskId task_id,
173 blink::WebCache::ResourceTypeStats* stats) const {
174 const Task* task = GetTaskByTaskId(task_id);
175 if (!task->ReportsWebCacheStats())
176 return false;
178 *stats = task->GetWebCacheStats();
180 return true;
183 const TaskIdList& TaskManagerImpl::GetTaskIdsList() const {
184 DCHECK(is_running_) << "Task manager is not running. You must observe the "
185 "task manager for it to start running";
187 if (sorted_task_ids_.empty()) {
188 sorted_task_ids_.reserve(task_groups_by_task_id_.size());
189 for (const auto& groups_pair : task_groups_by_proc_id_)
190 groups_pair.second->AppendSortedTaskIds(&sorted_task_ids_);
193 return sorted_task_ids_;
196 size_t TaskManagerImpl::GetNumberOfTasksOnSameProcess(TaskId task_id) const {
197 return GetTaskGroupByTaskId(task_id)->num_tasks();
200 void TaskManagerImpl::TaskAdded(Task* task) {
201 DCHECK(task);
203 TaskGroup* task_group = nullptr;
204 const base::ProcessId proc_id = task->process_id();
205 const TaskId task_id = task->task_id();
207 auto itr = task_groups_by_proc_id_.find(proc_id);
208 if (itr == task_groups_by_proc_id_.end()) {
209 task_group = new TaskGroup(task->process_handle(),
210 proc_id,
211 blocking_pool_runner_);
212 task_groups_by_proc_id_[proc_id] = task_group;
213 } else {
214 task_group = itr->second;
217 task_group->AddTask(task);
219 task_groups_by_task_id_[task_id] = task_group;
221 // Invalidate the cached sorted IDs by clearing the list.
222 sorted_task_ids_.clear();
224 NotifyObserversOnTaskAdded(task_id);
227 void TaskManagerImpl::TaskRemoved(Task* task) {
228 DCHECK(task);
230 const base::ProcessId proc_id = task->process_id();
231 const TaskId task_id = task->task_id();
233 DCHECK(ContainsKey(task_groups_by_proc_id_, proc_id));
234 DCHECK(ContainsKey(task_groups_by_task_id_, task_id));
236 NotifyObserversOnTaskToBeRemoved(task_id);
238 TaskGroup* task_group = task_groups_by_proc_id_.at(proc_id);
239 task_group->RemoveTask(task);
241 task_groups_by_task_id_.erase(task_id);
243 // Invalidate the cached sorted IDs by clearing the list.
244 sorted_task_ids_.clear();
246 if (task_group->empty()) {
247 task_groups_by_proc_id_.erase(proc_id);
248 delete task_group;
252 void TaskManagerImpl::OnVideoMemoryUsageStatsUpdate(
253 const content::GPUVideoMemoryUsageStats& gpu_memory_stats) {
254 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
256 gpu_memory_stats_ = gpu_memory_stats;
259 // static
260 void TaskManagerImpl::OnMultipleBytesReadUI(
261 std::vector<BytesReadParam>* params) {
262 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
263 DCHECK(params);
265 for (BytesReadParam& param : *params) {
266 if (!GetInstance()->UpdateTasksWithBytesRead(param)) {
267 // We can't match a task to the notification. That might mean the
268 // tab that started a download was closed, or the request may have had
269 // no originating task associated with it in the first place.
270 // We attribute orphaned/unaccounted activity to the Browser process.
271 DCHECK(param.origin_pid || (param.child_id != -1));
273 param.origin_pid = 0;
274 param.child_id = param.route_id = -1;
276 GetInstance()->UpdateTasksWithBytesRead(param);
281 void TaskManagerImpl::Refresh() {
282 if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY)) {
283 content::GpuDataManager::GetInstance()->
284 RequestVideoMemoryUsageStatsUpdate();
287 for (auto& groups_itr : task_groups_by_proc_id_) {
288 groups_itr.second->Refresh(gpu_memory_stats_,
289 GetCurrentRefreshTime(),
290 enabled_resources_flags());
293 TaskIdList task_ids(GetTaskIdsList());
294 NotifyObserversOnRefresh(task_ids);
297 void TaskManagerImpl::StartUpdating() {
298 is_running_ = true;
300 for (auto& provider : task_providers_)
301 provider->SetObserver(this);
303 io_thread_helper_manager_.reset(new IoThreadHelperManager);
306 void TaskManagerImpl::StopUpdating() {
307 is_running_ = false;
309 io_thread_helper_manager_.reset();
311 for (auto& provider : task_providers_)
312 provider->ClearObserver();
314 STLDeleteValues(&task_groups_by_proc_id_);
315 task_groups_by_task_id_.clear();
316 sorted_task_ids_.clear();
319 bool TaskManagerImpl::UpdateTasksWithBytesRead(const BytesReadParam& param) {
320 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
322 for (auto& task_provider : task_providers_) {
323 Task* task = task_provider->GetTaskOfUrlRequest(param.origin_pid,
324 param.child_id,
325 param.route_id);
326 if (task) {
327 task->OnNetworkBytesRead(param.byte_count);
328 return true;
332 // Couldn't match the bytes to any existing task.
333 return false;
336 TaskGroup* TaskManagerImpl::GetTaskGroupByTaskId(TaskId task_id) const {
337 DCHECK(ContainsKey(task_groups_by_task_id_, task_id));
339 return task_groups_by_task_id_.at(task_id);
342 Task* TaskManagerImpl::GetTaskByTaskId(TaskId task_id) const {
343 return GetTaskGroupByTaskId(task_id)->GetTaskById(task_id);
346 } // namespace task_management