Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: chrome/browser/memory_details_win.cc

Issue 159777: Add about:memory support for Linux.... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/memory_details.h" 5 #include "chrome/browser/memory_details.h"
6 #include <psapi.h> 6 #include <psapi.h>
7 7
8 #include "app/l10n_util.h"
8 #include "base/file_version_info.h" 9 #include "base/file_version_info.h"
9 #include "base/string_util.h" 10 #include "base/string_util.h"
10 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/chrome_thread.h" 12 #include "chrome/browser/chrome_thread.h"
12 #include "chrome/browser/renderer_host/render_process_host.h" 13 #include "chrome/browser/renderer_host/render_process_host.h"
13 #include "chrome/browser/tab_contents/navigation_entry.h" 14 #include "chrome/browser/tab_contents/navigation_entry.h"
14 #include "chrome/browser/tab_contents/tab_contents.h" 15 #include "chrome/browser/tab_contents/tab_contents.h"
15 #include "chrome/common/child_process_host.h" 16 #include "chrome/common/child_process_host.h"
16 #include "chrome/common/url_constants.h" 17 #include "chrome/common/url_constants.h"
18 #include "grit/chromium_strings.h"
17 19
18 class RenderViewHostDelegate; 20 // Known browsers which we collect details for.
21 enum {
22 CHROME_BROWSER = 0,
23 IE_BROWSER,
24 FIREFOX_BROWSER,
25 OPERA_BROWSER,
26 SAFARI_BROWSER,
27 IE_64BIT_BROWSER,
28 KONQUEROR_BROWSER,
29 MAX_BROWSERS
30 } BrowserProcess;
19 31
20 // Template of static data we use for finding browser process information. 32 // Template of static data we use for finding browser process information.
21 // These entries must match the ordering for MemoryDetails::BrowserProcess. 33 // These entries must match the ordering for MemoryDetails::BrowserProcess.
22 static ProcessData 34 static ProcessData g_process_template[MAX_BROWSERS];
23 g_process_template[MemoryDetails::MAX_BROWSERS] = { 35
24 { L"Chromium", L"chrome.exe", }, 36 MemoryDetails::MemoryDetails()
37 : ui_loop_(NULL) {
38 static const std::wstring google_browser_name =
39 l10n_util::GetString(IDS_PRODUCT_NAME);
40 ProcessData g_process_template[MAX_BROWSERS] = {
41 { google_browser_name.c_str(), L"chrome.exe", },
25 { L"IE", L"iexplore.exe", }, 42 { L"IE", L"iexplore.exe", },
26 { L"Firefox", L"firefox.exe", }, 43 { L"Firefox", L"firefox.exe", },
27 { L"Opera", L"opera.exe", }, 44 { L"Opera", L"opera.exe", },
28 { L"Safari", L"safari.exe", }, 45 { L"Safari", L"safari.exe", },
29 { L"IE (64bit)", L"iexplore.exe", }, 46 { L"IE (64bit)", L"iexplore.exe", },
30 { L"Konqueror", L"konqueror.exe", }, 47 { L"Konqueror", L"konqueror.exe", },
31 }; 48 };
32 49
33
34 // About threading:
35 //
36 // This operation will hit no fewer than 3 threads.
37 //
38 // The ChildProcessInfo::Iterator can only be accessed from the IO thread.
39 //
40 // The RenderProcessHostIterator can only be accessed from the UI thread.
41 //
42 // This operation can take 30-100ms to complete. We never want to have
43 // one task run for that long on the UI or IO threads. So, we run the
44 // expensive parts of this operation over on the file thread.
45 //
46
47 MemoryDetails::MemoryDetails()
48 : ui_loop_(NULL) {
49 for (int index = 0; index < arraysize(g_process_template); ++index) { 50 for (int index = 0; index < arraysize(g_process_template); ++index) {
50 process_data_[index].name = g_process_template[index].name; 51 ProcessData process;
51 process_data_[index].process_name = g_process_template[index].process_name; 52 process.name = g_process_template[index].name;
53 process.process_name = g_process_template[index].process_name;
54 process_data_.push_back(process);
52 } 55 }
53 } 56 }
54 57
55 void MemoryDetails::StartFetch() { 58 ProcessData* MemoryDetails::ChromeBrowser() {
56 ui_loop_ = MessageLoop::current(); 59 return &process_data_[CHROME_BROWSER];
57
58 DCHECK(ui_loop_ != g_browser_process->io_thread()->message_loop());
59 DCHECK(ui_loop_ != g_browser_process->file_thread()->message_loop());
60
61 // In order to process this request, we need to use the plugin information.
62 // However, plugin process information is only available from the IO thread.
63 g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
64 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnIOThread));
65 }
66
67 void MemoryDetails::CollectChildInfoOnIOThread() {
68 DCHECK(MessageLoop::current() ==
69 ChromeThread::GetMessageLoop(ChromeThread::IO));
70
71 std::vector<ProcessMemoryInformation> child_info;
72
73 // Collect the list of child processes.
74 for (ChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
75 ProcessMemoryInformation info;
76 info.pid = iter->GetProcessId();
77 if (!info.pid)
78 continue;
79
80 info.type = iter->type();
81 info.titles.push_back(iter->name());
82 child_info.push_back(info);
83 }
84
85 // Now go do expensive memory lookups from the file thread.
86 ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE,
87 NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info));
88 } 60 }
89 61
90 void MemoryDetails::CollectProcessData( 62 void MemoryDetails::CollectProcessData(
91 std::vector<ProcessMemoryInformation> child_info) { 63 std::vector<ProcessMemoryInformation> child_info) {
92 DCHECK(MessageLoop::current() == 64 DCHECK(MessageLoop::current() ==
93 ChromeThread::GetMessageLoop(ChromeThread::FILE)); 65 ChromeThread::GetMessageLoop(ChromeThread::FILE));
94 66
95 // Clear old data. 67 // Clear old data.
96 for (int index = 0; index < arraysize(g_process_template); index++) 68 for (int index = 0; index < arraysize(g_process_template); index++)
97 process_data_[index].processes.clear(); 69 process_data_[index].processes.clear();
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 // Add the process info to our list. 146 // Add the process info to our list.
175 process_data_[index2].processes.push_back(info); 147 process_data_[index2].processes.push_back(info);
176 break; 148 break;
177 } 149 }
178 } while (::Process32Next(snapshot, &process_entry)); 150 } while (::Process32Next(snapshot, &process_entry));
179 151
180 // Finally return to the browser thread. 152 // Finally return to the browser thread.
181 ui_loop_->PostTask(FROM_HERE, 153 ui_loop_->PostTask(FROM_HERE,
182 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread)); 154 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
183 } 155 }
184
185 void MemoryDetails::CollectChildInfoOnUIThread() {
186 DCHECK(MessageLoop::current() == ui_loop_);
187
188 // Get more information about the process.
189 for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
190 index++) {
191 // Check if it's a renderer, if so get the list of page titles in it and
192 // check if it's a diagnostics-related process. We skip all diagnostics
193 // pages (e.g. "about:xxx" URLs). Iterate the RenderProcessHosts to find
194 // the tab contents.
195 RenderProcessHost::iterator renderer_iter;
196 for (renderer_iter = RenderProcessHost::begin(); renderer_iter !=
197 RenderProcessHost::end(); ++renderer_iter) {
198 DCHECK(renderer_iter->second);
199 ProcessMemoryInformation& process =
200 process_data_[CHROME_BROWSER].processes[index];
201 if (process.pid != renderer_iter->second->process().pid())
202 continue;
203 process.type = ChildProcessInfo::RENDER_PROCESS;
204 // The RenderProcessHost may host multiple TabContents. Any
205 // of them which contain diagnostics information make the whole
206 // process be considered a diagnostics process.
207 //
208 // NOTE: This is a bit dangerous. We know that for now, listeners
209 // are always RenderWidgetHosts. But in theory, they don't
210 // have to be.
211 RenderProcessHost::listeners_iterator iter;
212 for (iter = renderer_iter->second->listeners_begin();
213 iter != renderer_iter->second->listeners_end(); ++iter) {
214 RenderWidgetHost* widget =
215 static_cast<RenderWidgetHost*>(iter->second);
216 DCHECK(widget);
217 if (!widget || !widget->IsRenderView())
218 continue;
219
220 RenderViewHost* host = static_cast<RenderViewHost*>(widget);
221 TabContents* contents = NULL;
222 if (host->delegate())
223 contents = host->delegate()->GetAsTabContents();
224 if (!contents)
225 continue;
226 std::wstring title = UTF16ToWideHack(contents->GetTitle());
227 if (!title.length())
228 title = L"Untitled";
229 process.titles.push_back(title);
230
231 // We need to check the pending entry as well as the display_url to
232 // see if it's an about:memory URL (we don't want to count these in the
233 // total memory usage of the browser).
234 //
235 // When we reach here, about:memory will be the pending entry since we
236 // haven't responded with any data such that it would be committed. If
237 // you have another about:memory tab open (which would be committed),
238 // we don't want to count it either, so we also check the last committed
239 // entry.
240 //
241 // Either the pending or last committed entries can be NULL.
242 const NavigationEntry* pending_entry =
243 contents->controller().pending_entry();
244 const NavigationEntry* last_committed_entry =
245 contents->controller().GetLastCommittedEntry();
246 if ((last_committed_entry &&
247 LowerCaseEqualsASCII(last_committed_entry->display_url().spec(),
248 chrome::kAboutMemoryURL)) ||
249 (pending_entry &&
250 LowerCaseEqualsASCII(pending_entry->display_url().spec(),
251 chrome::kAboutMemoryURL)))
252 process.is_diagnostics = true;
253 }
254 }
255 }
256
257 // Get rid of other Chrome processes that are from a different profile.
258 for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
259 index++) {
260 if (process_data_[CHROME_BROWSER].processes[index].type ==
261 ChildProcessInfo::UNKNOWN_PROCESS) {
262 process_data_[CHROME_BROWSER].processes.erase(
263 process_data_[CHROME_BROWSER].processes.begin() + index);
264 index--;
265 }
266 }
267
268 UpdateHistograms();
269
270 OnDetailsAvailable();
271 }
272
273 void MemoryDetails::UpdateHistograms() {
274 // Reports a set of memory metrics to UMA.
275 // Memory is measured in units of 10KB.
276
277 ProcessData browser = process_data_[CHROME_BROWSER];
278 size_t aggregate_memory = 0;
279 int plugin_count = 0;
280 int worker_count = 0;
281 for (size_t index = 0; index < browser.processes.size(); index++) {
282 int sample = static_cast<int>(browser.processes[index].working_set.priv);
283 aggregate_memory += sample;
284 switch (browser.processes[index].type) {
285 case ChildProcessInfo::BROWSER_PROCESS:
286 UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
287 break;
288 case ChildProcessInfo::RENDER_PROCESS:
289 UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
290 break;
291 case ChildProcessInfo::PLUGIN_PROCESS:
292 UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
293 plugin_count++;
294 break;
295 case ChildProcessInfo::WORKER_PROCESS:
296 UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
297 worker_count++;
298 break;
299 }
300 }
301
302 UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
303 static_cast<int>(browser.processes.size()));
304 UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
305 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
306
307 int total_sample = static_cast<int>(aggregate_memory / 1000);
308 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
309 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698