190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/process/process_metrics.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/param.h>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <sys/sysctl.h>
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace base {
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return new ProcessMetrics(process);
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t ProcessMetrics::GetPagefileUsage() const {
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct kinfo_proc info;
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t length;
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_,
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                sizeof(struct kinfo_proc), 0 };
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0)
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return -1;
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mib[5] = (length / sizeof(struct kinfo_proc));
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return -1;
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return (info.p_vm_tsize + info.p_vm_dsize + info.p_vm_ssize);
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t ProcessMetrics::GetPeakPagefileUsage() const {
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 0;
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t ProcessMetrics::GetWorkingSetSize() const {
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct kinfo_proc info;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t length;
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_,
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                sizeof(struct kinfo_proc), 0 };
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0)
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return -1;
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mib[5] = (length / sizeof(struct kinfo_proc));
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return -1;
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return info.p_vm_rssize * getpagesize();
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t ProcessMetrics::GetPeakWorkingSetSize() const {
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return 0;
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    size_t* shared_bytes) {
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WorkingSetKBytes ws_usage;
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!GetWorkingSetKBytes(&ws_usage))
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (private_bytes)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *private_bytes = ws_usage.priv << 10;
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (shared_bytes)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *shared_bytes = ws_usage.shared * 1024;
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(bapt): be sure we can't be precise
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t priv = GetWorkingSetSize();
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!priv)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ws_usage->priv = priv / 1024;
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ws_usage->shareable = 0;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ws_usage->shared = 0;
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static int GetProcessCPU(pid_t pid) {
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct kinfo_proc info;
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t length;
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid,
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                sizeof(struct kinfo_proc), 0 };
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), NULL, &length, NULL, 0) < 0)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return -1;
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mib[5] = (length / sizeof(struct kinfo_proc));
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return info.p_pctcpu;
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)double ProcessMetrics::GetCPUUsage() {
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct timeval now;
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int retval = gettimeofday(&now, NULL);
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (retval)
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 time = TimeValToMicroseconds(now);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (last_time_ == 0) {
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // First call, just set the last values.
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    last_time_ = time;
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    last_cpu_ = GetProcessCPU(process_);
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 time_delta = time - last_time_;
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_NE(time_delta, 0);
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (time_delta == 0)
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int cpu = GetProcessCPU(process_);
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  last_time_ = time;
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  last_cpu_ = cpu;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  double percentage = static_cast<double>((cpu * 100.0) / FSCALE);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return percentage;
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ProcessMetrics::ProcessMetrics(ProcessHandle process)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : process_(process),
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_time_(0),
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_system_time_(0),
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_cpu_(0) {
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  processor_count_ = base::SysInfo::NumberOfProcessors();
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)size_t GetSystemCommitCharge() {
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int mib[] = { CTL_VM, VM_METER };
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int pagesize;
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct vmtotal vmtotal;
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  unsigned long mem_total, mem_free, mem_inactive;
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t len = sizeof(vmtotal);
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (sysctl(mib, arraysize(mib), &vmtotal, &len, NULL, 0) < 0)
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return 0;
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mem_total = vmtotal.t_vm;
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mem_free = vmtotal.t_free;
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mem_inactive = vmtotal.t_vm - vmtotal.t_avm;
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pagesize = getpagesize();
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return mem_total - (mem_free*pagesize) - (mem_inactive*pagesize);
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace base
169