Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / task_management / sampling / task_manager_impl.cc
blob97793437bf41e628dbb549152e5c42cc8558abcb
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());
190 // Ensure browser process group of task IDs are at the beginning of the
191 // list.
192 const TaskGroup* browser_group =
193 task_groups_by_proc_id_.at(base::GetCurrentProcId());
194 browser_group->AppendSortedTaskIds(&sorted_task_ids_);
196 for (const auto& groups_pair : task_groups_by_proc_id_) {
197 if (groups_pair.second == browser_group)
198 continue;
200 groups_pair.second->AppendSortedTaskIds(&sorted_task_ids_);
204 return sorted_task_ids_;
207 size_t TaskManagerImpl::GetNumberOfTasksOnSameProcess(TaskId task_id) const {
208 return GetTaskGroupByTaskId(task_id)->num_tasks();
211 void TaskManagerImpl::TaskAdded(Task* task) {
212 DCHECK(task);
214 TaskGroup* task_group = nullptr;
215 const base::ProcessId proc_id = task->process_id();
216 const TaskId task_id = task->task_id();
218 auto itr = task_groups_by_proc_id_.find(proc_id);
219 if (itr == task_groups_by_proc_id_.end()) {
220 task_group = new TaskGroup(task->process_handle(),
221 proc_id,
222 blocking_pool_runner_);
223 task_groups_by_proc_id_[proc_id] = task_group;
224 } else {
225 task_group = itr->second;
228 task_group->AddTask(task);
230 task_groups_by_task_id_[task_id] = task_group;
232 // Invalidate the cached sorted IDs by clearing the list.
233 sorted_task_ids_.clear();
235 NotifyObserversOnTaskAdded(task_id);
238 void TaskManagerImpl::TaskRemoved(Task* task) {
239 DCHECK(task);
241 const base::ProcessId proc_id = task->process_id();
242 const TaskId task_id = task->task_id();
244 DCHECK(ContainsKey(task_groups_by_proc_id_, proc_id));
245 DCHECK(ContainsKey(task_groups_by_task_id_, task_id));
247 NotifyObserversOnTaskToBeRemoved(task_id);
249 TaskGroup* task_group = task_groups_by_proc_id_.at(proc_id);
250 task_group->RemoveTask(task);
252 task_groups_by_task_id_.erase(task_id);
254 // Invalidate the cached sorted IDs by clearing the list.
255 sorted_task_ids_.clear();
257 if (task_group->empty()) {
258 task_groups_by_proc_id_.erase(proc_id);
259 delete task_group;
263 void TaskManagerImpl::OnVideoMemoryUsageStatsUpdate(
264 const content::GPUVideoMemoryUsageStats& gpu_memory_stats) {
265 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
267 gpu_memory_stats_ = gpu_memory_stats;
270 // static
271 void TaskManagerImpl::OnMultipleBytesReadUI(
272 std::vector<BytesReadParam>* params) {
273 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
274 DCHECK(params);
276 for (BytesReadParam& param : *params) {
277 if (!GetInstance()->UpdateTasksWithBytesRead(param)) {
278 // We can't match a task to the notification. That might mean the
279 // tab that started a download was closed, or the request may have had
280 // no originating task associated with it in the first place.
281 // We attribute orphaned/unaccounted activity to the Browser process.
282 DCHECK(param.origin_pid || (param.child_id != -1));
284 param.origin_pid = 0;
285 param.child_id = param.route_id = -1;
287 GetInstance()->UpdateTasksWithBytesRead(param);
292 void TaskManagerImpl::Refresh() {
293 if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY)) {
294 content::GpuDataManager::GetInstance()->
295 RequestVideoMemoryUsageStatsUpdate();
298 for (auto& groups_itr : task_groups_by_proc_id_) {
299 groups_itr.second->Refresh(gpu_memory_stats_,
300 GetCurrentRefreshTime(),
301 enabled_resources_flags());
304 NotifyObserversOnRefresh(GetTaskIdsList());
307 void TaskManagerImpl::StartUpdating() {
308 is_running_ = true;
310 for (auto& provider : task_providers_)
311 provider->SetObserver(this);
313 io_thread_helper_manager_.reset(new IoThreadHelperManager);
316 void TaskManagerImpl::StopUpdating() {
317 is_running_ = false;
319 io_thread_helper_manager_.reset();
321 for (auto& provider : task_providers_)
322 provider->ClearObserver();
324 STLDeleteValues(&task_groups_by_proc_id_);
325 task_groups_by_task_id_.clear();
326 sorted_task_ids_.clear();
329 bool TaskManagerImpl::UpdateTasksWithBytesRead(const BytesReadParam& param) {
330 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
332 for (auto& task_provider : task_providers_) {
333 Task* task = task_provider->GetTaskOfUrlRequest(param.origin_pid,
334 param.child_id,
335 param.route_id);
336 if (task) {
337 task->OnNetworkBytesRead(param.byte_count);
338 return true;
342 // Couldn't match the bytes to any existing task.
343 return false;
346 TaskGroup* TaskManagerImpl::GetTaskGroupByTaskId(TaskId task_id) const {
347 DCHECK(ContainsKey(task_groups_by_task_id_, task_id));
349 return task_groups_by_task_id_.at(task_id);
352 Task* TaskManagerImpl::GetTaskByTaskId(TaskId task_id) const {
353 return GetTaskGroupByTaskId(task_id)->GetTaskById(task_id);
356 } // namespace task_management