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.
    240 BASE_EXPORT size_t GetPageSize();
    241 
    242 #if defined(OS_POSIX)
    243 // Returns the maximum number of file descriptors that can be open by a process
    244 // at once. If the number is unavailable, a conservative best guess is returned.
    245 BASE_EXPORT size_t GetMaxFds();
    246 
    247 // Sets the file descriptor soft limit to |max_descriptors| or the OS hard
    248 // limit, whichever is lower.
    249 BASE_EXPORT void SetFdLimit(unsigned int max_descriptors);
    250 #endif  // defined(OS_POSIX)
    251 
    252 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
    253     defined(OS_ANDROID)
    254 // Data about system-wide memory consumption. Values are in KB. Available on
    255 // Windows, Mac, Linux, Android and Chrome OS.
    256 //
    257 // Total/free memory are available on all platforms that implement
    258 // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms
    259 // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/
    260 // inactive_file/dirty/pswpin/pswpout/pgmajfault are available on
    261 // Linux/Android/Chrome OS. Shmem/slab/gem_objects/gem_size are Chrome OS only.
    262 struct BASE_EXPORT SystemMemoryInfoKB {
    263   SystemMemoryInfoKB();
    264 
    265   // Serializes the platform specific fields to value.
    266   scoped_ptr<Value> ToValue() const;
    267 
    268   int total;
    269   int free;
    270 
    271 #if !defined(OS_MACOSX)
    272   int swap_total;
    273   int swap_free;
    274 #endif
    275 
    276 #if defined(OS_ANDROID) || defined(OS_LINUX)
    277   int buffers;
    278   int cached;
    279   int active_anon;
    280   int inactive_anon;
    281   int active_file;
    282   int inactive_file;
    283   int dirty;
    284 
    285   // vmstats data.
    286   int pswpin;
    287   int pswpout;
    288   int pgmajfault;
    289 #endif  // defined(OS_ANDROID) || defined(OS_LINUX)
    290 
    291 #if defined(OS_CHROMEOS)
    292   int shmem;
    293   int slab;
    294   // Gem data will be -1 if not supported.
    295   int gem_objects;
    296   long long gem_size;
    297 #endif  // defined(OS_CHROMEOS)
    298 };
    299 
    300 // On Linux/Android/Chrome OS, system-wide memory consumption data is parsed
    301 // from /proc/meminfo and /proc/vmstat. On Windows/Mac, it is obtained using
    302 // system API calls.
    303 //
    304 // Fills in the provided |meminfo| structure. Returns true on success.
    305 // Exposed for memory debugging widget.
    306 BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
    307 
    308 #endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
    309         // defined(OS_ANDROID)
    310 
    311 #if defined(OS_LINUX) || defined(OS_ANDROID)
    312 // Parse the data found in /proc/<pid>/stat and return the sum of the
    313 // CPU-related ticks.  Returns -1 on parse error.
    314 // Exposed for testing.
    315 BASE_EXPORT int ParseProcStatCPU(const std::string& input);
    316 
    317 // Get the number of threads of |process| as available in /proc/<pid>/stat.
    318 // This should be used with care as no synchronization with running threads is
    319 // done. This is mostly useful to guarantee being single-threaded.
    320 // Returns 0 on failure.
    321 BASE_EXPORT int GetNumberOfThreads(ProcessHandle process);
    322 
    323 // /proc/self/exe refers to the current executable.
    324 BASE_EXPORT extern const char kProcSelfExe[];
    325 
    326 // Parses a string containing the contents of /proc/meminfo
    327 // returns true on success or false for a parsing error
    328 BASE_EXPORT bool ParseProcMeminfo(const std::string& input,
    329                                   SystemMemoryInfoKB* meminfo);
    330 
    331 // Parses a string containing the contents of /proc/vmstat
    332 // returns true on success or false for a parsing error
    333 BASE_EXPORT bool ParseProcVmstat(const std::string& input,
    334                                  SystemMemoryInfoKB* meminfo);
    335 
    336 // Data from /proc/diskstats about system-wide disk I/O.
    337 struct BASE_EXPORT SystemDiskInfo {
    338   SystemDiskInfo();
    339 
    340   // Serializes the platform specific fields to value.
    341   scoped_ptr<Value> ToValue() const;
    342 
    343   uint64_t reads;
    344   uint64_t reads_merged;
    345   uint64_t sectors_read;
    346   uint64_t read_time;
    347   uint64_t writes;
    348   uint64_t writes_merged;
    349   uint64_t sectors_written;
    350   uint64_t write_time;
    351   uint64_t io;
    352   uint64_t io_time;
    353   uint64_t weighted_io_time;
    354 };
    355 
    356 // Checks whether the candidate string is a valid disk name, [hsv]d[a-z]+
    357 // for a generic disk or mmcblk[0-9]+ for the MMC case.
    358 // Names of disk partitions (e.g. sda1) are not valid.
    359 BASE_EXPORT bool IsValidDiskName(const std::string& candidate);
    360 
    361 // Retrieves data from /proc/diskstats about system-wide disk I/O.
    362 // Fills in the provided |diskinfo| structure. Returns true on success.
    363 BASE_EXPORT bool GetSystemDiskInfo(SystemDiskInfo* diskinfo);
    364 #endif  // defined(OS_LINUX) || defined(OS_ANDROID)
    365 
    366 #if defined(OS_CHROMEOS)
    367 // Data from files in directory /sys/block/zram0 about ZRAM usage.
    368 struct BASE_EXPORT SwapInfo {
    369   SwapInfo()
    370       : num_reads(0),
    371         num_writes(0),
    372         compr_data_size(0),
    373         orig_data_size(0),
    374         mem_used_total(0) {
    375   }
    376 
    377   // Serializes the platform specific fields to value.
    378   scoped_ptr<Value> ToValue() const;
    379 
    380   uint64_t num_reads;
    381   uint64_t num_writes;
    382   uint64_t compr_data_size;
    383   uint64_t orig_data_size;
    384   uint64_t mem_used_total;
    385 };
    386 
    387 // In ChromeOS, reads files from /sys/block/zram0 that contain ZRAM usage data.
    388 // Fills in the provided |swap_data| structure.
    389 BASE_EXPORT void GetSwapInfo(SwapInfo* swap_info);
    390 #endif  // defined(OS_CHROMEOS)
    391 
    392 // Collects and holds performance metrics for system memory and disk.
    393 // Provides functionality to retrieve the data on various platforms and
    394 // to serialize the stored data.
    395 class SystemMetrics {
    396  public:
    397   SystemMetrics();
    398 
    399   static SystemMetrics Sample();
    400 
    401   // Serializes the system metrics to value.
    402   scoped_ptr<Value> ToValue() const;
    403 
    404  private:
    405   FRIEND_TEST_ALL_PREFIXES(SystemMetricsTest, SystemMetrics);
    406 
    407   size_t committed_memory_;
    408 #if defined(OS_LINUX) || defined(OS_ANDROID)
    409   SystemMemoryInfoKB memory_info_;
    410   SystemDiskInfo disk_info_;
    411 #endif
    412 #if defined(OS_CHROMEOS)
    413   SwapInfo swap_info_;
    414 #endif
    415 };
    416 
    417 }  // namespace base
    418 
    419 #endif  // BASE_PROCESS_PROCESS_METRICS_H_
    420