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

Unified Diff: content/browser/renderer_host/render_process_host_impl.cc

Issue 2929113002: Enable spare RenderProcessHost to be preinitialized. (Closed)
Patch Set: Omnibox hook Created 3 years, 6 months 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 side-by-side diff with in-line comments
Download patch
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.
}

Powered by Google App Engine
This is Rietveld 408576698