Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / task_management / sampling / task_group.cc
blob45c596f9717214f92cdb34eb134f0715f41a6456
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_group.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/stl_util.h"
10 #include "chrome/browser/task_management/task_manager_observer.h"
11 #include "components/nacl/browser/nacl_browser.h"
12 #include "content/public/browser/browser_thread.h"
14 namespace task_management {
16 namespace {
18 inline bool IsResourceRefreshEnabled(RefreshType refresh_type,
19 int refresh_flags) {
20 return (refresh_flags & refresh_type) != 0;
23 #if defined(OS_WIN)
24 // Gets the GDI and USER Handles on Windows at one shot.
25 void GetWindowsHandles(base::ProcessHandle handle,
26 int64* out_gdi_current,
27 int64* out_gdi_peak,
28 int64* out_user_current,
29 int64* out_user_peak) {
30 *out_gdi_current = 0;
31 *out_gdi_peak = 0;
32 *out_user_current = 0;
33 *out_user_peak = 0;
34 // Get a handle to |process| that has PROCESS_QUERY_INFORMATION rights.
35 HANDLE current_process = GetCurrentProcess();
36 HANDLE process_with_query_rights;
37 if (DuplicateHandle(current_process, handle, current_process,
38 &process_with_query_rights, PROCESS_QUERY_INFORMATION,
39 false, 0)) {
40 *out_gdi_current = static_cast<int64>(
41 GetGuiResources(process_with_query_rights, GR_GDIOBJECTS));
42 *out_gdi_peak = static_cast<int64>(
43 GetGuiResources(process_with_query_rights, GR_GDIOBJECTS_PEAK));
44 *out_user_current = static_cast<int64>(
45 GetGuiResources(process_with_query_rights, GR_USEROBJECTS));
46 *out_user_peak = static_cast<int64>(
47 GetGuiResources(process_with_query_rights, GR_USEROBJECTS_PEAK));
48 CloseHandle(process_with_query_rights);
51 #endif // defined(OS_WIN)
53 } // namespace
55 TaskGroup::TaskGroup(
56 base::ProcessHandle proc_handle,
57 base::ProcessId proc_id,
58 const scoped_refptr<base::SequencedTaskRunner>& blocking_pool_runner)
59 : process_handle_(proc_handle),
60 process_id_(proc_id),
61 worker_thread_sampler_(nullptr),
62 tasks_(),
63 cpu_usage_(0.0),
64 memory_usage_(),
65 gpu_memory_(-1),
66 #if defined(OS_WIN)
67 gdi_current_handles_(-1),
68 gdi_peak_handles_(-1),
69 user_current_handles_(-1),
70 user_peak_handles_(-1),
71 #endif // defined(OS_WIN)
72 #if !defined(DISABLE_NACL)
73 nacl_debug_stub_port_(-1),
74 #endif // !defined(DISABLE_NACL)
75 idle_wakeups_per_second_(-1),
76 gpu_memory_has_duplicates_(false),
77 weak_ptr_factory_(this) {
78 scoped_refptr<TaskGroupSampler> sampler(
79 new TaskGroupSampler(proc_handle,
80 blocking_pool_runner,
81 base::Bind(&TaskGroup::OnCpuRefreshDone,
82 weak_ptr_factory_.GetWeakPtr()),
83 base::Bind(&TaskGroup::OnMemoryUsageRefreshDone,
84 weak_ptr_factory_.GetWeakPtr()),
85 base::Bind(&TaskGroup::OnIdleWakeupsRefreshDone,
86 weak_ptr_factory_.GetWeakPtr())));
87 worker_thread_sampler_.swap(sampler);
90 TaskGroup::~TaskGroup() {
93 void TaskGroup::AddTask(Task* task) {
94 DCHECK(task);
95 DCHECK(task->process_id() == process_id_);
96 DCHECK(!ContainsKey(tasks_, task->task_id()));
98 tasks_[task->task_id()] = task;
101 void TaskGroup::RemoveTask(Task* task) {
102 DCHECK(task);
103 DCHECK(ContainsKey(tasks_, task->task_id()));
105 tasks_.erase(task->task_id());
108 void TaskGroup::Refresh(
109 const content::GPUVideoMemoryUsageStats& gpu_memory_stats,
110 base::TimeDelta update_interval,
111 int64 refresh_flags) {
112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
114 // First refresh the enabled non-expensive resources usages on the UI thread.
115 // 1- Refresh all the tasks.
116 for (auto& task_pair : tasks_)
117 task_pair.second->Refresh(update_interval, refresh_flags);
119 // 2- Refresh GPU memory (if enabled).
120 if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY, refresh_flags))
121 RefreshGpuMemory(gpu_memory_stats);
123 // 3- Refresh Windows handles (if enabled).
124 #if defined(OS_WIN)
125 if (IsResourceRefreshEnabled(REFRESH_TYPE_HANDLES, refresh_flags))
126 RefreshWindowsHandles();
127 #endif // defined(OS_WIN)
129 // 4- Refresh the NACL debug stub port (if enabled).
130 #if !defined(DISABLE_NACL)
131 if (IsResourceRefreshEnabled(REFRESH_TYPE_NACL, refresh_flags) &&
132 !tasks_.empty()) {
133 RefreshNaClDebugStubPort(tasks_.begin()->second->GetChildProcessUniqueID());
135 #endif // !defined(DISABLE_NACL)
137 // The remaining resource refreshes are time consuming and cannot be done on
138 // the UI thread. Do them all on the worker thread using the TaskGroupSampler.
139 // 5- CPU usage.
140 // 6- Memory usage.
141 // 7- Idle Wakeups per second.
142 worker_thread_sampler_->Refresh(refresh_flags);
145 void TaskGroup::AppendSortedTaskIds(TaskIdList* out_list) const {
146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
147 DCHECK(out_list);
149 for (const auto& task_pair : tasks_)
150 out_list->push_back(task_pair.first);
153 Task* TaskGroup::GetTaskById(TaskId task_id) const {
154 DCHECK(ContainsKey(tasks_, task_id));
156 return tasks_.at(task_id);
159 void TaskGroup::RefreshGpuMemory(
160 const content::GPUVideoMemoryUsageStats& gpu_memory_stats) {
161 auto itr = gpu_memory_stats.process_map.find(process_id_);
162 if (itr == gpu_memory_stats.process_map.end()) {
163 gpu_memory_ = -1;
164 gpu_memory_has_duplicates_ = false;
165 return;
168 gpu_memory_ = static_cast<int64>(itr->second.video_memory);
169 gpu_memory_has_duplicates_ = itr->second.has_duplicates;
172 void TaskGroup::RefreshWindowsHandles() {
173 #if defined(OS_WIN)
174 GetWindowsHandles(process_handle_,
175 &gdi_current_handles_,
176 &gdi_peak_handles_,
177 &user_current_handles_,
178 &user_peak_handles_);
179 #endif // defined(OS_WIN)
182 void TaskGroup::RefreshNaClDebugStubPort(int child_process_unique_id) {
183 #if !defined(DISABLE_NACL)
184 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
185 nacl_debug_stub_port_ =
186 nacl_browser->GetProcessGdbDebugStubPort(child_process_unique_id);
187 #endif // !defined(DISABLE_NACL)
190 void TaskGroup::OnCpuRefreshDone(double cpu_usage) {
191 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
193 cpu_usage_ = cpu_usage;
196 void TaskGroup::OnMemoryUsageRefreshDone(MemoryUsageStats memory_usage) {
197 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
199 memory_usage_ = memory_usage;
202 void TaskGroup::OnIdleWakeupsRefreshDone(int idle_wakeups_per_second) {
203 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
205 idle_wakeups_per_second_ = idle_wakeups_per_second;
208 } // namespace task_management