Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_MEMORY_DETAILS_H_
      6 #define CHROME_BROWSER_MEMORY_DETAILS_H_
      7 
      8 #include <map>
      9 #include <vector>
     10 
     11 #include "base/memory/ref_counted.h"
     12 #include "base/process/process_handle.h"
     13 #include "base/process/process_metrics.h"
     14 #include "base/strings/string16.h"
     15 #include "base/time/time.h"
     16 #include "chrome/browser/site_details.h"
     17 #include "content/public/common/process_type.h"
     18 
     19 // We collect data about each browser process.  A browser may
     20 // have multiple processes (of course!).  Even IE has multiple
     21 // processes these days.
     22 struct ProcessMemoryInformation {
     23   // NOTE: Do not remove or reorder the elements in this enum, and only add new
     24   // items at the end. We depend on these specific values in a histogram.
     25   enum RendererProcessType {
     26     RENDERER_UNKNOWN = 0,
     27     RENDERER_NORMAL,
     28     RENDERER_CHROME,        // WebUI (chrome:// URL)
     29     RENDERER_EXTENSION,     // chrome-extension://
     30     RENDERER_DEVTOOLS,      // Web inspector
     31     RENDERER_INTERSTITIAL,  // malware/phishing interstitial
     32     RENDERER_BACKGROUND_APP // hosted app background page
     33   };
     34 
     35   static std::string GetRendererTypeNameInEnglish(RendererProcessType type);
     36   static std::string GetFullTypeNameInEnglish(
     37       int process_type,
     38       RendererProcessType rtype);
     39 
     40   ProcessMemoryInformation();
     41   ~ProcessMemoryInformation();
     42 
     43   // Default ordering is by private memory consumption.
     44   bool operator<(const ProcessMemoryInformation& rhs) const;
     45 
     46   // The process id.
     47   base::ProcessId pid;
     48   // The working set information.
     49   base::WorkingSetKBytes working_set;
     50   // The committed bytes.
     51   base::CommittedKBytes committed;
     52   // The process version
     53   base::string16 version;
     54   // The process product name.
     55   base::string16 product_name;
     56   // The number of processes which this memory represents.
     57   int num_processes;
     58   // A process is a diagnostics process if it is rendering about:memory.
     59   // Mark this specially so that it can avoid counting it in its own
     60   // results.
     61   bool is_diagnostics;
     62   // If this is a child process of Chrome, what type (i.e. plugin) it is.
     63   int process_type;
     64   // If this is a renderer process, what type it is.
     65   RendererProcessType renderer_type;
     66   // A collection of titles used, i.e. for a tab it'll show all the page titles.
     67   std::vector<base::string16> titles;
     68 };
     69 
     70 typedef std::vector<ProcessMemoryInformation> ProcessMemoryInformationList;
     71 
     72 // Browser Process Information.
     73 struct ProcessData {
     74   ProcessData();
     75   ProcessData(const ProcessData& rhs);
     76   ~ProcessData();
     77   ProcessData& operator=(const ProcessData& rhs);
     78 
     79   base::string16 name;
     80   base::string16 process_name;
     81   ProcessMemoryInformationList processes;
     82 
     83   // Track site data for predicting process counts with out-of-process iframes.
     84   // See site_details.h.
     85   BrowserContextSiteDataMap site_data;
     86 };
     87 
     88 // MemoryGrowthTracker tracks latest metrics about record time and memory usage
     89 // at that time per process.
     90 class MemoryGrowthTracker {
     91  public:
     92   MemoryGrowthTracker();
     93   ~MemoryGrowthTracker();
     94 
     95   // If 30 minutes have passed since last UMA record, UpdateSample() computes
     96   // a difference between current memory usage |sample| of process |pid| and
     97   // stored memory usage at the time of last UMA record. Then, it updates the
     98   // stored memory usage to |sample|, stores the difference in |diff| and
     99   // returns true.
    100   // If no memory usage of |pid| has not been recorded so far or 30 minutes
    101   // have not passed since last record, it just returns false.
    102   // |sample| is memory usage in kB.
    103   bool UpdateSample(base::ProcessId pid, int sample, int* diff);
    104 
    105  private:
    106   // Latest metrics about record time and memory usage at that time per process.
    107   // The second values of |memory_sizes_| are in kB.
    108   std::map<base::ProcessId, base::TimeTicks> times_;
    109   std::map<base::ProcessId, int> memory_sizes_;
    110 
    111   DISALLOW_COPY_AND_ASSIGN(MemoryGrowthTracker);
    112 };
    113 
    114 #if defined(OS_MACOSX)
    115 class ProcessInfoSnapshot;
    116 #endif
    117 
    118 // MemoryDetails fetches memory details about current running browsers.
    119 // Because this data can only be fetched asynchronously, callers use
    120 // this class via a callback.
    121 //
    122 // Example usage:
    123 //
    124 //    class MyMemoryDetailConsumer : public MemoryDetails {
    125 //
    126 //      MyMemoryDetailConsumer() {
    127 //        // Anything but |StartFetch()|.
    128 //      }
    129 //
    130 //      // (Or just call |StartFetch()| explicitly if there's nothing else to
    131 //      // do.)
    132 //      void StartDoingStuff() {
    133 //        StartFetch();  // Starts fetching details.
    134 //        // Etc.
    135 //      }
    136 //
    137 //      // Your other class stuff here
    138 //
    139 //      virtual void OnDetailsAvailable() {
    140 //        // do work with memory info here
    141 //      }
    142 //    }
    143 class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> {
    144  public:
    145   enum UserMetricsMode {
    146     UPDATE_USER_METRICS,  // Update UMA memory histograms with results.
    147     SKIP_USER_METRICS
    148   };
    149 
    150   // Constructor.
    151   MemoryDetails();
    152 
    153   // Access to the process detail information.  This data is only available
    154   // after OnDetailsAvailable() has been called.
    155   const std::vector<ProcessData>& processes() { return process_data_; }
    156 
    157   // Initiate updating the current memory details.  These are fetched
    158   // asynchronously because data must be collected from multiple threads.
    159   // Updates UMA memory histograms if |mode| is UPDATE_USER_METRICS.
    160   // OnDetailsAvailable will be called when this process is complete.
    161   void StartFetch(UserMetricsMode user_metrics_mode);
    162 
    163   virtual void OnDetailsAvailable() = 0;
    164 
    165   // Returns a string summarizing memory usage of the Chrome browser process
    166   // and all sub-processes, suitable for logging.
    167   std::string ToLogString();
    168 
    169  protected:
    170   friend class base::RefCountedThreadSafe<MemoryDetails>;
    171 
    172   virtual ~MemoryDetails();
    173 
    174   // Set MemoryGrowthTracker into MemoryDetails.
    175   void SetMemoryGrowthTracker(MemoryGrowthTracker* memory_growth_tracker);
    176 
    177  private:
    178   // Collect child process information on the IO thread.  This is needed because
    179   // information about some child process types (i.e. plugins) can only be taken
    180   // on that thread.  The data will be used by about:memory.  When finished,
    181   // invokes back to the file thread to run the rest of the about:memory
    182   // functionality.
    183   void CollectChildInfoOnIOThread();
    184 
    185   // Collect current process information from the OS and store it
    186   // for processing.  If data has already been collected, clears old
    187   // data and re-collects the data.
    188   // Note - this function enumerates memory details from many processes
    189   // and is fairly expensive to run, hence it's run on the file thread.
    190   // The parameter holds information about processes from the IO thread.
    191   void CollectProcessData(const std::vector<ProcessMemoryInformation>&);
    192 
    193 #if defined(OS_MACOSX)
    194   // A helper for |CollectProcessData()|, collecting data on the Chrome/Chromium
    195   // process with PID |pid|. The collected data is added to the state of the
    196   // object (in |process_data_|).
    197   void CollectProcessDataChrome(
    198       const std::vector<ProcessMemoryInformation>& child_info,
    199       base::ProcessId pid,
    200       const ProcessInfoSnapshot& process_info);
    201 #endif
    202 
    203   // Collect child process information on the UI thread.  Information about
    204   // renderer processes is only available there.
    205   void CollectChildInfoOnUIThread();
    206 
    207   // Updates the global histograms for tracking memory usage.
    208   void UpdateHistograms();
    209 
    210 #if defined(OS_CHROMEOS)
    211   void UpdateSwapHistograms();
    212 #endif
    213 
    214   // Returns a pointer to the ProcessData structure for Chrome.
    215   ProcessData* ChromeBrowser();
    216 
    217   std::vector<ProcessData> process_data_;
    218 
    219   UserMetricsMode user_metrics_mode_;
    220 
    221   // A pointer to MemoryGrowthTracker which is contained in a longer-lived
    222   // owner of MemoryDetails, for example, ChromeMetricsServiceClient.
    223   // The pointer is NULL by default and set by SetMemoryGrowthTracker().
    224   // If it is NULL, nothing is tracked.
    225   MemoryGrowthTracker* memory_growth_tracker_;
    226 
    227 #if defined(OS_CHROMEOS)
    228   base::SwapInfo swap_info_;
    229 #endif
    230 
    231   DISALLOW_COPY_AND_ASSIGN(MemoryDetails);
    232 };
    233 
    234 #endif  // CHROME_BROWSER_MEMORY_DETAILS_H_
    235