Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / task_management / sampling / task_group.cc
blob330b80bf3978ab5b8212aacd9ad40b6841280f0a
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);
113 // First refresh the enabled non-expensive resources usages on the UI thread.
114 // 1- Refresh all the tasks.
115 for (auto& task_pair : tasks_)
116 task_pair.second->Refresh(update_interval, refresh_flags);
118 // 2- Refresh GPU memory (if enabled).
119 if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY, refresh_flags))
120 RefreshGpuMemory(gpu_memory_stats);
122 // 3- Refresh Windows handles (if enabled).
123 #if defined(OS_WIN)
124 if (IsResourceRefreshEnabled(REFRESH_TYPE_HANDLES, refresh_flags))
125 RefreshWindowsHandles();
126 #endif // defined(OS_WIN)
128 // 4- Refresh the NACL debug stub port (if enabled).
129 #if !defined(DISABLE_NACL)
130 if (IsResourceRefreshEnabled(REFRESH_TYPE_NACL, refresh_flags) &&
131 !tasks_.empty()) {
132 RefreshNaClDebugStubPort(tasks_.begin()->second->GetChildProcessUniqueID());
134 #endif // !defined(DISABLE_NACL)
136 // The remaining resource refreshes are time consuming and cannot be done on
137 // the UI thread. Do them all on the worker thread using the TaskGroupSampler.
138 // 5- CPU usage.
139 // 6- Memory usage.
140 // 7- Idle Wakeups per second.
141 worker_thread_sampler_->Refresh(refresh_flags);
144 Task* TaskGroup::GetTaskById(TaskId task_id) const {
145 DCHECK(ContainsKey(tasks_, task_id));
147 return tasks_.at(task_id);
150 void TaskGroup::RefreshGpuMemory(
151 const content::GPUVideoMemoryUsageStats& gpu_memory_stats) {
152 auto itr = gpu_memory_stats.process_map.find(process_id_);
153 if (itr == gpu_memory_stats.process_map.end()) {
154 gpu_memory_ = -1;
155 gpu_memory_has_duplicates_ = false;
156 return;
159 gpu_memory_ = static_cast<int64>(itr->second.video_memory);
160 gpu_memory_has_duplicates_ = itr->second.has_duplicates;
163 void TaskGroup::RefreshWindowsHandles() {
164 #if defined(OS_WIN)
165 GetWindowsHandles(process_handle_,
166 &gdi_current_handles_,
167 &gdi_peak_handles_,
168 &user_current_handles_,
169 &user_peak_handles_);
170 #endif // defined(OS_WIN)
173 void TaskGroup::RefreshNaClDebugStubPort(int child_process_unique_id) {
174 #if !defined(DISABLE_NACL)
175 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
176 nacl_debug_stub_port_ =
177 nacl_browser->GetProcessGdbDebugStubPort(child_process_unique_id);
178 #endif // !defined(DISABLE_NACL)
181 void TaskGroup::OnCpuRefreshDone(double cpu_usage) {
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
184 cpu_usage_ = cpu_usage;
187 void TaskGroup::OnMemoryUsageRefreshDone(MemoryUsageStats memory_usage) {
188 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
190 memory_usage_ = memory_usage;
193 void TaskGroup::OnIdleWakeupsRefreshDone(int idle_wakeups_per_second) {
194 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
196 idle_wakeups_per_second_ = idle_wakeups_per_second;
199 } // namespace task_management