1 // Copyright 2013 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.
4 
5 #include "base/process/process_metrics.h"
6 
7 #include <utility>
8 
9 #include "base/logging.h"
10 #include "base/values.h"
11 #include "build/build_config.h"
12 
13 namespace {
CalculateEventsPerSecond(uint64_t event_count,uint64_t * last_event_count,base::TimeTicks * last_calculated)14 int CalculateEventsPerSecond(uint64_t event_count,
15                              uint64_t* last_event_count,
16                              base::TimeTicks* last_calculated) {
17   base::TimeTicks time = base::TimeTicks::Now();
18 
19   if (*last_event_count == 0) {
20     // First call, just set the last values.
21     *last_calculated = time;
22     *last_event_count = event_count;
23     return 0;
24   }
25 
26   int64_t events_delta = event_count - *last_event_count;
27   int64_t time_delta = (time - *last_calculated).InMicroseconds();
28   if (time_delta == 0) {
29     NOTREACHED();
30     return 0;
31   }
32 
33   *last_calculated = time;
34   *last_event_count = event_count;
35 
36   int64_t events_delta_for_ms =
37       events_delta * base::Time::kMicrosecondsPerSecond;
38   // Round the result up by adding 1/2 (the second term resolves to 1/2 without
39   // dropping down into floating point).
40   return (events_delta_for_ms + time_delta / 2) / time_delta;
41 }
42 
43 }  // namespace
44 
45 namespace base {
46 
47 SystemMemoryInfoKB::SystemMemoryInfoKB() = default;
48 
49 SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) =
50     default;
51 
SystemMetrics()52 SystemMetrics::SystemMetrics() {
53   committed_memory_ = 0;
54 }
55 
Sample()56 SystemMetrics SystemMetrics::Sample() {
57   SystemMetrics system_metrics;
58 
59   system_metrics.committed_memory_ = GetSystemCommitCharge();
60 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_BSD)
61   GetSystemMemoryInfo(&system_metrics.memory_info_);
62   GetVmStatInfo(&system_metrics.vmstat_info_);
63   GetSystemDiskInfo(&system_metrics.disk_info_);
64 #endif
65 #if defined(OS_CHROMEOS)
66   GetSwapInfo(&system_metrics.swap_info_);
67 #endif
68 #if defined(OS_WIN)
69   GetSystemPerformanceInfo(&system_metrics.performance_);
70 #endif
71   return system_metrics;
72 }
73 
ToValue() const74 std::unique_ptr<Value> SystemMetrics::ToValue() const {
75   std::unique_ptr<DictionaryValue> res(new DictionaryValue());
76 
77   res->SetIntKey("committed_memory", static_cast<int>(committed_memory_));
78 #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_BSD)
79   std::unique_ptr<DictionaryValue> meminfo = memory_info_.ToValue();
80   std::unique_ptr<DictionaryValue> vmstat = vmstat_info_.ToValue();
81   meminfo->MergeDictionary(vmstat.get());
82   res->Set("meminfo", std::move(meminfo));
83   res->Set("diskinfo", disk_info_.ToValue());
84 #endif
85 #if defined(OS_CHROMEOS)
86   res->Set("swapinfo", swap_info_.ToValue());
87 #endif
88 #if defined(OS_WIN)
89   res->Set("perfinfo", performance_.ToValue());
90 #endif
91 
92   return std::move(res);
93 }
94 
CreateCurrentProcessMetrics()95 std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() {
96 #if !defined(OS_MACOSX) || defined(OS_IOS)
97   return CreateProcessMetrics(base::GetCurrentProcessHandle());
98 #else
99   return CreateProcessMetrics(base::GetCurrentProcessHandle(), nullptr);
100 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
101 }
102 
103 #if !defined(OS_FREEBSD) || !defined(OS_POSIX)
GetPlatformIndependentCPUUsage()104 double ProcessMetrics::GetPlatformIndependentCPUUsage() {
105   TimeDelta cumulative_cpu = GetCumulativeCPUUsage();
106   TimeTicks time = TimeTicks::Now();
107 
108   if (last_cumulative_cpu_.is_zero()) {
109     // First call, just set the last values.
110     last_cumulative_cpu_ = cumulative_cpu;
111     last_cpu_time_ = time;
112     return 0;
113   }
114 
115   TimeDelta system_time_delta = cumulative_cpu - last_cumulative_cpu_;
116   TimeDelta time_delta = time - last_cpu_time_;
117   DCHECK(!time_delta.is_zero());
118   if (time_delta.is_zero())
119     return 0;
120 
121   last_cumulative_cpu_ = cumulative_cpu;
122   last_cpu_time_ = time;
123 
124   return 100.0 * system_time_delta.InMicrosecondsF() /
125          time_delta.InMicrosecondsF();
126 }
127 #endif
128 
129 #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) || defined(OS_BSD)
CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups)130 int ProcessMetrics::CalculateIdleWakeupsPerSecond(
131     uint64_t absolute_idle_wakeups) {
132   return CalculateEventsPerSecond(absolute_idle_wakeups,
133                                   &last_absolute_idle_wakeups_,
134                                   &last_idle_wakeups_time_);
135 }
136 #else
GetIdleWakeupsPerSecond()137 int ProcessMetrics::GetIdleWakeupsPerSecond() {
138   NOTIMPLEMENTED();  // http://crbug.com/120488
139   return 0;
140 }
141 #endif  // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) || defined(OS_BSD)
142 
143 #if defined(OS_MACOSX)
CalculatePackageIdleWakeupsPerSecond(uint64_t absolute_package_idle_wakeups)144 int ProcessMetrics::CalculatePackageIdleWakeupsPerSecond(
145     uint64_t absolute_package_idle_wakeups) {
146   return CalculateEventsPerSecond(absolute_package_idle_wakeups,
147                                   &last_absolute_package_idle_wakeups_,
148                                   &last_package_idle_wakeups_time_);
149 }
150 
151 #endif  // defined(OS_MACOSX)
152 
153 #if !defined(OS_WIN)
GetCumulativeDiskUsageInBytes()154 uint64_t ProcessMetrics::GetCumulativeDiskUsageInBytes() {
155   // Not implemented.
156   return 0;
157 }
158 #endif
159 
GetDiskUsageBytesPerSecond()160 uint64_t ProcessMetrics::GetDiskUsageBytesPerSecond() {
161   uint64_t cumulative_disk_usage = GetCumulativeDiskUsageInBytes();
162   return CalculateEventsPerSecond(cumulative_disk_usage,
163                                   &last_cumulative_disk_usage_,
164                                   &last_disk_usage_time_);
165 }
166 
167 }  // namespace base
168