OLD | NEW |
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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 using WebKit::WebNetworkStateNotifier; | 95 using WebKit::WebNetworkStateNotifier; |
96 using WebKit::WebRuntimeFeatures; | 96 using WebKit::WebRuntimeFeatures; |
97 using WebKit::WebScriptController; | 97 using WebKit::WebScriptController; |
98 using WebKit::WebString; | 98 using WebKit::WebString; |
99 using WebKit::WebStorageEventDispatcher; | 99 using WebKit::WebStorageEventDispatcher; |
100 using WebKit::WebView; | 100 using WebKit::WebView; |
101 using content::RenderProcessObserver; | 101 using content::RenderProcessObserver; |
102 | 102 |
103 namespace { | 103 namespace { |
104 static const int64 kInitialIdleHandlerDelayMs = 1000; | 104 static const int64 kInitialIdleHandlerDelayMs = 1000; |
| 105 static const int64 kShortIdleHandlerDelayMs = 1000; |
| 106 static const int64 kLongIdleHandlerDelayMs = 30*1000; |
| 107 static const int kIdleCPUUsageThresholdInPercents = 3; |
105 | 108 |
106 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access | 109 // Keep the global RenderThreadImpl in a TLS slot so it is impossible to access |
107 // incorrectly from the wrong thread. | 110 // incorrectly from the wrong thread. |
108 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > | 111 static base::LazyInstance<base::ThreadLocalPointer<RenderThreadImpl> > |
109 lazy_tls = LAZY_INSTANCE_INITIALIZER; | 112 lazy_tls = LAZY_INSTANCE_INITIALIZER; |
110 | 113 |
111 class RenderViewZoomer : public content::RenderViewVisitor { | 114 class RenderViewZoomer : public content::RenderViewVisitor { |
112 public: | 115 public: |
113 RenderViewZoomer(const GURL& url, double zoom_level) | 116 RenderViewZoomer(const GURL& url, double zoom_level) |
114 : zoom_level_(zoom_level) { | 117 : zoom_level_(zoom_level) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 initialize_com_.reset(new base::win::ScopedCOMInitializer()); | 186 initialize_com_.reset(new base::win::ScopedCOMInitializer()); |
184 #endif | 187 #endif |
185 | 188 |
186 // In single process the single process is all there is. | 189 // In single process the single process is all there is. |
187 suspend_webkit_shared_timer_ = true; | 190 suspend_webkit_shared_timer_ = true; |
188 notify_webkit_of_modal_loop_ = true; | 191 notify_webkit_of_modal_loop_ = true; |
189 plugin_refresh_allowed_ = true; | 192 plugin_refresh_allowed_ = true; |
190 widget_count_ = 0; | 193 widget_count_ = 0; |
191 hidden_widget_count_ = 0; | 194 hidden_widget_count_ = 0; |
192 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; | 195 idle_notification_delay_in_ms_ = kInitialIdleHandlerDelayMs; |
| 196 idle_notifications_to_skip_ = 0; |
| 197 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
| 198 #if defined(OS_MACOSX) |
| 199 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle, |
| 200 NULL)); |
| 201 #else |
| 202 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); |
| 203 #endif |
| 204 process_metrics_->GetCPUUsage(); // Initialize CPU usage counters. |
193 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); | 205 task_factory_.reset(new ScopedRunnableMethodFactory<RenderThreadImpl>(this)); |
194 | 206 |
195 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); | 207 appcache_dispatcher_.reset(new AppCacheDispatcher(Get())); |
196 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); | 208 indexed_db_dispatcher_.reset(new IndexedDBDispatcher()); |
197 | 209 |
198 db_message_filter_ = new DBMessageFilter(); | 210 db_message_filter_ = new DBMessageFilter(); |
199 AddFilter(db_message_filter_.get()); | 211 AddFilter(db_message_filter_.get()); |
200 | 212 |
201 vc_manager_ = new VideoCaptureImplManager(); | 213 vc_manager_ = new VideoCaptureImplManager(); |
202 AddFilter(vc_manager_->video_capture_message_filter()); | 214 AddFilter(vc_manager_->video_capture_message_filter()); |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 | 536 |
525 WebRuntimeFeatures::enableFileSystem( | 537 WebRuntimeFeatures::enableFileSystem( |
526 !command_line.HasSwitch(switches::kDisableFileSystem)); | 538 !command_line.HasSwitch(switches::kDisableFileSystem)); |
527 | 539 |
528 WebRuntimeFeatures::enableJavaScriptI18NAPI( | 540 WebRuntimeFeatures::enableJavaScriptI18NAPI( |
529 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); | 541 !command_line.HasSwitch(switches::kDisableJavaScriptI18NAPI)); |
530 | 542 |
531 WebRuntimeFeatures::enableQuota(true); | 543 WebRuntimeFeatures::enableQuota(true); |
532 | 544 |
533 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); | 545 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized()); |
| 546 |
| 547 if (content::GetContentClient()->renderer()-> |
| 548 RunIdleHandlerWhenWidgetsHidden()) { |
| 549 ScheduleIdleHandler(kLongIdleHandlerDelayMs); |
| 550 } |
534 } | 551 } |
535 | 552 |
536 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { | 553 void RenderThreadImpl::RecordUserMetrics(const std::string& action) { |
537 Send(new ViewHostMsg_UserMetricsRecordAction(action)); | 554 Send(new ViewHostMsg_UserMetricsRecordAction(action)); |
538 } | 555 } |
539 | 556 |
540 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( | 557 base::SharedMemoryHandle RenderThreadImpl::HostAllocateSharedMemoryBuffer( |
541 uint32 buffer_size) { | 558 uint32 buffer_size) { |
542 base::SharedMemoryHandle mem_handle; | 559 base::SharedMemoryHandle mem_handle; |
543 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( | 560 Send(new ChildProcessHostMsg_SyncAllocateSharedMemory( |
(...skipping 13 matching lines...) Expand all Loading... |
557 | 574 |
558 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { | 575 void RenderThreadImpl::ScheduleIdleHandler(int64 initial_delay_ms) { |
559 idle_notification_delay_in_ms_ = initial_delay_ms; | 576 idle_notification_delay_in_ms_ = initial_delay_ms; |
560 idle_timer_.Stop(); | 577 idle_timer_.Stop(); |
561 idle_timer_.Start(FROM_HERE, | 578 idle_timer_.Start(FROM_HERE, |
562 base::TimeDelta::FromMilliseconds(initial_delay_ms), | 579 base::TimeDelta::FromMilliseconds(initial_delay_ms), |
563 this, &RenderThreadImpl::IdleHandler); | 580 this, &RenderThreadImpl::IdleHandler); |
564 } | 581 } |
565 | 582 |
566 void RenderThreadImpl::IdleHandler() { | 583 void RenderThreadImpl::IdleHandler() { |
567 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) | 584 bool run_in_foreground_tab = (widget_count_ > hidden_widget_count_) && |
| 585 content::GetContentClient()->renderer()-> |
| 586 RunIdleHandlerWhenWidgetsHidden(); |
| 587 if (run_in_foreground_tab) { |
| 588 IdleHandlerInForegroundTab(); |
| 589 return; |
| 590 } |
| 591 #if !defined(OS_MACOSX) && defined(USE_TCMALLOC) |
568 MallocExtension::instance()->ReleaseFreeMemory(); | 592 MallocExtension::instance()->ReleaseFreeMemory(); |
569 #endif | 593 #endif |
570 | 594 |
571 v8::V8::IdleNotification(); | 595 v8::V8::IdleNotification(); |
572 | 596 |
573 // Schedule next invocation. | 597 // Schedule next invocation. |
574 // Dampen the delay using the algorithm (if delay is in seconds): | 598 // Dampen the delay using the algorithm (if delay is in seconds): |
575 // delay = delay + 1 / (delay + 2) | 599 // delay = delay + 1 / (delay + 2) |
576 // Using floor(delay) has a dampening effect such as: | 600 // Using floor(delay) has a dampening effect such as: |
577 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... | 601 // 1s, 1, 1, 2, 2, 2, 2, 3, 3, ... |
578 // If the delay is in milliseconds, the above formula is equivalent to: | 602 // If the delay is in milliseconds, the above formula is equivalent to: |
579 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) | 603 // delay_ms / 1000 = delay_ms / 1000 + 1 / (delay_ms / 1000 + 2) |
580 // which is equivalent to | 604 // which is equivalent to |
581 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). | 605 // delay_ms = delay_ms + 1000*1000 / (delay_ms + 2000). |
582 // Note that idle_notification_delay_in_ms_ would be reset to | 606 // Note that idle_notification_delay_in_ms_ would be reset to |
583 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. | 607 // kInitialIdleHandlerDelayMs in RenderThreadImpl::WidgetHidden. |
584 ScheduleIdleHandler(idle_notification_delay_in_ms_ + | 608 ScheduleIdleHandler(idle_notification_delay_in_ms_ + |
585 1000000 / (idle_notification_delay_in_ms_ + 2000)); | 609 1000000 / (idle_notification_delay_in_ms_ + 2000)); |
586 | 610 |
587 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); | 611 FOR_EACH_OBSERVER(RenderProcessObserver, observers_, IdleNotification()); |
588 } | 612 } |
589 | 613 |
| 614 void RenderThreadImpl::IdleHandlerInForegroundTab() { |
| 615 // Increase the delay in the same way as in IdleHandler, |
| 616 // but make it periodic by reseting it once it is too big. |
| 617 int64 new_delay_ms = idle_notification_delay_in_ms_ + |
| 618 1000000 / (idle_notification_delay_in_ms_ + 2000); |
| 619 if (new_delay_ms >= kLongIdleHandlerDelayMs) |
| 620 new_delay_ms = kShortIdleHandlerDelayMs; |
| 621 |
| 622 // Sample the CPU usage on each timer event, so that it is more accurate. |
| 623 double cpu_usage = process_metrics_->GetCPUUsage(); |
| 624 |
| 625 if (idle_notifications_to_skip_ > 0) { |
| 626 idle_notifications_to_skip_--; |
| 627 } else if (cpu_usage < kIdleCPUUsageThresholdInPercents) { |
| 628 if (v8::V8::IdleNotification()) { |
| 629 // V8 finished collecting garbage. |
| 630 new_delay_ms = kLongIdleHandlerDelayMs; |
| 631 } |
| 632 } |
| 633 |
| 634 ScheduleIdleHandler(new_delay_ms); |
| 635 } |
| 636 |
590 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { | 637 int64 RenderThreadImpl::GetIdleNotificationDelayInMs() const { |
591 return idle_notification_delay_in_ms_; | 638 return idle_notification_delay_in_ms_; |
592 } | 639 } |
593 | 640 |
594 void RenderThreadImpl::SetIdleNotificationDelayInMs( | 641 void RenderThreadImpl::SetIdleNotificationDelayInMs( |
595 int64 idle_notification_delay_in_ms) { | 642 int64 idle_notification_delay_in_ms) { |
596 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; | 643 idle_notification_delay_in_ms_ = idle_notification_delay_in_ms; |
597 } | 644 } |
598 | 645 |
| 646 void RenderThreadImpl::PostponeIdleNotification() { |
| 647 idle_notifications_to_skip_ = 2; |
| 648 } |
| 649 |
599 #if defined(OS_WIN) | 650 #if defined(OS_WIN) |
600 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { | 651 void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { |
601 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); | 652 Send(new ChildProcessHostMsg_PreCacheFont(log_font)); |
602 } | 653 } |
603 | 654 |
604 void RenderThreadImpl::ReleaseCachedFonts() { | 655 void RenderThreadImpl::ReleaseCachedFonts() { |
605 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); | 656 Send(new ChildProcessHostMsg_ReleaseCachedFonts()); |
606 } | 657 } |
607 | 658 |
608 #endif // OS_WIN | 659 #endif // OS_WIN |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 | 847 |
797 scoped_refptr<base::MessageLoopProxy> | 848 scoped_refptr<base::MessageLoopProxy> |
798 RenderThreadImpl::GetFileThreadMessageLoopProxy() { | 849 RenderThreadImpl::GetFileThreadMessageLoopProxy() { |
799 DCHECK(message_loop() == MessageLoop::current()); | 850 DCHECK(message_loop() == MessageLoop::current()); |
800 if (!file_thread_.get()) { | 851 if (!file_thread_.get()) { |
801 file_thread_.reset(new base::Thread("Renderer::FILE")); | 852 file_thread_.reset(new base::Thread("Renderer::FILE")); |
802 file_thread_->Start(); | 853 file_thread_->Start(); |
803 } | 854 } |
804 return file_thread_->message_loop_proxy(); | 855 return file_thread_->message_loop_proxy(); |
805 } | 856 } |
OLD | NEW |