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

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

Issue 547063003: Remove the unmaintained performance monitor. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 3 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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/performance_monitor/performance_monitor.h" 5 #include "chrome/browser/performance_monitor/performance_monitor.h"
6 6
7 #include <set>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/logging.h"
13 #include "base/memory/singleton.h" 7 #include "base/memory/singleton.h"
14 #include "base/process/process_iterator.h" 8 #include "base/process/process_iterator.h"
15 #include "base/stl_util.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/threading/worker_pool.h"
18 #include "base/time/time.h" 9 #include "base/time/time.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/browser_shutdown.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/performance_monitor/constants.h"
23 #include "chrome/browser/performance_monitor/performance_monitor_util.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_iterator.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/chrome_version_info.h"
30 #include "content/public/browser/browser_child_process_host.h" 10 #include "content/public/browser/browser_child_process_host.h"
31 #include "content/public/browser/browser_child_process_host_iterator.h" 11 #include "content/public/browser/browser_child_process_host_iterator.h"
32 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/child_process_data.h" 13 #include "content/public/browser/child_process_data.h"
34 #include "content/public/browser/load_notification_details.h" 14 #include "content/public/browser/render_process_host.h"
35 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/notification_types.h"
37 #include "content/public/browser/render_view_host.h"
38 #include "content/public/browser/render_widget_host.h"
39 #include "content/public/browser/render_widget_host_iterator.h"
40 #include "content/public/browser/web_contents.h"
41 #include "net/url_request/url_request.h"
42
43 #if defined(ENABLE_EXTENSIONS)
44 #include "chrome/browser/extensions/crx_installer.h"
45 #include "chrome/common/extensions/extension_constants.h"
46 #include "extensions/common/extension.h"
47 #endif
48 15
49 using content::BrowserThread; 16 using content::BrowserThread;
50 17
51 #if defined(ENABLE_EXTENSIONS) 18 namespace {
52 using extensions::Extension; 19
53 using extensions::UnloadedExtensionInfo; 20 // The default interval at which PerformanceMonitor performs its timed
54 #endif 21 // collections.
22 const int kGatherIntervalInSeconds = 120;
23 }
55 24
56 namespace performance_monitor { 25 namespace performance_monitor {
57 26
58 namespace { 27 PerformanceMonitor::PerformanceMonitor() {
59
60 #if !defined(OS_ANDROID)
61 std::string TimeToString(base::Time time) {
62 int64 time_int64 = time.ToInternalValue();
63 return base::Int64ToString(time_int64);
64 }
65 #endif // !defined(OS_ANDROID)
66
67 bool StringToTime(std::string time, base::Time* output) {
68 int64 time_int64 = 0;
69 if (!base::StringToInt64(time, &time_int64))
70 return false;
71 *output = base::Time::FromInternalValue(time_int64);
72 return true;
73 }
74
75 // Try to get the URL for the RenderViewHost if the host does not correspond to
76 // an incognito profile (we don't store URLs from incognito sessions). Returns
77 // true if url has been populated, and false otherwise.
78 bool MaybeGetURLFromRenderView(const content::RenderViewHost* view,
79 std::string* url) {
80 content::WebContents* web_contents =
81 content::WebContents::FromRenderViewHost(view);
82
83 if (Profile::FromBrowserContext(
84 web_contents->GetBrowserContext())->IsOffTheRecord()) {
85 return false;
86 }
87
88 *url = web_contents->GetURL().spec();
89 return true;
90 }
91
92 // Takes ownership of and deletes |database| on the background thread, to
93 // avoid destruction in the middle of an operation.
94 void DeleteDatabaseOnBackgroundThread(Database* database) {
95 delete database;
96 }
97
98 } // namespace
99
100 bool PerformanceMonitor::initialized_ = false;
101
102 PerformanceMonitor::PerformanceDataForIOThread::PerformanceDataForIOThread()
103 : network_bytes_read(0) {
104 }
105
106 PerformanceMonitor::PerformanceMonitor()
107 : gather_interval_in_seconds_(kDefaultGatherIntervalInSeconds),
108 database_logging_enabled_(false),
109 timer_(FROM_HERE,
110 base::TimeDelta::FromSeconds(kSampleIntervalInSeconds),
111 this,
112 &PerformanceMonitor::DoTimedCollections),
113 disable_timer_autostart_for_testing_(false) {
114 } 28 }
115 29
116 PerformanceMonitor::~PerformanceMonitor() { 30 PerformanceMonitor::~PerformanceMonitor() {
117 BrowserThread::PostBlockingPoolSequencedTask(
118 Database::kDatabaseSequenceToken,
119 FROM_HERE,
120 base::Bind(&DeleteDatabaseOnBackgroundThread, database_.release()));
121 }
122
123 bool PerformanceMonitor::SetDatabasePath(const base::FilePath& path) {
124 if (!database_.get()) {
125 database_path_ = path;
126 return true;
127 }
128
129 // PerformanceMonitor already initialized with another path.
130 return false;
131 } 31 }
132 32
133 // static 33 // static
134 PerformanceMonitor* PerformanceMonitor::GetInstance() { 34 PerformanceMonitor* PerformanceMonitor::GetInstance() {
135 return Singleton<PerformanceMonitor>::get(); 35 return Singleton<PerformanceMonitor>::get();
136 } 36 }
137 37
138 void PerformanceMonitor::Initialize() {
139 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140
141 if (CommandLine::ForCurrentProcess()->HasSwitch(
142 switches::kPerformanceMonitorGathering)) {
143 database_logging_enabled_ = true;
144
145 std::string switch_value = CommandLine::ForCurrentProcess()->
146 GetSwitchValueASCII(switches::kPerformanceMonitorGathering);
147
148 if (!switch_value.empty()) {
149 int specified_interval = 0;
150 if (!base::StringToInt(switch_value, &specified_interval) ||
151 specified_interval <= 0) {
152 LOG(ERROR) << "Invalid value for switch: '"
153 << switches::kPerformanceMonitorGathering
154 << "'; please use an integer greater than 0.";
155 } else {
156 gather_interval_in_seconds_ = std::max(specified_interval,
157 kSampleIntervalInSeconds);
158 }
159 }
160 }
161
162 DCHECK(gather_interval_in_seconds_ >= kSampleIntervalInSeconds);
163
164 next_collection_time_ = base::Time::Now() +
165 base::TimeDelta::FromSeconds(gather_interval_in_seconds_);
166
167 util::PostTaskToDatabaseThreadAndReply(
168 FROM_HERE,
169 base::Bind(&PerformanceMonitor::InitOnBackgroundThread,
170 base::Unretained(this)),
171 base::Bind(&PerformanceMonitor::FinishInit,
172 base::Unretained(this)));
173 }
174
175 void PerformanceMonitor::InitOnBackgroundThread() {
176 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
177
178 if (database_logging_enabled_) {
179 if (!database_)
180 database_ = Database::Create(database_path_);
181
182 if (!database_) {
183 LOG(ERROR) << "Could not initialize database; aborting initialization.";
184 database_logging_enabled_ = false;
185 return;
186 }
187
188 // Initialize the io thread's performance data to the value in the database;
189 // if there isn't a recording in the database, the value stays at 0.
190 Metric metric;
191 if (database_->GetRecentStatsForActivityAndMetric(METRIC_NETWORK_BYTES_READ,
192 &metric)) {
193 performance_data_for_io_thread_.network_bytes_read = metric.value;
194 }
195 }
196 }
197
198 void PerformanceMonitor::FinishInit() {
199 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
200
201 // Events and notifications are only useful if we're logging to the database.
202 if (database_logging_enabled_) {
203 RegisterForNotifications();
204 CheckForUncleanExits();
205 BrowserThread::PostBlockingPoolSequencedTask(
206 Database::kDatabaseSequenceToken,
207 FROM_HERE,
208 base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
209 base::Unretained(this)));
210 }
211
212 // Post a task to the background thread to a function which does nothing.
213 // This will force any tasks the database is performing to finish prior to
214 // the reply being sent, since they use the same thread.
215 //
216 // Important! Make sure that methods in FinishInit() only rely on posting
217 // to the background thread, and do not rely upon a reply from the background
218 // thread; this is necessary for this notification to be valid.
219 util::PostTaskToDatabaseThreadAndReply(
220 FROM_HERE,
221 base::Bind(&base::DoNothing),
222 base::Bind(&PerformanceMonitor::NotifyInitialized,
223 base::Unretained(this)));
224 }
225
226 void PerformanceMonitor::StartGatherCycle() { 38 void PerformanceMonitor::StartGatherCycle() {
227 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 39 DCHECK_CURRENTLY_ON(BrowserThread::UI);
228 40 repeating_timer_.Start(FROM_HERE,
229 // Start our periodic gathering of metrics. 41 base::TimeDelta::FromSeconds(kGatherIntervalInSeconds),
230 if (!disable_timer_autostart_for_testing_) 42 this,
231 timer_.Reset(); 43 &PerformanceMonitor::GatherMetricsMapOnUIThread);
232 }
233
234 void PerformanceMonitor::RegisterForNotifications() {
235 DCHECK(database_logging_enabled_);
236
237 // Extensions
238 registrar_.Add(
239 this,
240 extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
241 content::NotificationService::AllSources());
242 registrar_.Add(this,
243 extensions::NOTIFICATION_EXTENSION_ENABLED,
244 content::NotificationService::AllSources());
245 registrar_.Add(this,
246 extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
247 content::NotificationService::AllSources());
248 registrar_.Add(this,
249 extensions::NOTIFICATION_CRX_INSTALLER_DONE,
250 content::NotificationService::AllSources());
251 registrar_.Add(this,
252 extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED,
253 content::NotificationService::AllSources());
254
255 // Crashes
256 registrar_.Add(this, content::NOTIFICATION_RENDER_WIDGET_HOST_HANG,
257 content::NotificationService::AllSources());
258 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
259 content::NotificationService::AllSources());
260
261 // Profiles (for unclean exit)
262 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
263 content::NotificationService::AllSources());
264
265 // Page load times
266 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
267 content::NotificationService::AllSources());
268 }
269
270 // We check if profiles exited cleanly initialization time in case they were
271 // loaded prior to PerformanceMonitor's initialization. Later profiles will be
272 // checked through the PROFILE_ADDED notification.
273 void PerformanceMonitor::CheckForUncleanExits() {
274 DCHECK(database_logging_enabled_);
275
276 std::vector<Profile*> profiles =
277 g_browser_process->profile_manager()->GetLoadedProfiles();
278
279 for (std::vector<Profile*>::const_iterator iter = profiles.begin();
280 iter != profiles.end(); ++iter) {
281 if ((*iter)->GetLastSessionExitType() == Profile::EXIT_CRASHED) {
282 BrowserThread::PostBlockingPoolSequencedTask(
283 Database::kDatabaseSequenceToken,
284 FROM_HERE,
285 base::Bind(&PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
286 base::Unretained(this),
287 (*iter)->GetDebugName()));
288 }
289 }
290 }
291
292 void PerformanceMonitor::AddUncleanExitEventOnBackgroundThread(
293 const std::string& profile_name) {
294 DCHECK(database_logging_enabled_);
295 std::string database_key = kStateProfilePrefix + profile_name;
296 std::string last_active_string = database_->GetStateValue(database_key);
297
298 // Check if there was no previous time; this should only happen if the profile
299 // was last used prior to PerformanceMonitor's integration. Do nothing in this
300 // case, since the event was prior to the beginning of our recording.
301 if (last_active_string.empty())
302 return;
303
304 base::Time last_active_time;
305 CHECK(StringToTime(last_active_string, &last_active_time));
306
307 scoped_ptr<Event> event =
308 util::CreateUncleanExitEvent(last_active_time, profile_name);
309
310 database_->AddEvent(*event.get());
311 }
312
313 void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() {
314 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
315 DCHECK(database_logging_enabled_);
316
317 chrome::VersionInfo version;
318 DCHECK(version.is_valid());
319 std::string current_version = version.Version();
320
321 std::string previous_version = database_->GetStateValue(kStateChromeVersion);
322
323 // We should never have a current_version which is older than the
324 // previous_version.
325 DCHECK(current_version >= previous_version);
326
327 // If this is the first run, there will not be a stored value for Chrome
328 // version; we insert the current version and will insert an event for the
329 // next update of Chrome. If the previous version is older than the current
330 // version, update the state in the database and insert an event.
331 if (current_version > previous_version) {
332 database_->AddStateValue(kStateChromeVersion, current_version);
333 if (!previous_version.empty()) {
334 scoped_ptr<Event> event = util::CreateChromeUpdateEvent(
335 base::Time::Now(), previous_version, current_version);
336 database_->AddEvent(*event.get());
337 }
338 }
339 }
340
341 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) {
342 DCHECK(database_logging_enabled_);
343
344 BrowserThread::PostBlockingPoolSequencedTask(
345 Database::kDatabaseSequenceToken,
346 FROM_HERE,
347 base::Bind(&PerformanceMonitor::AddEventOnBackgroundThread,
348 base::Unretained(this),
349 base::Passed(&event)));
350 }
351
352 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
353 database_->AddEvent(*event.get());
354 }
355
356 void PerformanceMonitor::AddMetricOnBackgroundThread(const Metric& metric) {
357 DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
358 DCHECK(database_logging_enabled_);
359
360 database_->AddMetric(metric);
361 }
362
363 void PerformanceMonitor::NotifyInitialized() {
364 content::NotificationService::current()->Notify(
365 chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
366 content::Source<PerformanceMonitor>(this),
367 content::NotificationService::NoDetails());
368
369 initialized_ = true;
370 }
371
372 void PerformanceMonitor::DoTimedCollections() {
373 #if !defined(OS_ANDROID)
374 // The profile list is only useful for the logged events.
375 if (database_logging_enabled_)
376 UpdateLiveProfiles();
377 #endif
378
379 GatherMetricsMapOnUIThread();
380 } 44 }
381 45
382 void PerformanceMonitor::GatherMetricsMapOnUIThread() { 46 void PerformanceMonitor::GatherMetricsMapOnUIThread() {
383 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 47 DCHECK_CURRENTLY_ON(BrowserThread::UI);
48
384 static int current_update_sequence = 0; 49 static int current_update_sequence = 0;
385 // Even in the "somewhat" unlikely event this wraps around, 50 // Even in the "somewhat" unlikely event this wraps around,
386 // it doesn't matter. We just check it for inequality. 51 // it doesn't matter. We just check it for inequality.
387 current_update_sequence++; 52 current_update_sequence++;
388 53
389 // Find all render child processes; has to be done on the UI thread. 54 // Find all render child processes; has to be done on the UI thread.
390 for (content::RenderProcessHost::iterator rph_iter = 55 for (content::RenderProcessHost::iterator rph_iter =
391 content::RenderProcessHost::AllHostsIterator(); 56 content::RenderProcessHost::AllHostsIterator();
392 !rph_iter.IsAtEnd(); rph_iter.Advance()) { 57 !rph_iter.IsAtEnd(); rph_iter.Advance()) {
393 base::ProcessHandle handle = rph_iter.GetCurrentValue()->GetHandle(); 58 base::ProcessHandle handle = rph_iter.GetCurrentValue()->GetHandle();
394 MarkProcessAsAlive(handle, content::PROCESS_TYPE_RENDERER, 59 MarkProcessAsAlive(handle, content::PROCESS_TYPE_RENDERER,
395 current_update_sequence); 60 current_update_sequence);
396 } 61 }
397 62
398 BrowserThread::PostTask( 63 BrowserThread::PostTask(
399 BrowserThread::IO, 64 BrowserThread::IO,
400 FROM_HERE, 65 FROM_HERE,
401 base::Bind(&PerformanceMonitor::GatherMetricsMapOnIOThread, 66 base::Bind(&PerformanceMonitor::GatherMetricsMapOnIOThread,
402 base::Unretained(this), 67 base::Unretained(this),
403 current_update_sequence)); 68 current_update_sequence));
404 } 69 }
405 70
406 void PerformanceMonitor::MarkProcessAsAlive(const base::ProcessHandle& handle, 71 void PerformanceMonitor::MarkProcessAsAlive(const base::ProcessHandle& handle,
407 int process_type, 72 int process_type,
408 int current_update_sequence) { 73 int current_update_sequence) {
409 if (handle == 0) { 74 if (handle == 0) {
410 // Process may not be valid yet. 75 // Process may not be valid yet.
411 return; 76 return;
412 } 77 }
413 78
414 MetricsMap::iterator process_metrics_iter = metrics_map_.find(handle); 79 MetricsMap::iterator process_metrics_iter = metrics_map_.find(handle);
415 if (process_metrics_iter == metrics_map_.end()) { 80 if (process_metrics_iter == metrics_map_.end()) {
416 // If we're not already watching the process, let's initialize it. 81 // If we're not already watching the process, let's initialize it.
417 metrics_map_[handle] 82 metrics_map_[handle]
418 .Initialize(handle, process_type, current_update_sequence); 83 .Initialize(handle, process_type, current_update_sequence);
419 } else { 84 } else {
420 // If we are watching the process, touch it to keep it alive. 85 // If we are watching the process, touch it to keep it alive.
421 ProcessMetricsHistory& process_metrics = process_metrics_iter->second; 86 ProcessMetricsHistory& process_metrics = process_metrics_iter->second;
422 process_metrics.set_last_update_sequence(current_update_sequence); 87 process_metrics.set_last_update_sequence(current_update_sequence);
423 } 88 }
424 } 89 }
425 90
426 #if !defined(OS_ANDROID)
427 void PerformanceMonitor::UpdateLiveProfiles() {
428 std::string time = TimeToString(base::Time::Now());
429 scoped_ptr<std::set<std::string> > active_profiles(
430 new std::set<std::string>());
431
432 for (chrome::BrowserIterator it; !it.done(); it.Next())
433 active_profiles->insert(it->profile()->GetDebugName());
434
435 BrowserThread::PostBlockingPoolSequencedTask(
436 Database::kDatabaseSequenceToken,
437 FROM_HERE,
438 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
439 base::Unretained(this),
440 base::Passed(&active_profiles),
441 time));
442 }
443
444 void PerformanceMonitor::UpdateLiveProfilesHelper(
445 scoped_ptr<std::set<std::string> > active_profiles,
446 std::string time) {
447 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
448 DCHECK(database_logging_enabled_);
449
450 for (std::set<std::string>::const_iterator iter = active_profiles->begin();
451 iter != active_profiles->end(); ++iter) {
452 database_->AddStateValue(kStateProfilePrefix + *iter, time);
453 }
454 }
455 #endif
456
457 void PerformanceMonitor::GatherMetricsMapOnIOThread( 91 void PerformanceMonitor::GatherMetricsMapOnIOThread(
458 int current_update_sequence) { 92 int current_update_sequence) {
459 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
460 94
461 // Find all child processes (does not include renderers), which has to be 95 // Find all child processes (does not include renderers), which has to be
462 // done on the IO thread. 96 // done on the IO thread.
463 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { 97 for (content::BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
464 const content::ChildProcessData& child_process_data = iter.GetData(); 98 const content::ChildProcessData& child_process_data = iter.GetData();
465 base::ProcessHandle handle = child_process_data.handle; 99 base::ProcessHandle handle = child_process_data.handle;
466 MarkProcessAsAlive(handle, child_process_data.process_type, 100 MarkProcessAsAlive(handle, child_process_data.process_type,
467 current_update_sequence); 101 current_update_sequence);
468 } 102 }
469 103
470 // Add the current (browser) process. 104 // Add the current (browser) process.
471 MarkProcessAsAlive(base::GetCurrentProcessHandle(), 105 MarkProcessAsAlive(base::GetCurrentProcessHandle(),
472 content::PROCESS_TYPE_BROWSER, current_update_sequence); 106 content::PROCESS_TYPE_BROWSER, current_update_sequence);
473 107
474 BrowserThread::PostBlockingPoolSequencedTask(
475 Database::kDatabaseSequenceToken,
476 FROM_HERE,
477 base::Bind(&PerformanceMonitor::StoreMetricsOnBackgroundThread,
478 base::Unretained(this), current_update_sequence,
479 performance_data_for_io_thread_));
480 }
481
482 void PerformanceMonitor::StoreMetricsOnBackgroundThread(
483 int current_update_sequence,
484 const PerformanceDataForIOThread& performance_data_for_io_thread) {
485 CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
486
487 base::Time time_now = base::Time::Now();
488
489 // The timing can be off by kSampleIntervalInSeconds during any one particular
490 // run, but will be correct over time.
491 bool end_of_cycle = time_now >= next_collection_time_;
492 if (end_of_cycle) {
493 next_collection_time_ +=
494 base::TimeDelta::FromSeconds(gather_interval_in_seconds_);
495 }
496
497 double cpu_usage = 0.0; 108 double cpu_usage = 0.0;
498 size_t private_memory_sum = 0; 109 size_t private_memory_sum = 0;
499 size_t shared_memory_sum = 0; 110 size_t shared_memory_sum = 0;
500 111
501 // Update metrics for all watched processes; remove dead entries from the map. 112 // Update metrics for all watched processes; remove dead entries from the map.
502 MetricsMap::iterator iter = metrics_map_.begin(); 113 MetricsMap::iterator iter = metrics_map_.begin();
503 while (iter != metrics_map_.end()) { 114 while (iter != metrics_map_.end()) {
504 ProcessMetricsHistory& process_metrics = iter->second; 115 ProcessMetricsHistory& process_metrics = iter->second;
505 if (process_metrics.last_update_sequence() != current_update_sequence) { 116 if (process_metrics.last_update_sequence() != current_update_sequence) {
506 // Not touched this iteration; let's get rid of it. 117 // Not touched this iteration; let's get rid of it.
507 metrics_map_.erase(iter++); 118 metrics_map_.erase(iter++);
508 } else { 119 } else {
509 process_metrics.SampleMetrics(); 120 process_metrics.SampleMetrics();
510 121
511 if (end_of_cycle) { 122 // Gather averages of previously sampled metrics.
512 // Gather averages of previously sampled metrics. 123 cpu_usage += process_metrics.GetAverageCPUUsage();
513 cpu_usage += process_metrics.GetAverageCPUUsage();
514 124
515 size_t private_memory = 0; 125 size_t private_memory = 0;
516 size_t shared_memory = 0; 126 size_t shared_memory = 0;
517 process_metrics.GetAverageMemoryBytes(&private_memory, &shared_memory); 127 process_metrics.GetAverageMemoryBytes(&private_memory, &shared_memory);
518 private_memory_sum += private_memory; 128 private_memory_sum += private_memory;
519 shared_memory_sum += shared_memory; 129 shared_memory_sum += shared_memory;
520 130
521 process_metrics.EndOfCycle(); 131 process_metrics.EndOfCycle();
522 }
523 132
524 ++iter; 133 ++iter;
525 } 134 }
526 } 135 }
527
528 // Store previously-sampled metrics.
529 if (end_of_cycle && database_logging_enabled_) {
530 if (!metrics_map_.empty()) {
531 database_->AddMetric(Metric(METRIC_CPU_USAGE, time_now, cpu_usage));
532 database_->AddMetric(Metric(METRIC_PRIVATE_MEMORY_USAGE,
533 time_now,
534 static_cast<double>(private_memory_sum)));
535 database_->AddMetric(Metric(METRIC_SHARED_MEMORY_USAGE,
536 time_now,
537 static_cast<double>(shared_memory_sum)));
538 }
539
540 database_->AddMetric(
541 Metric(METRIC_NETWORK_BYTES_READ,
542 time_now,
543 static_cast<double>(
544 performance_data_for_io_thread.network_bytes_read)));
545 }
546
547 BrowserThread::PostTask(
548 BrowserThread::UI,
549 FROM_HERE,
550 base::Bind(&PerformanceMonitor::StartGatherCycle,
551 base::Unretained(this)));
552 }
553
554 void PerformanceMonitor::BytesReadOnIOThread(const net::URLRequest& request,
555 const int bytes_read) {
556 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
557
558 if (initialized_ && !request.url().SchemeIsFile())
559 performance_data_for_io_thread_.network_bytes_read += bytes_read;
560 }
561
562 void PerformanceMonitor::Observe(int type,
563 const content::NotificationSource& source,
564 const content::NotificationDetails& details) {
565 DCHECK(database_logging_enabled_);
566
567 switch (type) {
568 #if defined(ENABLE_EXTENSIONS)
569 case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: {
570 AddExtensionEvent(
571 EVENT_EXTENSION_INSTALL,
572 content::Details<const extensions::InstalledExtensionInfo>(details)->
573 extension);
574 break;
575 }
576 case extensions::NOTIFICATION_EXTENSION_ENABLED: {
577 AddExtensionEvent(EVENT_EXTENSION_ENABLE,
578 content::Details<Extension>(details).ptr());
579 break;
580 }
581 case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
582 const UnloadedExtensionInfo* info =
583 content::Details<UnloadedExtensionInfo>(details).ptr();
584
585 // Check if the extension was unloaded because it was disabled.
586 if (info->reason == UnloadedExtensionInfo::REASON_DISABLE) {
587 AddExtensionEvent(EVENT_EXTENSION_DISABLE,
588 info->extension);
589 }
590 break;
591 }
592 case extensions::NOTIFICATION_CRX_INSTALLER_DONE: {
593 const extensions::CrxInstaller* installer =
594 content::Source<extensions::CrxInstaller>(source).ptr();
595 const extensions::Extension* extension =
596 content::Details<Extension>(details).ptr();
597
598 // Check if the reason for the install was due to a successful
599 // extension update. |extension| is NULL in case of install failure.
600 if (extension &&
601 installer->install_cause() == extension_misc::INSTALL_CAUSE_UPDATE) {
602 AddExtensionEvent(EVENT_EXTENSION_UPDATE, extension);
603 }
604 break;
605 }
606 case extensions::NOTIFICATION_EXTENSION_UNINSTALLED_DEPRECATED: {
607 AddExtensionEvent(EVENT_EXTENSION_UNINSTALL,
608 content::Details<Extension>(details).ptr());
609 break;
610 }
611 #endif // defined(ENABLE_EXTENSIONS)
612 case content::NOTIFICATION_RENDER_WIDGET_HOST_HANG: {
613 std::string url;
614 content::RenderWidgetHost* widget =
615 content::Source<content::RenderWidgetHost>(source).ptr();
616 if (widget->IsRenderView()) {
617 content::RenderViewHost* view = content::RenderViewHost::From(widget);
618 MaybeGetURLFromRenderView(view, &url);
619 }
620 AddEvent(util::CreateRendererFailureEvent(base::Time::Now(),
621 EVENT_RENDERER_HANG,
622 url));
623 break;
624 }
625 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
626 AddRendererClosedEvent(
627 content::Source<content::RenderProcessHost>(source).ptr(),
628 *content::Details<content::RenderProcessHost::RendererClosedDetails>(
629 details).ptr());
630 break;
631 }
632 case chrome::NOTIFICATION_PROFILE_ADDED: {
633 Profile* profile = content::Source<Profile>(source).ptr();
634 if (profile->GetLastSessionExitType() == Profile::EXIT_CRASHED) {
635 BrowserThread::PostBlockingPoolSequencedTask(
636 Database::kDatabaseSequenceToken,
637 FROM_HERE,
638 base::Bind(
639 &PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
640 base::Unretained(this),
641 profile->GetDebugName()));
642 }
643 break;
644 }
645 case content::NOTIFICATION_LOAD_STOP: {
646 const content::LoadNotificationDetails* load_details =
647 content::Details<content::LoadNotificationDetails>(details).ptr();
648 if (!load_details)
649 break;
650 BrowserThread::PostBlockingPoolSequencedTask(
651 Database::kDatabaseSequenceToken,
652 FROM_HERE,
653 base::Bind(
654 &PerformanceMonitor::AddMetricOnBackgroundThread,
655 base::Unretained(this),
656 Metric(METRIC_PAGE_LOAD_TIME,
657 base::Time::Now(),
658 static_cast<double>(
659 load_details->load_time.ToInternalValue()))));
660 break;
661 }
662 default: {
663 NOTREACHED();
664 break;
665 }
666 }
667 }
668
669 #if defined(ENABLE_EXTENSIONS)
670 void PerformanceMonitor::AddExtensionEvent(EventType type,
671 const Extension* extension) {
672 DCHECK(type == EVENT_EXTENSION_INSTALL ||
673 type == EVENT_EXTENSION_UNINSTALL ||
674 type == EVENT_EXTENSION_UPDATE ||
675 type == EVENT_EXTENSION_ENABLE ||
676 type == EVENT_EXTENSION_DISABLE);
677 AddEvent(util::CreateExtensionEvent(type,
678 base::Time::Now(),
679 extension->id(),
680 extension->name(),
681 extension->url().spec(),
682 extension->location(),
683 extension->VersionString(),
684 extension->description()));
685 }
686 #endif // defined(ENABLE_EXTENSIONS)
687
688 void PerformanceMonitor::AddRendererClosedEvent(
689 content::RenderProcessHost* host,
690 const content::RenderProcessHost::RendererClosedDetails& details) {
691 // We only care if this is an invalid termination.
692 if (details.status == base::TERMINATION_STATUS_NORMAL_TERMINATION ||
693 details.status == base::TERMINATION_STATUS_STILL_RUNNING)
694 return;
695
696 // Determine the type of crash.
697 EventType type =
698 details.status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
699 EVENT_RENDERER_KILLED : EVENT_RENDERER_CRASH;
700
701 // A RenderProcessHost may contain multiple render views - for each valid
702 // render view, extract the url, and append it to the string, comma-separating
703 // the entries.
704 std::string url_list;
705 scoped_ptr<content::RenderWidgetHostIterator> widgets(
706 content::RenderWidgetHost::GetRenderWidgetHosts());
707 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
708 if (widget->GetProcess()->GetID() != host->GetID())
709 continue;
710 if (!widget->IsRenderView())
711 continue;
712
713 content::RenderViewHost* view = content::RenderViewHost::From(widget);
714 std::string url;
715 if (!MaybeGetURLFromRenderView(view, &url))
716 continue;
717
718 if (!url_list.empty())
719 url_list += ", ";
720
721 url_list += url;
722 }
723
724 AddEvent(util::CreateRendererFailureEvent(base::Time::Now(), type, url_list));
725 } 136 }
726 137
727 } // namespace performance_monitor 138 } // namespace performance_monitor
OLDNEW
« no previous file with comments | « chrome/browser/performance_monitor/performance_monitor.h ('k') | chrome/browser/performance_monitor/performance_monitor.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698