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_sampler.h"
8 #include "base/callback.h"
9 #include "chrome/browser/task_management/task_manager_observer.h"
10 #include "content/public/browser/browser_child_process_host.h"
11 #include "content/public/browser/browser_thread.h"
13 namespace task_management
{
17 base::ProcessMetrics
* CreateProcessMetrics(base::ProcessHandle handle
) {
18 #if !defined(OS_MACOSX)
19 return base::ProcessMetrics::CreateProcessMetrics(handle
);
21 return base::ProcessMetrics::CreateProcessMetrics(
22 handle
, content::BrowserChildProcessHost::GetPortProvider());
26 inline bool IsResourceRefreshEnabled(RefreshType refresh_type
,
28 return (refresh_flags
& refresh_type
) != 0;
33 TaskGroupSampler::TaskGroupSampler(
34 base::ProcessHandle proc_handle
,
35 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_pool_runner
,
36 const OnCpuRefreshCallback
& on_cpu_refresh
,
37 const OnMemoryRefreshCallback
& on_memory_refresh
,
38 const OnIdleWakeupsCallback
& on_idle_wakeups
)
39 : process_metrics_(CreateProcessMetrics(proc_handle
)),
40 blocking_pool_runner_(blocking_pool_runner
),
41 on_cpu_refresh_callback_(on_cpu_refresh
),
42 on_memory_refresh_callback_(on_memory_refresh
),
43 on_idle_wakeups_callback_(on_idle_wakeups
) {
44 DCHECK(blocking_pool_runner
.get());
46 // This object will be created on the UI thread, however the sequenced checker
47 // will be used to assert we're running the expensive operations on one of the
48 // blocking pool threads.
49 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
50 worker_pool_sequenced_checker_
.DetachFromSequence();
53 void TaskGroupSampler::Refresh(int64 refresh_flags
) {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
56 if (IsResourceRefreshEnabled(REFRESH_TYPE_CPU
, refresh_flags
)) {
57 base::PostTaskAndReplyWithResult(
58 blocking_pool_runner_
.get(),
60 base::Bind(&TaskGroupSampler::RefreshCpuUsage
, this),
61 on_cpu_refresh_callback_
);
64 if (IsResourceRefreshEnabled(REFRESH_TYPE_MEMORY
, refresh_flags
)) {
65 base::PostTaskAndReplyWithResult(
66 blocking_pool_runner_
.get(),
68 base::Bind(&TaskGroupSampler::RefreshMemoryUsage
, this),
69 on_memory_refresh_callback_
);
72 #if defined(OS_MACOSX) || defined(OS_LINUX)
73 if (IsResourceRefreshEnabled(REFRESH_TYPE_IDLE_WAKEUPS
, refresh_flags
)) {
74 base::PostTaskAndReplyWithResult(
75 blocking_pool_runner_
.get(),
77 base::Bind(&TaskGroupSampler::RefreshIdleWakeupsPerSecond
, this),
78 on_idle_wakeups_callback_
);
80 #endif // defined(OS_MACOSX) || defined(OS_LINUX)
83 TaskGroupSampler::~TaskGroupSampler() {
86 double TaskGroupSampler::RefreshCpuUsage() {
87 DCHECK(worker_pool_sequenced_checker_
.CalledOnValidSequencedThread());
89 return process_metrics_
->GetCPUUsage();
92 MemoryUsageStats
TaskGroupSampler::RefreshMemoryUsage() {
93 DCHECK(worker_pool_sequenced_checker_
.CalledOnValidSequencedThread());
95 // TODO(afakhry): Integrate Bruce's CL for faster retrieval of physical memory
98 MemoryUsageStats memory_usage
;
99 // Refreshing the physical/private/shared memory at one shot.
100 base::WorkingSetKBytes ws_usage
;
101 if (process_metrics_
->GetWorkingSetKBytes(&ws_usage
)) {
102 memory_usage
.private_bytes
= static_cast<int64
>(ws_usage
.priv
* 1024);
103 memory_usage
.shared_bytes
= static_cast<int64
>(ws_usage
.shared
* 1024);
104 #if defined(OS_LINUX)
105 // On Linux private memory is also resident. Just use it.
106 memory_usage
.physical_bytes
= memory_usage
.private_bytes
;
108 // Memory = working_set.private which is working set minus shareable. This
109 // avoids the unpredictable counting that occurs when calculating memory as
110 // working set minus shared (renderer code counted when one tab is open and
111 // not counted when two or more are open) and it is much more efficient to
112 // calculate on Windows.
113 memory_usage
.physical_bytes
=
114 static_cast<int64
>(process_metrics_
->GetWorkingSetSize());
115 memory_usage
.physical_bytes
-=
116 static_cast<int64
>(ws_usage
.shareable
* 1024);
123 int TaskGroupSampler::RefreshIdleWakeupsPerSecond() {
124 DCHECK(worker_pool_sequenced_checker_
.CalledOnValidSequencedThread());
126 return process_metrics_
->GetIdleWakeupsPerSecond();
129 } // namespace task_management