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

Side by Side Diff: content/renderer/render_thread_impl.cc

Issue 8513008: Schedule idle handler in the foreground tab based on CPU usage and user activity. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Created 9 years, 1 month 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/renderer/render_thread_impl.h" 5 #include "content/renderer/render_thread_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <map> 9 #include <map>
10 #include <vector> 10 #include <vector>
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 using WebKit::WebNetworkStateNotifier; 94 using WebKit::WebNetworkStateNotifier;
95 using WebKit::WebRuntimeFeatures; 95 using WebKit::WebRuntimeFeatures;
96 using WebKit::WebScriptController; 96 using WebKit::WebScriptController;
97 using WebKit::WebString; 97 using WebKit::WebString;
98 using WebKit::WebStorageEventDispatcher; 98 using WebKit::WebStorageEventDispatcher;
99 using WebKit::WebView; 99 using WebKit::WebView;
100 using content::RenderProcessObserver; 100 using content::RenderProcessObserver;
101 101
102 namespace { 102 namespace {
103 static const int64 kInitialIdleHandlerDelayMs = 1000; 103 static const int64 kInitialIdleHandlerDelayMs = 1000;
104 static const int64 kShortIdleHandlerDelayMs = 1000;
105 static const int64 kLongIdleHandlerDelayMs = 30*1000;
106 static const int kIdleCPUUsageThresholdInPercents = 3;
104 107
105 #if defined(TOUCH_UI) 108 #if defined(TOUCH_UI)
106 static const int kPopupListBoxMinimumRowHeight = 60; 109 static const int kPopupListBoxMinimumRowHeight = 60;
107 #endif 110 #endif
108 111
109 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access 112 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
110 // incorrectly from the wrong thread. 113 // incorrectly from the wrong thread.
111 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > 114 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> >
112 lazy_tls = LAZY_INSTANCE_INITIALIZER; 115 lazy_tls = LAZY_INSTANCE_INITIALIZER;
113 116
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 initialize_com_.reset(new base::win::ScopedCOMInitializer()); 189 initialize_com_.reset(new base::win::ScopedCOMInitializer());
187 #endif 190 #endif
188 191
189 // In single process the single process is all there is. 192 // In single process the single process is all there is.
190 suspend_webkit_shared_timer_ = true; 193 suspend_webkit_shared_timer_ = true;
191 notify_webkit_of_modal_loop_ = true; 194 notify_webkit_of_modal_loop_ = true;
192 plugin_refresh_allowed_ = true; 195 plugin_refresh_allowed_ = true;
193 widget_count_ = 0; 196 widget_count_ = 0;
194 hidden_widget_count_ = 0; 197 hidden_widget_count_ = 0;
195 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; 198 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs;
199 idle_notifications_to_skip_ = 0;
200 base::ProcessHandle handle = base::GetCurrentProcessHandle();
201 #if defined(OS_MACOSX)
202 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
203 NULL));
204 #else
205 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
206 #endif
207 process_metrics_->GetCPUUsage(); // Initialize CPU usage counters.
196 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); 208 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this));
197 209
198 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); 210 appcache_dispatcher_.reset(new AppCacheDispatcher(Get()));
199 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); 211 indexed_db_dispatcher_.reset(new IndexedDBDispatcher());
200 212
201 db_message_filter_ = new DBMessageFilter(); 213 db_message_filter_ = new DBMessageFilter();
202 AddFilter(db_message_filter_.get()); 214 AddFilter(db_message_filter_.get());
203 215
204 vc_manager_ = new VideoCaptureImplManager(); 216 vc_manager_ = new VideoCaptureImplManager();
205 AddFilter(vc_manager_->video_capture_message_filter()); 217 AddFilter(vc_manager_->video_capture_message_filter());
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } 420 }
409 421
410 void RenderThreadImpl::WidgetRestored() { 422 void RenderThreadImpl::WidgetRestored() {
411 DCHECK_GT(hidden_widget_count_, 0); 423 DCHECK_GT(hidden_widget_count_, 0);
412 hidden_widget_count_--; 424 hidden_widget_count_--;
413 if (!content::GetContentClient()->renderer()-> 425 if (!content::GetContentClient()->renderer()->
414 RunIdleHandlerWhenWidgetsHidden()) { 426 RunIdleHandlerWhenWidgetsHidden()) {
415 return; 427 return;
416 } 428 }
417 429
418 idle_timer_.Stop(); 430 ScheduleIdleHandler(kLongIdleHandlerDelayMs);
419 } 431 }
420 432
421 void RenderThreadImpl::EnsureWebKitInitialized() { 433 void RenderThreadImpl::EnsureWebKitInitialized() {
422 if (webkit_platform_support_.get()) 434 if (webkit_platform_support_.get())
423 return; 435 return;
424 436
425 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); 437 v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
426 v8::V8::SetCreateHistogramFunction(CreateHistogram); 438 v8::V8::SetCreateHistogramFunction(CreateHistogram);
427 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); 439 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
428 440
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 529
518 WebRuntimeFeatures::enableFileSystem( 530 WebRuntimeFeatures::enableFileSystem(
519 !command_line.HasSwitch(switches::kDisableFileSystem)); 531 !command_line.HasSwitch(switches::kDisableFileSystem));
520 532
521 WebRuntimeFeatures::enableJavaScriptI18NAPI( 533 WebRuntimeFeatures::enableJavaScriptI18NAPI(
522 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); 534 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI));
523 535
524 WebRuntimeFeatures::enableQuota(true); 536 WebRuntimeFeatures::enableQuota(true);
525 537
526 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); 538 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
539
540 if (content::GetContentClient()->renderer()->
541 RunIdleHandlerWhenWidgetsHidden()) {
542 ScheduleIdleHandler(kLongIdleHandlerDelayMs);
543 }
527 } 544 }
528 545
529 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { 546 void RenderThreadImpl::RecordUserMetrics(const std::string& action) {
530 Send(new ViewHostMsg_UserMetricsRecordAction(action)); 547 Send(new ViewHostMsg_UserMetricsRecordAction(action));
531 } 548 }
532 549
533 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( 550 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer(
534 uint32 buffer_size) { 551 uint32 buffer_size) {
535 base::SharedMemoryHandle mem_handle; 552 base::SharedMemoryHandle mem_handle;
536 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( 553 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory(
(...skipping 13 matching lines...) Expand all
550 567
551 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { 568 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) {
552 idle_notification_delay_in_ms_ = initial_delay_ms; 569 idle_notification_delay_in_ms_ = initial_delay_ms;
553 idle_timer_.Stop(); 570 idle_timer_.Stop();
554 idle_timer_.Start(FROM_HERE, 571 idle_timer_.Start(FROM_HERE,
555 base::TimeDelta::FromMilliseconds(initial_delay_ms), 572 base::TimeDelta::FromMilliseconds(initial_delay_ms),
556 this, &RenderThreadImpl::IdleHandler); 573 this, &RenderThreadImpl::IdleHandler);
557 } 574 }
558 575
559 void RenderThreadImpl::IdleHandler() { 576 void RenderThreadImpl::IdleHandler() {
560 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) 577 bool is_extension = !content::GetContentClient()->renderer()->
Matt Perry 2011/11/16 19:23:52 extensions are a chrome concept, and this code liv
ulan 2011/11/16 20:13:22 Done.
578 RunIdleHandlerWhenWidgetsHidden();
579 bool foreground_tab = (widget_count_ > hidden_widget_count_) && !is_extension;
580 if (foreground_tab) {
581 IdleHandlerInForegroundTab();
582 return;
583 }
584 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
561 MallocExtension::instance()->ReleaseFreeMemory(); 585 MallocExtension::instance()->ReleaseFreeMemory();
562 #endif 586 #endif
563 587
564 v8::V8::IdleNotification(); 588 v8::V8::IdleNotification();
565 589
566 // Schedule next invocation. 590 // Schedule next invocation.
567 // Dampen the delay using the algorithm (if delay is in seconds): 591 // Dampen the delay using the algorithm (if delay is in seconds):
568 // delay = delay + 1 / (delay + 2) 592 // delay = delay + 1 / (delay + 2)
569 // Using floor(delay) has a dampening effect such as: 593 // Using floor(delay) has a dampening effect such as:
570 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... 594 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
(...skipping 11 matching lines...) Expand all
582 606
583 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { 607 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
584 return idle_notification_delay_in_ms_; 608 return idle_notification_delay_in_ms_;
585 } 609 }
586 610
587 void RenderThreadImpl::SetIdleNotificationDelayInMs( 611 void RenderThreadImpl::SetIdleNotificationDelayInMs(
588 int64 idle_notification_delay_in_ms) { 612 int64 idle_notification_delay_in_ms) {
589 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; 613 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms;
590 } 614 }
591 615
616 void RenderThreadImpl::PostponeIdleNotification() {
617 idle_notifications_to_skip_ = 2;
618 }
619
592 #if defined(OS_WIN) 620 #if defined(OS_WIN)
593 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { 621 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) {
594 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); 622 Send(new ChildProcessHostMsg_PreCacheFont(log_font));
595 } 623 }
596 624
597 void RenderThreadImpl::ReleaseCachedFonts() { 625 void RenderThreadImpl::ReleaseCachedFonts() {
598 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); 626 Send(new ChildProcessHostMsg_ReleaseCachedFonts());
599 } 627 }
600 628
601 #endif // OS_WIN 629 #endif // OS_WIN
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 void RenderThreadImpl::OnNetworkStateChanged(bool online) { 804 void RenderThreadImpl::OnNetworkStateChanged(bool online) {
777 EnsureWebKitInitialized(); 805 EnsureWebKitInitialized();
778 WebNetworkStateNotifier::setOnLine(online); 806 WebNetworkStateNotifier::setOnLine(online);
779 } 807 }
780 808
781 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { 809 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
782 content::GetContentClient()->SetActiveURL(data); 810 content::GetContentClient()->SetActiveURL(data);
783 CHECK(false); 811 CHECK(false);
784 } 812 }
785 813
814 void RenderThreadImpl::IdleHandlerInForegroundTab() {
Matt Perry 2011/11/16 19:23:52 could you move this next to the other IdleHandler,
ulan 2011/11/16 20:13:22 Done.
815 // Increase the delay in the same way as in IdleHandler,
816 // but make it periodic by reseting it once it is too big.
817 int64 new_delay_ms = idle_notification_delay_in_ms_ +
818 1000000 / (idle_notification_delay_in_ms_ + 2000);
819 if (new_delay_ms >= kLongIdleHandlerDelayMs)
820 new_delay_ms = kShortIdleHandlerDelayMs;
821
822 double cpu_usage = process_metrics_->GetCPUUsage();
ulan 2011/11/16 14:14:46 I didn't place GetCPUUsage inside the "if" stateme
Matt Perry 2011/11/16 19:23:52 Add this as a comment in the code, so someone read
ulan 2011/11/16 20:13:22 Done.
823
824 if (idle_notifications_to_skip_ > 0) {
825 idle_notifications_to_skip_--;
826 } else if (cpu_usage < kIdleCPUUsageThresholdInPercents) {
827 if (v8::V8::IdleNotification()) {
828 // V8 finished collecting garbage.
829 new_delay_ms = kLongIdleHandlerDelayMs;
830 }
831 }
832
833 ScheduleIdleHandler(new_delay_ms);
834 }
835
786 scoped_refptr<base::MessageLoopProxy> 836 scoped_refptr<base::MessageLoopProxy>
787 RenderThreadImpl::GetFileThreadMessageLoopProxy() { 837 RenderThreadImpl::GetFileThreadMessageLoopProxy() {
788 DCHECK(message_loop() == MessageLoop::current()); 838 DCHECK(message_loop() == MessageLoop::current());
789 if (!file_thread_.get()) { 839 if (!file_thread_.get()) {
790 file_thread_.reset(new base::Thread("Renderer::FILE")); 840 file_thread_.reset(new base::Thread("Renderer::FILE"));
791 file_thread_->Start(); 841 file_thread_->Start();
792 } 842 }
793 return file_thread_->message_loop_proxy(); 843 return file_thread_->message_loop_proxy();
794 } 844 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698