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

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

Issue 8574012: Schedule idle handler based on CPU usage. (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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 using WebKit::WebFrame; 93 using WebKit::WebFrame;
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 kLongIdleDelayMs = 30000;
104 static const int64 kShortIdleDelayMs = 1000;
105 static const int kIdleCPUUsageThresholdInPercents = 3;
ulan 2011/11/15 19:08:53 I have chosen these values based on GeneralMixMemo
104 106
105 #if defined(TOUCH_UI) 107 #if defined(TOUCH_UI)
106 static const int kPopupListBoxMinimumRowHeight = 60; 108 static const int kPopupListBoxMinimumRowHeight = 60;
107 #endif 109 #endif
108 110
109 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access 111 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access
110 // incorrectly from the wrong thread. 112 // incorrectly from the wrong thread.
111 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > lazy_tls( 113 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > lazy_tls(
112 base::LINKER_INITIALIZED); 114 base::LINKER_INITIALIZED);
113 115
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 if (RenderProcessImpl::InProcessPlugins()) 187 if (RenderProcessImpl::InProcessPlugins())
186 initialize_com_.reset(new base::win::ScopedCOMInitializer()); 188 initialize_com_.reset(new base::win::ScopedCOMInitializer());
187 #endif 189 #endif
188 190
189 // In single process the single process is all there is. 191 // In single process the single process is all there is.
190 suspend_webkit_shared_timer_ = true; 192 suspend_webkit_shared_timer_ = true;
191 notify_webkit_of_modal_loop_ = true; 193 notify_webkit_of_modal_loop_ = true;
192 plugin_refresh_allowed_ = true; 194 plugin_refresh_allowed_ = true;
193 widget_count_ = 0; 195 widget_count_ = 0;
194 hidden_widget_count_ = 0; 196 hidden_widget_count_ = 0;
195 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; 197 idle_delay_ms_ = kLongIdleDelayMs;
198 base::ProcessHandle handle = base::GetCurrentProcessHandle();
199 #if defined(OS_MACOSX)
200 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle,
201 NULL));
202 #else
203 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
204 #endif
196 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); 205 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this));
197 206
198 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); 207 appcache_dispatcher_.reset(new AppCacheDispatcher(Get()));
199 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); 208 indexed_db_dispatcher_.reset(new IndexedDBDispatcher());
200 209
201 db_message_filter_ = new DBMessageFilter(); 210 db_message_filter_ = new DBMessageFilter();
202 AddFilter(db_message_filter_.get()); 211 AddFilter(db_message_filter_.get());
203 212
204 vc_manager_ = new VideoCaptureImplManager(); 213 vc_manager_ = new VideoCaptureImplManager();
205 AddFilter(vc_manager_->video_capture_message_filter()); 214 AddFilter(vc_manager_->video_capture_message_filter());
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 } 399 }
391 400
392 void RenderThreadImpl::SetResourceDispatcherDelegate( 401 void RenderThreadImpl::SetResourceDispatcherDelegate(
393 content::ResourceDispatcherDelegate* delegate) { 402 content::ResourceDispatcherDelegate* delegate) {
394 resource_dispatcher()->set_delegate(delegate); 403 resource_dispatcher()->set_delegate(delegate);
395 } 404 }
396 405
397 void RenderThreadImpl::WidgetHidden() { 406 void RenderThreadImpl::WidgetHidden() {
398 DCHECK(hidden_widget_count_ < widget_count_); 407 DCHECK(hidden_widget_count_ < widget_count_);
399 hidden_widget_count_++; 408 hidden_widget_count_++;
400
401 if (!content::GetContentClient()->renderer()->
402 RunIdleHandlerWhenWidgetsHidden()) {
403 return;
404 }
405
406 if (widget_count_ && hidden_widget_count_ == widget_count_) 409 if (widget_count_ && hidden_widget_count_ == widget_count_)
407 ScheduleIdleHandler(kInitialIdleHandlerDelayMs); 410 ResetIdleTimer();
408 } 411 }
409 412
410 void RenderThreadImpl::WidgetRestored() { 413 void RenderThreadImpl::WidgetRestored() {
411 DCHECK_GT(hidden_widget_count_, 0); 414 DCHECK_GT(hidden_widget_count_, 0);
412 hidden_widget_count_--; 415 hidden_widget_count_--;
413 if (!content::GetContentClient()->renderer()->
414 RunIdleHandlerWhenWidgetsHidden()) {
415 return;
416 }
417
418 idle_timer_.Stop();
419 } 416 }
420 417
421 void RenderThreadImpl::EnsureWebKitInitialized() { 418 void RenderThreadImpl::EnsureWebKitInitialized() {
422 if (webkit_platform_support_.get()) 419 if (webkit_platform_support_.get())
423 return; 420 return;
424 421
425 v8::V8::SetCounterFunction(base::StatsTable::FindLocation); 422 v8::V8::SetCounterFunction(base::StatsTable::FindLocation);
426 v8::V8::SetCreateHistogramFunction(CreateHistogram); 423 v8::V8::SetCreateHistogramFunction(CreateHistogram);
427 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample); 424 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
428 425
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 514
518 WebRuntimeFeatures::enableFileSystem( 515 WebRuntimeFeatures::enableFileSystem(
519 !command_line.HasSwitch(switches::kDisableFileSystem)); 516 !command_line.HasSwitch(switches::kDisableFileSystem));
520 517
521 WebRuntimeFeatures::enableJavaScriptI18NAPI( 518 WebRuntimeFeatures::enableJavaScriptI18NAPI(
522 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); 519 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI));
523 520
524 WebRuntimeFeatures::enableQuota(true); 521 WebRuntimeFeatures::enableQuota(true);
525 522
526 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); 523 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
524
525 ScheduleIdleHandler(kLongIdleDelayMs);
527 } 526 }
528 527
529 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { 528 void RenderThreadImpl::RecordUserMetrics(const std::string& action) {
530 Send(new ViewHostMsg_UserMetricsRecordAction(action)); 529 Send(new ViewHostMsg_UserMetricsRecordAction(action));
531 } 530 }
532 531
533 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( 532 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer(
534 uint32 buffer_size) { 533 uint32 buffer_size) {
535 base::SharedMemoryHandle mem_handle; 534 base::SharedMemoryHandle mem_handle;
536 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( 535 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory(
537 buffer_size, &mem_handle)); 536 buffer_size, &mem_handle));
538 return mem_handle; 537 return mem_handle;
539 } 538 }
540 539
541 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) { 540 void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
542 WebScriptController::registerExtension(extension); 541 WebScriptController::registerExtension(extension);
543 v8_extensions_.insert(extension->name()); 542 v8_extensions_.insert(extension->name());
544 } 543 }
545 544
546 bool RenderThreadImpl::IsRegisteredExtension( 545 bool RenderThreadImpl::IsRegisteredExtension(
547 const std::string& v8_extension_name) const { 546 const std::string& v8_extension_name) const {
548 return v8_extensions_.find(v8_extension_name) != v8_extensions_.end(); 547 return v8_extensions_.find(v8_extension_name) != v8_extensions_.end();
549 } 548 }
550 549
551 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { 550 void RenderThreadImpl::ResetIdleTimer() {
552 idle_notification_delay_in_ms_ = initial_delay_ms; 551 if (idle_delay_ms_ > kShortIdleDelayMs) {
553 idle_timer_.Stop(); 552 idle_timer_.Stop();
554 idle_timer_.Start(FROM_HERE, 553 ScheduleIdleHandler(kShortIdleDelayMs);
555 base::TimeDelta::FromMilliseconds(initial_delay_ms), 554 }
556 this, &RenderThreadImpl::IdleHandler);
557 }
558
559 void RenderThreadImpl::IdleHandler() {
560 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
561 MallocExtension::instance()->ReleaseFreeMemory();
562 #endif
563
564 v8::V8::IdleNotification();
565
566 // Schedule next invocation.
567 // Dampen the delay using the algorithm (if delay is in seconds):
568 // delay = delay + 1 / (delay + 2)
569 // Using floor(delay) has a dampening effect such as:
570 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
571 // If the delay is in milliseconds, the above formula is equivalent to:
572 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
573 // which is equivalent to
574 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
575 // Note that idle_notification_delay_in_ms_ would be reset to
576 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden.
577 ScheduleIdleHandler(idle_notification_delay_in_ms_ +
578 1000000 / (idle_notification_delay_in_ms_ + 2000));
579
580 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification());
581 }
582
583 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const {
584 return idle_notification_delay_in_ms_;
585 }
586
587 void RenderThreadImpl::SetIdleNotificationDelayInMs(
588 int64 idle_notification_delay_in_ms) {
589 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms;
590 } 555 }
591 556
592 #if defined(OS_WIN) 557 #if defined(OS_WIN)
593 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { 558 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) {
594 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); 559 Send(new ChildProcessHostMsg_PreCacheFont(log_font));
595 } 560 }
596 561
597 void RenderThreadImpl::ReleaseCachedFonts() { 562 void RenderThreadImpl::ReleaseCachedFonts() {
598 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); 563 Send(new ChildProcessHostMsg_ReleaseCachedFonts());
599 } 564 }
(...skipping 16 matching lines...) Expand all
616 } 581 }
617 582
618 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() { 583 void RenderThreadImpl::DoNotSuspendWebKitSharedTimer() {
619 suspend_webkit_shared_timer_ = false; 584 suspend_webkit_shared_timer_ = false;
620 } 585 }
621 586
622 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() { 587 void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
623 notify_webkit_of_modal_loop_ = false; 588 notify_webkit_of_modal_loop_ = false;
624 } 589 }
625 590
591 void RenderThreadImpl::IdleHandler() {
592 // Dampen the delay using the algorithm (if delay is in seconds):
593 // new_delay = delay + 1 / (delay + 2)
594 // Using floor(delay) has a dampening effect such as:
595 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ...
596 // If the delay is in milliseconds, the above formula is equivalent to:
597 // new_delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2)
598 // which is equivalent to
599 // new_delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000).
600 int64 new_delay_ms = idle_delay_ms_ + 1000000 / (idle_delay_ms_ + 2000);
601 if (process_metrics_->GetCPUUsage() < kIdleCPUUsageThresholdInPercents) {
602 new_delay_ms = kShortIdleDelayMs;
603 // Make sure that CPU usage was sampled for short delay, not long delay.
604 if (idle_delay_ms_ == kShortIdleDelayMs) {
605 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
606 MallocExtension::instance()->ReleaseFreeMemory();
607 #endif
608 if (v8::V8::IdleNotification()) {
609 // V8 finished collecting garbage.
610 new_delay_ms = kLongIdleDelayMs;
611 }
612 }
613 }
614 ScheduleIdleHandler(new_delay_ms);
615 }
616
626 void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const GURL& url, 617 void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const GURL& url,
627 double zoom_level) { 618 double zoom_level) {
628 RenderViewZoomer zoomer(url, zoom_level); 619 RenderViewZoomer zoomer(url, zoom_level);
629 content::RenderView::ForEach(&zoomer); 620 content::RenderView::ForEach(&zoomer);
630 } 621 }
631 622
632 void RenderThreadImpl::OnDOMStorageEvent( 623 void RenderThreadImpl::OnDOMStorageEvent(
633 const DOMStorageMsg_Event_Params& params) { 624 const DOMStorageMsg_Event_Params& params) {
634 if (!dom_storage_event_dispatcher_.get()) 625 if (!dom_storage_event_dispatcher_.get())
635 dom_storage_event_dispatcher_.reset(WebStorageEventDispatcher::create()); 626 dom_storage_event_dispatcher_.reset(WebStorageEventDispatcher::create());
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 void RenderThreadImpl::OnNetworkStateChanged(bool online) { 767 void RenderThreadImpl::OnNetworkStateChanged(bool online) {
777 EnsureWebKitInitialized(); 768 EnsureWebKitInitialized();
778 WebNetworkStateNotifier::setOnLine(online); 769 WebNetworkStateNotifier::setOnLine(online);
779 } 770 }
780 771
781 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { 772 void RenderThreadImpl::OnTempCrashWithData(const GURL& data) {
782 content::GetContentClient()->SetActiveURL(data); 773 content::GetContentClient()->SetActiveURL(data);
783 CHECK(false); 774 CHECK(false);
784 } 775 }
785 776
777 void RenderThreadImpl::ScheduleIdleHandler(int64 delay_ms) {
778 idle_delay_ms_ = delay_ms;
779 idle_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
780 this, &RenderThreadImpl::IdleHandler);
781 }
782
786 scoped_refptr<base::MessageLoopProxy> 783 scoped_refptr<base::MessageLoopProxy>
787 RenderThreadImpl::GetFileThreadMessageLoopProxy() { 784 RenderThreadImpl::GetFileThreadMessageLoopProxy() {
788 DCHECK(message_loop() == MessageLoop::current()); 785 DCHECK(message_loop() == MessageLoop::current());
789 if (!file_thread_.get()) { 786 if (!file_thread_.get()) {
790 file_thread_.reset(new base::Thread("Renderer::FILE")); 787 file_thread_.reset(new base::Thread("Renderer::FILE"));
791 file_thread_->Start(); 788 file_thread_->Start();
792 } 789 }
793 return file_thread_->message_loop_proxy(); 790 return file_thread_->message_loop_proxy();
794 } 791 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698