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 sequenced_checker_() {
45 DCHECK(blocking_pool_runner
.get());
48 void TaskGroupSampler::Refresh(int64 refresh_flags
) {
49 DCHECK_CURRENTLY_ON(content::BrowserThread::UI
);
51 if (IsResourceRefreshEnabled(REFRESH_TYPE_CPU
, refresh_flags
)) {
52 base::PostTaskAndReplyWithResult(
53 blocking_pool_runner_
.get(),
55 base::Bind(&TaskGroupSampler::RefreshCpuUsage
, this),
56 on_cpu_refresh_callback_
);
59 if (IsResourceRefreshEnabled(REFRESH_TYPE_MEMORY
, refresh_flags
)) {
60 base::PostTaskAndReplyWithResult(
61 blocking_pool_runner_
.get(),
63 base::Bind(&TaskGroupSampler::RefreshMemoryUsage
, this),
64 on_memory_refresh_callback_
);
67 #if defined(OS_MACOSX) || defined(OS_LINUX)
68 if (IsResourceRefreshEnabled(REFRESH_TYPE_IDLE_WAKEUPS
, refresh_flags
)) {
69 base::PostTaskAndReplyWithResult(
70 blocking_pool_runner_
.get(),
72 base::Bind(&TaskGroupSampler::RefreshIdleWakeupsPerSecond
, this),
73 on_idle_wakeups_callback_
);
75 #endif // defined(OS_MACOSX) || defined(OS_LINUX)
78 TaskGroupSampler::~TaskGroupSampler() {
81 double TaskGroupSampler::RefreshCpuUsage() {
82 DCHECK(sequenced_checker_
.CalledOnValidSequencedThread());
84 return process_metrics_
->GetCPUUsage();
87 MemoryUsageStats
TaskGroupSampler::RefreshMemoryUsage() {
88 DCHECK(sequenced_checker_
.CalledOnValidSequencedThread());
90 // TODO(afakhry): Integrate Bruce's CL for faster retrieval of physical memory
93 MemoryUsageStats memory_usage
;
94 // Refreshing the physical/private/shared memory at one shot.
95 base::WorkingSetKBytes ws_usage
;
96 if (process_metrics_
->GetWorkingSetKBytes(&ws_usage
)) {
97 memory_usage
.private_bytes
= static_cast<int64
>(ws_usage
.priv
* 1024);
98 memory_usage
.shared_bytes
= static_cast<int64
>(ws_usage
.shared
* 1024);
100 // On Linux private memory is also resident. Just use it.
101 memory_usage
.physical_bytes
= memory_usage
.private_bytes
;
103 // Memory = working_set.private which is working set minus shareable. This
104 // avoids the unpredictable counting that occurs when calculating memory as
105 // working set minus shared (renderer code counted when one tab is open and
106 // not counted when two or more are open) and it is much more efficient to
107 // calculate on Windows.
108 memory_usage
.physical_bytes
=
109 static_cast<int64
>(process_metrics_
->GetWorkingSetSize());
110 memory_usage
.physical_bytes
-=
111 static_cast<int64
>(ws_usage
.shareable
* 1024);
118 int TaskGroupSampler::RefreshIdleWakeupsPerSecond() {
119 DCHECK(sequenced_checker_
.CalledOnValidSequencedThread());
121 return process_metrics_
->GetIdleWakeupsPerSecond();
124 } // namespace task_management