Home | History | Annotate | Download | only in process
      1 // Copyright (c) 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 // This file contains routines for gathering resource statistics for processes
      6 // running on the system.
      7 
      8 #ifndef BASE_PROCESS_PROCESS_METRICS_H_
      9 #define BASE_PROCESS_PROCESS_METRICS_H_
     10 
     11 #include <stddef.h>
     12 #include <stdint.h>
     13 
     14 #include <string>
     15 
     16 #include "base/base_export.h"
     17 #include "base/gtest_prod_util.h"
     18 #include "base/macros.h"
     19 #include "base/process/process_handle.h"
     20 #include "base/time/time.h"
     21 #include "base/values.h"
     22 #include "build/build_config.h"
     23 
     24 #if defined(OS_MACOSX)
     25 #include <mach/mach.h>
     26 #include "base/process/port_provider_mac.h"
     27 #endif
     28 
     29 namespace base {
     30 
     31 #if defined(OS_WIN)
     32 struct IoCounters : public IO_COUNTERS {
     33 };
     34 #elif defined(OS_POSIX)
     35 struct IoCounters {
     36   uint64_t ReadOperationCount;
     37   uint64_t WriteOperationCount;
     38   uint64_t OtherOperationCount;
     39   uint64_t ReadTransferCount;
     40   uint64_t WriteTransferCount;
     41   uint64_t OtherTransferCount;
     42 };
     43 #endif
     44 
     45 // Working Set (resident) memory usage broken down by
     46 //
     47 // On Windows:
     48 // priv (private): These pages (kbytes) cannot be shared with any other process.
     49 // shareable:      These pages (kbytes) can be shared with other processes under
     50 //                 the right circumstances.
     51 // shared :        These pages (kbytes) are currently shared with at least one
     52 //                 other process.
     53 //
     54 // On Linux:
     55 // priv:           Pages mapped only by this process.
     56 // shared:         PSS or 0 if the kernel doesn't support this.
     57 // shareable:      0
     58 
     59 // On ChromeOS:
     60 // priv:           Pages mapped only by this process.
     61 // shared:         PSS or 0 if the kernel doesn't support this.
     62 // shareable:      0
     63 // swapped         Pages swapped out to zram.
     64 //
     65 // On OS X: TODO(thakis): Revise.
     66 // priv:           Memory.
     67 // shared:         0
     68 // shareable:      0
     69 //
     70 struct WorkingSetKBytes {
     71   WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
     72   size_t priv;
     73   size_t shareable;
     74   size_t shared;
     75 #if defined(OS_CHROMEOS)
     76   size_t swapped;
     77 #endif
     78 };
     79 
     80 // Committed (resident + paged) memory usage broken down by
     81 // private: These pages cannot be shared with any other process.
     82 // mapped:  These pages are mapped into the view of a section (backed by
     83 //          pagefile.sys)
     84 // image:   These pages are mapped into the view of an image section (backed by
     85 //          file system)
     86 struct CommittedKBytes {
     87   CommittedKBytes() : priv(0), mapped(0), image(0) {}
     88   size_t priv;
     89   size_t mapped;
     90   size_t image;
     91 };
     92 
     93 // Convert a POSIX timeval to microseconds.
     94 BASE_EXPORT int64_t TimeValToMicroseconds(const struct timeval& tv);
     95 
     96 // Provides performance metrics for a specified process (CPU usage, memory and
     97 // IO counters). Use CreateCurrentProcessMetrics() to get an instance for the
     98 // current process, or CreateProcessMetrics() to get an instance for an
     99 // arbitrary process. Then, access the information with the different get
    100 // methods.
    101 class BASE_EXPORT ProcessMetrics {
    102  public:
    103   ~ProcessMetrics();
    104 
    105   // Creates a ProcessMetrics for the specified process.
    106   // The caller owns the returned object.
    107 #if !defined(OS_MACOSX) || defined(OS_IOS)
    108   static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
    109 #else
    110 
    111   // The port provider needs to outlive the ProcessMetrics object returned by
    112   // this function. If NULL is passed as provider, the returned object
    113   // only returns valid metrics if |process| is the current process.
    114   static ProcessMetrics* CreateProcessMetrics(ProcessHandle process,
    115                                               PortProvider* port_provider);
    116 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
    117 
    118   // Creates a ProcessMetrics for the current process. This a cross-platform
    119   // convenience wrapper for CreateProcessMetrics().
    120   // The caller owns the returned object.
    121   static ProcessMetrics* CreateCurrentProcessMetrics();
    122 
    123   // Returns the current space allocated for the pagefile, in bytes (these pages
    124   // may or may not be in memory).  On Linux, this returns the total virtual
    125   // memory size.
    126   size_t GetPagefileUsage() const;
    127   // Returns the peak space allocated for the pagefile, in bytes.
    128   size_t GetPeakPagefileUsage() const;
    129   // Returns the current working set size, in bytes.  On Linux, this returns
    130   // the resident set size.
    131   size_t GetWorkingSetSize() const;
    132   // Returns the peak working set size, in bytes.
    133   size_t GetPeakWorkingSetSize() const;
    134   // Returns private and sharedusage, in bytes. Private bytes is the amount of
    135   // memory currently allocated to a process that cannot be shared. Returns
    136   // false on platform specific error conditions.  Note: |private_bytes|
    137   // returns 0 on unsupported OSes: prior to XP SP2.
    138   bool GetMemoryBytes(size_t* private_bytes,
    139                       size_t* shared_bytes);
    140   // Fills a CommittedKBytes with both resident and paged
    141   // memory usage as per definition of CommittedBytes.
    142   void GetCommittedKBytes(CommittedKBytes* usage) const;
    143   // Fills a WorkingSetKBytes containing resident private and shared memory
    144   // usage in bytes, as per definition of WorkingSetBytes. Note that this
    145   // function is somewhat expensive on Windows (a few ms per process).
    146   bool GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const;
    147 
    148 #if defined(OS_MACOSX)
    149   // Fills both CommitedKBytes and WorkingSetKBytes in a single operation. This
    150   // is more efficient on Mac OS X, as the two can be retrieved with a single
    151   // system call.
    152   bool GetCommittedAndWorkingSetKBytes(CommittedKBytes* usage,
    153                                        WorkingSetKBytes* ws_usage) const;
    154 #endif
    155 
    156   // Returns the CPU usage in percent since the last time this method or
    157   // GetPlatformIndependentCPUUsage() was called. The first time this method
    158   // is called it returns 0 and will return the actual CPU info on subsequent
    159   // calls. On Windows, the CPU usage value is for all CPUs. So if you have
    160   // 2 CPUs and your process is using all the cycles of 1 CPU and not the other
    161   // CPU, this method returns 50.
    162   double GetCPUUsage();
    163 
    164   // Returns the number of average idle cpu wakeups per second since the last
    165   // call.
    166   int GetIdleWakeupsPerSecond();
    167 
    168   // Same as GetCPUUsage(), but will return consistent values on all platforms
    169   // (cancelling the Windows exception mentioned above) by returning a value in
    170   // the range of 0 to (100 * numCPUCores) everywhere.
    171   double GetPlatformIndependentCPUUsage();
    172 
    173   // Retrieves accounting information for all I/O operations performed by the
    174   // process.
    175   // If IO information is retrieved successfully, the function returns true
    176   // and fills in the IO_COUNTERS passed in. The function returns false
    177   // otherwise.
    178   bool GetIOCounters(IoCounters* io_counters) const;
    179 
    180 #if defined(OS_LINUX)
    181   // Returns the number of file descriptors currently open by the process, or
    182   // -1 on error.
    183   int GetOpenFdCount() const;
    184 #endif  // defined(OS_LINUX)
    185 
    186  private:
    187 #if !defined(OS_MACOSX) || defined(OS_IOS)
    188   explicit ProcessMetrics(ProcessHandle process);
    189 #else
    190   ProcessMetrics(ProcessHandle process, PortProvider* port_provider);
    191 #endif  // !defined(OS_MACOSX) || defined(OS_IOS)
    192 
    193 #if defined(OS_LINUX) || defined(OS_ANDROID)
    194   bool GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) const;
    195 #endif
    196 
    197 #if defined(OS_CHROMEOS)
    198   bool GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) const;
    199 #endif
    200 
    201 #if defined(OS_MACOSX) || defined(OS_LINUX)
    202   int CalculateIdleWakeupsPerSecond(uint64_t absolute_idle_wakeups);
    203 #endif
    204 
    205   ProcessHandle process_;
    206 
    207   int processor_count_;
    208 
    209   // Used to store the previous times and CPU usage counts so we can
    210   // compute the CPU usage between calls.
    211   TimeTicks last_cpu_time_;
    212   int64_t last_system_time_;
    213 
    214 #if defined(OS_MACOSX) || defined(OS_LINUX)
    215   // Same thing for idle wakeups.
    216   TimeTicks last_idle_wakeups_time_;
    217   uint64_t last_absolute_idle_wakeups_;
    218 #endif
    219 
    220 #if !defined(OS_IOS)
    221 #if defined(OS_MACOSX)
    222   // Queries the port provider if it's set.
    223   mach_port_t TaskForPid(ProcessHandle process) const;
    224 
    225   PortProvider* port_provider_;
    226 #elif defined(OS_POSIX)
    227   // Jiffie count at the last_cpu_time_ we updated.
    228   int last_cpu_;
    229 #endif  // defined(OS_POSIX)
    230 #endif  // !defined(OS_IOS)
    231 
    232   DISALLOW_COPY_AND_ASSIGN(ProcessMetrics);
    233 };
    234 
    235 // Returns the memory committed by the system in KBytes.
    236 // Returns 0 if it can't compute the commit charge.
    237 BASE_EXPORT size_t GetSystemCommitCharge();
    238 
    239 // Returns the number of bytes in a memory page. Do not use this to compute
    240 // the number of pages in a block of memory for calling mincore(). On some
    241 // platforms, e.g. iOS, mincore() uses a different page size from what is
    242 // returned by GetPageSize().
    243 BASE_EXPORT size_t GetPageSize();
    244 
    245 #if defined(OS_POSIX)
    246 // Returns the maximum number of file descriptors that can be open by a process
    247 // at once. If the number is unavailable, a conservative best guess is returned.
    248 BASE_EXPORT size_t GetMaxFds();
    249 
    250 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
    251 // limit, whichever is lower.
    252 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
    253 #endif  // defined(OS_POSIX)
    254 
    255 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    256     defined(OS_ANDROID)
    257 // Data about system-wide memory consumption. Values are in KB. Available on
    258 // Windows, Mac, Linux, Android and Chrome OS.
    259 //
    260 // Total/free memory are available on all platforms that implement
    261 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
    262 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
    263 // inactive_file/dirty/pswpin/pswpout/pgmajfault are available on
    264 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only.
    265 struct BASE_EXPORT SystemMemoryInfoKB {
    266   SystemMemoryInfoKB();
    267   SystemMemoryInfoKB(const SystemMemoryInfoKB& other);
    268 
    269   // Serializes the platform specific fields to value.
    270   std::unique_ptr<Value> ToValue() const;
    271 
    272   int total;
    273   int free;
    274 
    275 #if defined(OS_LINUX)
    276   // This provides an estimate of available memory as described here:
    277   // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
    278   // NOTE: this is ONLY valid in kernels 3.14 and up.  Its value will always
    279   // be 0 in earlier kernel versions.
    280   int available;
    281 #endif
    282 
    283 #if !defined(OS_MACOSX)
    284   int swap_total;
    285   int swap_free;
    286 #endif
    287 
    288 #if defined(OS_ANDROID) || defined(OS_LINUX)
    289   int buffers;
    290   int cached;
    291   int active_anon;
    292   int inactive_anon;
    293   int active_file;
    294   int inactive_file;
    295   int dirty;
    296 
    297   // vmstats data.
    298   int pswpin;
    299   int pswpout;
    300   int pgmajfault;
    301 #endif  // defined(OS_ANDROID) || defined(OS_LINUX)
    302 
    303 #if defined(OS_CHROMEOS)
    304   int shmem;
    305   int slab;
    306   // Gem data will be -1 if not supported.
    307   int gem_objects;
    308   long long gem_size;
    309 #endif  // defined(OS_CHROMEOS)
    310 };
    311 
    312 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
    313 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
    314 // system API calls.
    315 //
    316 // Fills in the provided |meminfo| structure. Returns true on success.
    317 // Exposed for memory debugging widget.
    318 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
    319 
    320 #endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
    321         // defined(OS_ANDROID)
    322 
    323 #if defined(OS_LINUX) || defined(OS_ANDROID)
    324 // Parse the data found in /proc/<pid>/stat and return the sum of the
    325 // CPU-related ticks.  Returns -1 on parse error.
    326 // Exposed for testing.
    327 BASE_EXPORT int ParseProcStatCPU(const std::string& input);
    328 
    329 // Get the number of threads of |process| as available in /proc/<pid>/stat.
    330 // This should be used with care as no synchronization with running threads is
    331 // done. This is mostly useful to guarantee being single-threaded.
    332 // Returns 0 on failure.
    333 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
    334 
    335 // /proc/self/exe refers to the current executable.
    336 BASE_EXPORT extern const char kProcSelfExe[];
    337 
    338 // Parses a string containing the contents of /proc/meminfo
    339 // returns true on success or false for a parsing error
    340 BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
    341                                   SystemMemoryInfoKB* meminfo);
    342 
    343 // Parses a string containing the contents of /proc/vmstat
    344 // returns true on success or false for a parsing error
    345 BASE_EXPORT bool ParseProcVmstat(const std::string& input,
    346                                  SystemMemoryInfoKB* meminfo);
    347 
    348 // Data from /proc/diskstats about system-wide disk I/O.
    349 struct BASE_EXPORT SystemDiskInfo {
    350   SystemDiskInfo();
    351   SystemDiskInfo(const SystemDiskInfo& other);
    352 
    353   // Serializes the platform specific fields to value.
    354   std::unique_ptr<Value> ToValue() const;
    355 
    356   uint64_t reads;
    357   uint64_t reads_merged;
    358   uint64_t sectors_read;
    359   uint64_t read_time;
    360   uint64_t writes;
    361   uint64_t writes_merged;
    362   uint64_t sectors_written;
    363   uint64_t write_time;
    364   uint64_t io;
    365   uint64_t io_time;
    366   uint64_t weighted_io_time;
    367 };
    368 
    369 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+
    370 // for a generic disk or mmcblk[0-9]+ for the MMC case.
    371 // Names of disk partitions (e.g. sda1) are not valid.
    372 BASE_EXPORT bool IsValidDiskName(const std::string& candidate);
    373 
    374 // Retrieves data from /proc/diskstats about system-wide disk I/O.
    375 // Fills in the provided |diskinfo| structure. Returns true on success.
    376 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
    377 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
    378 
    379 #if defined(OS_CHROMEOS)
    380 // Data from files in directory /sys/block/zram0 about ZRAM usage.
    381 struct BASE_EXPORT SwapInfo {
    382   SwapInfo()
    383       : num_reads(0),
    384         num_writes(0),
    385         compr_data_size(0),
    386         orig_data_size(0),
    387         mem_used_total(0) {
    388   }
    389 
    390   // Serializes the platform specific fields to value.
    391   std::unique_ptr<Value> ToValue() const;
    392 
    393   uint64_t num_reads;
    394   uint64_t num_writes;
    395   uint64_t compr_data_size;
    396   uint64_t orig_data_size;
    397   uint64_t mem_used_total;
    398 };
    399 
    400 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data.
    401 // Fills in the provided |swap_data| structure.
    402 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info);
    403 #endif  // defined(OS_CHROMEOS)
    404 
    405 // Collects and holds performance metrics for system memory and disk.
    406 // Provides functionality to retrieve the data on various platforms and
    407 // to serialize the stored data.
    408 class SystemMetrics {
    409  public:
    410   SystemMetrics();
    411 
    412   static SystemMetrics Sample();
    413 
    414   // Serializes the system metrics to value.
    415   std::unique_ptr<Value> ToValue() const;
    416 
    417  private:
    418   FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics);
    419 
    420   size_t committed_memory_;
    421 #if defined(OS_LINUX) || defined(OS_ANDROID)
    422   SystemMemoryInfoKB memory_info_;
    423   SystemDiskInfo disk_info_;
    424 #endif
    425 #if defined(OS_CHROMEOS)
    426   SwapInfo swap_info_;
    427 #endif
    428 };
    429 
    430 }  // namespace base
    431 
    432 #endif  // BASE_PROCESS_PROCESS_METRICS_H_
    433