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