|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // 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/logging.h" | 
|  | #include "base/values.h" | 
|  | #include "build_config.h" | 
|  |  | 
|  | #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) | 
|  | namespace { | 
|  | int CalculateEventsPerSecond(uint64_t event_count, | 
|  | uint64_t* last_event_count, | 
|  | base::TimeTicks* last_calculated) { | 
|  | base::TimeTicks time = base::TimeTicks::Now(); | 
|  |  | 
|  | if (*last_event_count == 0) { | 
|  | // First call, just set the last values. | 
|  | *last_calculated = time; | 
|  | *last_event_count = event_count; | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | int64_t events_delta = event_count - *last_event_count; | 
|  | int64_t time_delta = (time - *last_calculated).InMicroseconds(); | 
|  | if (time_delta == 0) { | 
|  | NOTREACHED(); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | *last_calculated = time; | 
|  | *last_event_count = event_count; | 
|  |  | 
|  | int64_t events_delta_for_ms = | 
|  | events_delta * base::Time::kMicrosecondsPerSecond; | 
|  | // Round the result up by adding 1/2 (the second term resolves to 1/2 without | 
|  | // dropping down into floating point). | 
|  | return (events_delta_for_ms + time_delta / 2) / time_delta; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  | #endif  // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) | 
|  |  | 
|  | namespace base { | 
|  |  | 
|  | SystemMemoryInfoKB::SystemMemoryInfoKB() = default; | 
|  |  | 
|  | SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB& other) = | 
|  | default; | 
|  |  | 
|  | SystemMetrics::SystemMetrics() { | 
|  | committed_memory_ = 0; | 
|  | } | 
|  |  | 
|  | SystemMetrics SystemMetrics::Sample() { | 
|  | SystemMetrics system_metrics; | 
|  |  | 
|  | system_metrics.committed_memory_ = GetSystemCommitCharge(); | 
|  | #if defined(OS_LINUX) || defined(OS_ANDROID) | 
|  | GetSystemMemoryInfo(&system_metrics.memory_info_); | 
|  | GetVmStatInfo(&system_metrics.vmstat_info_); | 
|  | GetSystemDiskInfo(&system_metrics.disk_info_); | 
|  | #endif | 
|  | #if defined(OS_CHROMEOS) | 
|  | GetSwapInfo(&system_metrics.swap_info_); | 
|  | #endif | 
|  |  | 
|  | return system_metrics; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<Value> SystemMetrics::ToValue() const { | 
|  | std::unique_ptr<DictionaryValue> res(new DictionaryValue()); | 
|  |  | 
|  | res->SetInteger("committed_memory", static_cast<int>(committed_memory_)); | 
|  | #if defined(OS_LINUX) || defined(OS_ANDROID) | 
|  | std::unique_ptr<DictionaryValue> meminfo = memory_info_.ToValue(); | 
|  | std::unique_ptr<DictionaryValue> vmstat = vmstat_info_.ToValue(); | 
|  | meminfo->MergeDictionary(vmstat.get()); | 
|  | res->Set("meminfo", std::move(meminfo)); | 
|  | res->Set("diskinfo", disk_info_.ToValue()); | 
|  | #endif | 
|  | #if defined(OS_CHROMEOS) | 
|  | res->Set("swapinfo", swap_info_.ToValue()); | 
|  | #endif | 
|  |  | 
|  | return std::move(res); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<ProcessMetrics> ProcessMetrics::CreateCurrentProcessMetrics() { | 
|  | #if !defined(OS_MACOSX) || defined(OS_IOS) | 
|  | return CreateProcessMetrics(base::GetCurrentProcessHandle()); | 
|  | #else | 
|  | return CreateProcessMetrics(base::GetCurrentProcessHandle(), nullptr); | 
|  | #endif  // !defined(OS_MACOSX) || defined(OS_IOS) | 
|  | } | 
|  |  | 
|  | #if !defined(OS_FREEBSD) || !defined(OS_POSIX) | 
|  | double ProcessMetrics::GetPlatformIndependentCPUUsage() { | 
|  | TimeDelta cumulative_cpu = GetCumulativeCPUUsage(); | 
|  | 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 system_time_delta = cumulative_cpu - last_cumulative_cpu_; | 
|  | TimeDelta time_delta = time - last_cpu_time_; | 
|  | DCHECK(!time_delta.is_zero()); | 
|  | if (time_delta.is_zero()) | 
|  | return 0; | 
|  |  | 
|  | last_cumulative_cpu_ = cumulative_cpu; | 
|  | last_cpu_time_ = time; | 
|  |  | 
|  | return 100.0 * system_time_delta.InMicrosecondsF() / | 
|  | time_delta.InMicrosecondsF(); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_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  // defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX) | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | 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  // defined(OS_MACOSX) | 
|  | }  // namespace base |