|  | // Copyright 2013 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "base/process/process_metrics.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/check.h" | 
|  | #include "base/notreached.h" | 
|  | #include "base/numerics/safe_conversions.h" | 
|  | #include "base/values.h" | 
|  | #include "build/build_config.h" | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ | 
|  | BUILDFLAG(IS_AIX) | 
|  | int CalculateEventsPerSecond(uint64_t event_count, | 
|  | uint64_t* last_event_count, | 
|  | base::TimeTicks* last_calculated) { | 
|  | const base::TimeTicks time = base::TimeTicks::Now(); | 
|  |  | 
|  | int events_per_second = 0; | 
|  | if (*last_event_count != 0) { | 
|  | const uint64_t events_delta = event_count - *last_event_count; | 
|  | const base::TimeDelta time_delta = time - *last_calculated; | 
|  | DCHECK(!time_delta.is_zero()); | 
|  | events_per_second = ClampRound(events_delta / time_delta.InSecondsF()); | 
|  | } | 
|  |  | 
|  | *last_calculated = time; | 
|  | *last_event_count = event_count; | 
|  | return events_per_second; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | SystemMemoryInfoKB::SystemMemoryInfoKB() = default; | 
|  |  | 
|  | SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB&) = default; | 
|  |  | 
|  | SystemMemoryInfoKB& SystemMemoryInfoKB::operator=(const SystemMemoryInfoKB&) = | 
|  | default; | 
|  |  | 
|  | SystemMetrics::SystemMetrics() { | 
|  | committed_memory_ = 0; | 
|  | } | 
|  |  | 
|  | SystemMetrics SystemMetrics::Sample() { | 
|  | SystemMetrics system_metrics; | 
|  |  | 
|  | system_metrics.committed_memory_ = GetSystemCommitCharge(); | 
|  | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) | 
|  | GetSystemMemoryInfo(&system_metrics.memory_info_); | 
|  | GetVmStatInfo(&system_metrics.vmstat_info_); | 
|  | GetSystemDiskInfo(&system_metrics.disk_info_); | 
|  | #endif | 
|  | #if BUILDFLAG(IS_CHROMEOS) | 
|  | GetSwapInfo(&system_metrics.swap_info_); | 
|  | GetGraphicsMemoryInfo(&system_metrics.gpu_memory_info_); | 
|  | #endif | 
|  | #if BUILDFLAG(IS_WIN) | 
|  | GetSystemPerformanceInfo(&system_metrics.performance_); | 
|  | #endif | 
|  | return system_metrics; | 
|  | } | 
|  |  | 
|  | Value::Dict SystemMetrics::ToDict() const { | 
|  | Value::Dict res; | 
|  |  | 
|  | res.Set("committed_memory", static_cast<int>(committed_memory_)); | 
|  | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) | 
|  | Value::Dict meminfo = memory_info_.ToDict(); | 
|  | meminfo.Merge(vmstat_info_.ToDict()); | 
|  | res.Set("meminfo", std::move(meminfo)); | 
|  | res.Set("diskinfo", disk_info_.ToDict()); | 
|  | #endif | 
|  | #if BUILDFLAG(IS_CHROMEOS) | 
|  | res.Set("swapinfo", swap_info_.ToDict()); | 
|  | res.Set("gpu_meminfo", gpu_memory_info_.ToDict()); | 
|  | #endif | 
|  | #if BUILDFLAG(IS_WIN) | 
|  | res.Set("perfinfo", performance_.ToDict()); | 
|  | #endif | 
|  |  | 
|  | return res; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() { | 
|  | #if !BUILDFLAG(IS_MAC) | 
|  | return CreateProcessMetrics(base::GetCurrentProcessHandle()); | 
|  | #else | 
|  | return CreateProcessMetrics(base::GetCurrentProcessHandle(), nullptr); | 
|  | #endif  // !BUILDFLAG(IS_MAC) | 
|  | } | 
|  |  | 
|  | #if !BUILDFLAG(IS_FREEBSD) || !BUILDFLAG(IS_POSIX) | 
|  | double ProcessMetrics::GetPlatformIndependentCPUUsage( | 
|  | TimeDelta cumulative_cpu) { | 
|  | TimeTicks time = TimeTicks::Now(); | 
|  |  | 
|  | if (last_cumulative_cpu_.is_zero()) { | 
|  | // First call, just set the last values. | 
|  | last_cumulative_cpu_ = cumulative_cpu; | 
|  | last_cpu_time_ = time; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | TimeDelta cpu_time_delta = cumulative_cpu - last_cumulative_cpu_; | 
|  | TimeDelta time_delta = time - last_cpu_time_; | 
|  | if (time_delta.is_zero()) | 
|  | return 0; | 
|  |  | 
|  | last_cumulative_cpu_ = cumulative_cpu; | 
|  | last_cpu_time_ = time; | 
|  |  | 
|  | return 100.0 * cpu_time_delta / time_delta; | 
|  | } | 
|  |  | 
|  | double ProcessMetrics::GetPlatformIndependentCPUUsage() { | 
|  | return GetPlatformIndependentCPUUsage(GetCumulativeCPUUsage()); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if BUILDFLAG(IS_WIN) | 
|  | double ProcessMetrics::GetPreciseCPUUsage(TimeDelta cumulative_cpu) { | 
|  | TimeTicks time = TimeTicks::Now(); | 
|  |  | 
|  | if (last_precise_cumulative_cpu_.is_zero()) { | 
|  | // First call, just set the last values. | 
|  | last_precise_cumulative_cpu_ = cumulative_cpu; | 
|  | last_cpu_time_for_precise_cpu_usage_ = time; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | TimeDelta cpu_time_delta = cumulative_cpu - last_precise_cumulative_cpu_; | 
|  | TimeDelta time_delta = time - last_cpu_time_for_precise_cpu_usage_; | 
|  | DCHECK(!time_delta.is_zero()); | 
|  | if (time_delta.is_zero()) | 
|  | return 0; | 
|  |  | 
|  | last_precise_cumulative_cpu_ = cumulative_cpu; | 
|  | last_cpu_time_for_precise_cpu_usage_ = time; | 
|  |  | 
|  | return 100.0 * cpu_time_delta / time_delta; | 
|  | } | 
|  |  | 
|  | double ProcessMetrics::GetPreciseCPUUsage() { | 
|  | return GetPreciseCPUUsage(GetPreciseCumulativeCPUUsage()); | 
|  | } | 
|  | #endif  // BUILDFLAG(IS_WIN) | 
|  |  | 
|  | #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ | 
|  | BUILDFLAG(IS_AIX) | 
|  | int ProcessMetrics::CalculateIdleWakeupsPerSecond( | 
|  | uint64_t absolute_idle_wakeups) { | 
|  | return CalculateEventsPerSecond(absolute_idle_wakeups, | 
|  | &last_absolute_idle_wakeups_, | 
|  | &last_idle_wakeups_time_); | 
|  | } | 
|  | #else | 
|  | int ProcessMetrics::GetIdleWakeupsPerSecond() { | 
|  | NOTIMPLEMENTED();  // http://crbug.com/120488 | 
|  | return 0; | 
|  | } | 
|  | #endif  // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) | 
|  | // || BUILDFLAG(IS_AIX) | 
|  |  | 
|  | #if BUILDFLAG(IS_APPLE) | 
|  | int ProcessMetrics::CalculatePackageIdleWakeupsPerSecond( | 
|  | uint64_t absolute_package_idle_wakeups) { | 
|  | return CalculateEventsPerSecond(absolute_package_idle_wakeups, | 
|  | &last_absolute_package_idle_wakeups_, | 
|  | &last_package_idle_wakeups_time_); | 
|  | } | 
|  |  | 
|  | #endif  // BUILDFLAG(IS_APPLE) | 
|  |  | 
|  | #if !BUILDFLAG(IS_WIN) | 
|  | uint64_t ProcessMetrics::GetCumulativeDiskUsageInBytes() { | 
|  | // Not implemented. | 
|  | return 0; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | }  // namespace base |