Index: content/browser/renderer_host/render_process_host_impl.cc |
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc |
index 3f18fa9012d39be745adae2d39e679720fe88a77..4f60035532db041a540fbe4efbeca6b20a18d748 100644 |
--- a/content/browser/renderer_host/render_process_host_impl.cc |
+++ b/content/browser/renderer_host/render_process_host_impl.cc |
@@ -466,6 +466,109 @@ class SessionStorageHolder : public base::SupportsUserData::Data { |
const void* const kDefaultSubframeProcessHostHolderKey = |
&kDefaultSubframeProcessHostHolderKey; |
Charlie Reis
2017/06/25 23:48:27
nit: Please keep this and the DefaultSubframeProce
mattcary
2017/06/26 14:45:06
Whoops, I assumed it was for the preceeding class.
|
+// This class manages spare RenderProcessHosts. |
Charlie Reis
2017/06/25 23:48:27
Please elaborate. :) Is this one per BrowserCont
mattcary
2017/06/26 14:45:06
Done.
|
+class SpareRenderProcessHostManager : public RenderProcessHostObserver { |
+ public: |
+ SpareRenderProcessHostManager() {} |
+ |
+ void WarmupSpareRenderProcessHost(BrowserContext* browser_context) { |
Charlie Reis
2017/06/25 23:48:28
This should return early if we're over the process
mattcary
2017/06/26 14:45:06
Yes. See also your comment about low-end devices.
|
+ StoragePartitionImpl* current_partition = |
+ static_cast<StoragePartitionImpl*>( |
+ BrowserContext::GetStoragePartition(browser_context, nullptr)); |
Charlie Reis
2017/06/25 23:48:28
Do we only allow spare processes in the default St
mattcary
2017/06/26 14:45:07
Done, in the implementation notes above.
|
+ |
+ if (spare_render_process_host_ && |
+ matching_browser_context_ == browser_context && |
+ matching_storage_partition_ == current_partition) { |
+ return; // Nothing to warm up. |
+ } |
+ |
+ CleanupSpareRenderProcessHost(); |
+ |
+ matching_browser_context_ = browser_context; |
+ matching_storage_partition_ = current_partition; |
+ |
+ spare_render_process_host_ = RenderProcessHostImpl::CreateRenderProcessHost( |
+ browser_context, current_partition, false /* is_for_guests_only */); |
Charlie Reis
2017/06/25 23:48:27
If we can't use spare processes for is_for_guests_
mattcary
2017/06/26 14:45:06
Done.
|
+ spare_render_process_host_->AddObserver(this); |
+ spare_render_process_host_->Init(); |
+ } |
+ |
+ RenderProcessHost* MaybeTakeSpareRenderProcessHost( |
+ const BrowserContext* browser_context, |
+ const StoragePartition* partition, |
+ bool is_for_guests_only) { |
+ if (!spare_render_process_host_ || |
+ browser_context != matching_browser_context_ || |
+ partition != matching_storage_partition_ || is_for_guests_only) { |
+ // As a new RenderProcessHost will almost certainly be created, we cleanup |
+ // the non-matching one so as not to waste resources. |
+ CleanupSpareRenderProcessHost(); |
+ return nullptr; |
+ } |
+ |
+ RenderProcessHost* rph = spare_render_process_host_; |
+ DropSpareRenderProcessHost(spare_render_process_host_); |
+ return rph; |
+ } |
+ |
+ void OnStoragePartitionShutdown(StoragePartition* partition) { |
+ if (partition == matching_storage_partition_) { |
Charlie Reis
2017/06/25 23:48:27
nit: No braces needed.
mattcary
2017/06/26 14:45:06
Done.
|
+ CleanupSpareRenderProcessHost(); |
+ } |
+ } |
+ |
+ RenderProcessHost* spare_render_process_host() { |
+ return spare_render_process_host_; |
+ } |
+ |
+ private: |
+ // RenderProcessHostObserver |
+ void RenderProcessWillExit(RenderProcessHost* host) override { |
+ DropSpareRenderProcessHost(host); |
+ } |
+ |
+ void RenderProcessExited(RenderProcessHost* host, |
+ base::TerminationStatus unused_status, |
+ int unused_exit_code) override { |
+ DropSpareRenderProcessHost(host); |
+ } |
+ |
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override { |
+ DropSpareRenderProcessHost(host); |
+ } |
+ |
+ void CleanupSpareRenderProcessHost() { |
+ if (spare_render_process_host_) { |
+ spare_render_process_host_->Cleanup(); |
Charlie Reis
2017/06/25 23:48:27
Is this the right method to be calling? It looks
mattcary
2017/06/26 14:45:07
It's possible that Shutdown is better. My reasonin
Charlie Reis
2017/06/28 22:31:35
Sorry, I missed this in the last round. Looking c
mattcary
2017/06/29 12:57:09
Good find! I don't think that's correct, GetExisti
Charlie Reis
2017/06/29 21:09:16
Thanks! I added a few suggestions to improve thes
|
+ DropSpareRenderProcessHost(spare_render_process_host_); |
+ } |
+ } |
+ |
+ // Remove |host| as a possible spare renderer. Does not shut it down cleanly, |
Charlie Reis
2017/06/25 23:48:28
nit: semicolon rather than comma
mattcary
2017/06/26 14:45:06
Done.
|
+ // the assumption is that the host has been shutdown somewhere else and has |
Charlie Reis
2017/06/25 23:48:28
nit: s/has/is/
mattcary
2017/06/26 14:45:06
Done (well, s/has been/was/, which maybe was your
|
+ // notifying the SpareRenderProcessHostManager. |
+ void DropSpareRenderProcessHost(RenderProcessHost* host) { |
+ if (host && host == spare_render_process_host_) { |
+ spare_render_process_host_->RemoveObserver(this); |
+ spare_render_process_host_ = nullptr; |
+ } |
+ } |
+ |
+ // This is a bare pointer, because RenderProcessHost manages the lifetime of |
+ // all its instances; see g_all_hosts, above. |
+ RenderProcessHost* spare_render_process_host_; |
+ |
+ // Used only to check if a creation request matches the |
+ // spare, and not accessed. |
Charlie Reis
2017/06/25 23:48:28
nit: Rewrap
mattcary
2017/06/26 14:45:06
Done.
|
+ const BrowserContext* matching_browser_context_ = nullptr; |
+ const StoragePartition* matching_storage_partition_ = nullptr; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SpareRenderProcessHostManager); |
+}; |
+ |
+base::LazyInstance<SpareRenderProcessHostManager>::Leaky |
+ g_spare_render_process_host_manager = LAZY_INSTANCE_INITIALIZER; |
+ |
class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, |
public RenderProcessHostObserver { |
public: |
@@ -484,7 +587,7 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, |
// Is this the default storage partition? If it isn't, then just give it its |
// own non-shared process. |
if (partition != default_partition || is_for_guests_only) { |
- RenderProcessHostImpl* host = new RenderProcessHostImpl( |
+ RenderProcessHost* host = RenderProcessHostImpl::CreateRenderProcessHost( |
browser_context_, static_cast<StoragePartitionImpl*>(partition), |
is_for_guests_only); |
host->SetIsNeverSuitableForReuse(); |
@@ -496,7 +599,12 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, |
if (host_) |
return host_; |
- host_ = new RenderProcessHostImpl( |
+ host_ = |
+ g_spare_render_process_host_manager.Get() |
+ .MaybeTakeSpareRenderProcessHost(browser_context_, partition, |
Charlie Reis
2017/06/25 23:48:28
Is there a reason not to do this within CreateRend
mattcary
2017/06/26 14:45:06
Yes, CreateRenderProcessHost is used in WarmupSpar
Charlie Reis
2017/06/26 21:22:49
I see. The trouble right now is that we're duplic
mattcary
2017/06/28 13:14:38
Note that your suggestion could change the behavio
Charlie Reis
2017/06/28 22:31:35
FWIW, the default StoragePartition can't change, b
mattcary
2017/06/29 12:57:09
:P point taken...
|
+ false /* is for guests only */); |
+ |
+ host_ = RenderProcessHostImpl::CreateRenderProcessHost( |
browser_context_, static_cast<StoragePartitionImpl*>(partition), |
false /* for guests only */); |
host_->SetIsNeverSuitableForReuse(); |
@@ -517,7 +625,7 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data, |
// The default subframe render process used for the default storage partition |
// of this BrowserContext. |
- RenderProcessHostImpl* host_ = nullptr; |
+ RenderProcessHost* host_ = nullptr; |
}; |
void CreateMemoryCoordinatorHandle( |
@@ -915,6 +1023,20 @@ void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { |
g_max_renderer_count_override = count; |
} |
+// static |
+RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost( |
+ BrowserContext* browser_context, |
+ StoragePartitionImpl* storage_partition_impl, |
+ bool is_for_guests_only) { |
+ if (g_render_process_host_factory_) { |
+ return g_render_process_host_factory_->CreateRenderProcessHost( |
+ browser_context); |
+ } |
+ |
+ return new RenderProcessHostImpl(browser_context, storage_partition_impl, |
+ is_for_guests_only); |
+} |
+ |
RenderProcessHostImpl::RenderProcessHostImpl( |
BrowserContext* browser_context, |
StoragePartitionImpl* storage_partition_impl, |
@@ -1986,6 +2108,19 @@ void RenderProcessHostImpl::RemoveExpectedNavigationToSite( |
tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID()); |
} |
+// static |
+void RenderProcessHostImpl::OnStoragePartitionShutdown( |
+ StoragePartition* partition) { |
+ g_spare_render_process_host_manager.Get().OnStoragePartitionShutdown( |
+ partition); |
+} |
+ |
+// static |
+RenderProcessHost* |
+RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() { |
+ return g_spare_render_process_host_manager.Get().spare_render_process_host(); |
+} |
+ |
bool RenderProcessHostImpl::IsForGuestsOnly() const { |
return is_for_guests_only_; |
} |
@@ -2924,6 +3059,13 @@ bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host, |
return GetContentClient()->browser()->IsSuitableHost(host, site_url); |
} |
+// static |
+void RenderProcessHost::WarmupSpareRenderProcessHost( |
+ content::BrowserContext* browser_context) { |
+ g_spare_render_process_host_manager.Get().WarmupSpareRenderProcessHost( |
+ browser_context); |
+} |
+ |
// static |
bool RenderProcessHost::run_renderer_in_process() { |
return g_run_renderer_in_process_; |
@@ -3123,18 +3265,20 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance( |
render_process_host = GetExistingProcessHost(browser_context, site_url); |
} |
+ // Try to use a spare process if one is found. |
Charlie Reis
2017/06/25 23:48:27
nit: Start with "Before creating a new process,"
mattcary
2017/06/26 14:45:06
Done.
|
+ StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
+ BrowserContext::GetStoragePartition(browser_context, site_instance)); |
+ if (!render_process_host) { |
+ render_process_host = |
+ g_spare_render_process_host_manager.Get() |
+ .MaybeTakeSpareRenderProcessHost(browser_context, partition, |
+ is_for_guests_only); |
+ } |
+ |
// Otherwise (or if that fails), create a new one. |
if (!render_process_host) { |
- if (g_render_process_host_factory_) { |
- render_process_host = |
- g_render_process_host_factory_->CreateRenderProcessHost( |
- browser_context); |
- } else { |
- StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>( |
- BrowserContext::GetStoragePartition(browser_context, site_instance)); |
- render_process_host = new RenderProcessHostImpl( |
- browser_context, partition, is_for_guests_only); |
- } |
+ render_process_host = |
+ CreateRenderProcessHost(browser_context, partition, is_for_guests_only); |
} |
return render_process_host; |
Charlie Reis
2017/06/25 23:48:27
nit: Unrelated, but can you put a DCHECK(render_pr
mattcary
2017/06/26 14:45:06
Done.
|
} |