Index: content/renderer/render_thread_impl.cc |
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc |
index 7562aec4bd25faf7d75ceb26c066df7178f0de13..50f010a7531975500f5ea51ea08351ed0223d070 100644 |
--- a/content/renderer/render_thread_impl.cc |
+++ b/content/renderer/render_thread_impl.cc |
@@ -102,6 +102,9 @@ using content::RenderProcessObserver; |
namespace { |
static const int64 kInitialIdleHandlerDelayMs = 1000; |
+static const int64 kShortIdleHandlerDelayMs = 1000; |
+static const int64 kLongIdleHandlerDelayMs = 30*1000; |
+static const int kIdleCPUUsageThresholdInPercents = 3; |
// Keep the global RenderThreadImpl in a TLS slot so it is impossible to access |
// incorrectly from the wrong thread. |
@@ -190,6 +193,15 @@ void RenderThreadImpl::Init() { |
widget_count_ = 0; |
hidden_widget_count_ = 0; |
idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; |
+ idle_notifications_to_skip_ = 0; |
+ base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
+#if defined(OS_MACOSX) |
+ process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle, |
+ NULL)); |
+#else |
+ process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); |
+#endif |
+ process_metrics_->GetCPUUsage(); // Initialize CPU usage counters. |
task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); |
appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); |
@@ -415,7 +427,7 @@ void RenderThreadImpl::WidgetRestored() { |
return; |
} |
- idle_timer_.Stop(); |
+ ScheduleIdleHandler(kLongIdleHandlerDelayMs); |
} |
void RenderThreadImpl::EnsureWebKitInitialized() { |
@@ -531,6 +543,11 @@ void RenderThreadImpl::EnsureWebKitInitialized() { |
WebRuntimeFeatures::enableQuota(true); |
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); |
+ |
+ if (content::GetContentClient()->renderer()-> |
+ RunIdleHandlerWhenWidgetsHidden()) { |
+ ScheduleIdleHandler(kLongIdleHandlerDelayMs); |
+ } |
} |
void RenderThreadImpl::RecordUserMetrics(const std::string& action) { |
@@ -564,7 +581,14 @@ void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { |
} |
void RenderThreadImpl::IdleHandler() { |
- #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) |
+ bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) && |
+ content::GetContentClient()->renderer()-> |
+ RunIdleHandlerWhenWidgetsHidden(); |
+ if (run_in_foreground_tab) { |
+ IdleHandlerInForegroundTab(); |
+ return; |
+ } |
+#if !defined(OS_MACOSX) && defined(USE_TCMALLOC) |
MallocExtension::instance()->ReleaseFreeMemory(); |
#endif |
@@ -587,6 +611,29 @@ void RenderThreadImpl::IdleHandler() { |
FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); |
} |
+void RenderThreadImpl::IdleHandlerInForegroundTab() { |
+ // Increase the delay in the same way as in IdleHandler, |
+ // but make it periodic by reseting it once it is too big. |
+ int64 new_delay_ms = idle_notification_delay_in_ms_ + |
+ 1000000 / (idle_notification_delay_in_ms_ + 2000); |
+ if (new_delay_ms >= kLongIdleHandlerDelayMs) |
+ new_delay_ms = kShortIdleHandlerDelayMs; |
+ |
+ // Sample the CPU usage on each timer event, so that it is more accurate. |
+ double cpu_usage = process_metrics_->GetCPUUsage(); |
+ |
+ if (idle_notifications_to_skip_ > 0) { |
+ idle_notifications_to_skip_--; |
+ } else if (cpu_usage < kIdleCPUUsageThresholdInPercents) { |
+ if (v8::V8::IdleNotification()) { |
+ // V8 finished collecting garbage. |
+ new_delay_ms = kLongIdleHandlerDelayMs; |
+ } |
+ } |
+ |
+ ScheduleIdleHandler(new_delay_ms); |
+} |
+ |
int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { |
return idle_notification_delay_in_ms_; |
} |
@@ -596,6 +643,10 @@ void RenderThreadImpl::SetIdleNotificationDelayInMs( |
idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; |
} |
+void RenderThreadImpl::PostponeIdleNotification() { |
+ idle_notifications_to_skip_ = 2; |
+} |
+ |
#if defined(OS_WIN) |
void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { |
Send(new ChildProcessHostMsg_PreCacheFont(log_font)); |