mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-14 05:44:20 +00:00
Bug 1364849 - Recycle short lived content processes. r=mrbkap
To prevent addons or other code to rapidly create and destroy content processes under various conditions, we let the preallocated process manager to reuse short lived content processes.
This commit is contained in:
parent
f3ac40becf
commit
98fc89bfe4
@ -862,12 +862,17 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
}
|
||||
|
||||
// Try to take the preallocated process only for the default process type.
|
||||
// The preallocated process manager might not had the chance yet to release the process
|
||||
// after a very recent ShutDownProcess, let's make sure we don't try to reuse a process
|
||||
// that is being shut down.
|
||||
RefPtr<ContentParent> p;
|
||||
if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
|
||||
(p = PreallocatedProcessManager::Take())) {
|
||||
(p = PreallocatedProcessManager::Take()) &&
|
||||
!p->mShutdownPending) {
|
||||
// For pre-allocated process we have not set the opener yet.
|
||||
p->mOpener = aOpener;
|
||||
contentParents.AppendElement(p);
|
||||
p->mActivateTS = TimeStamp::Now();
|
||||
return p.forget();
|
||||
}
|
||||
}
|
||||
@ -882,6 +887,7 @@ ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
|
||||
p->Init();
|
||||
|
||||
contentParents.AppendElement(p);
|
||||
p->mActivateTS = TimeStamp::Now();
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
@ -1522,7 +1528,7 @@ ContentParent::ShutDownMessageManager()
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::MarkAsTroubled()
|
||||
ContentParent::RemoveFromList()
|
||||
{
|
||||
if (IsForJSPlugin()) {
|
||||
if (sJSPluginContentParents) {
|
||||
@ -1554,6 +1560,12 @@ ContentParent::MarkAsTroubled()
|
||||
sPrivateContent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::MarkAsTroubled()
|
||||
{
|
||||
RemoveFromList();
|
||||
mIsAvailable = false;
|
||||
}
|
||||
|
||||
@ -1854,6 +1866,26 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::TryToRecycle()
|
||||
{
|
||||
// This life time check should be replaced by a memory health check (memory usage + fragmentation).
|
||||
const double kMaxLifeSpan = 5;
|
||||
if (mShutdownPending ||
|
||||
mCalledKillHard ||
|
||||
!IsAvailable() ||
|
||||
!mRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) ||
|
||||
(TimeStamp::Now() - mActivateTS).ToSeconds() > kMaxLifeSpan ||
|
||||
!PreallocatedProcessManager::Provide(this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The PreallocatedProcessManager took over the ownership let's not keep a reference to it,
|
||||
// until we don't take it back.
|
||||
RemoveFromList();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::ShouldKeepProcessAlive() const
|
||||
{
|
||||
@ -1916,6 +1948,10 @@ ContentParent::NotifyTabDestroying(const TabId& aTabId,
|
||||
return;
|
||||
}
|
||||
|
||||
if (cp->TryToRecycle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're dying now, so prevent this content process from being
|
||||
// recycled during its shutdown procedure.
|
||||
cp->MarkAsDead();
|
||||
@ -1965,7 +2001,7 @@ ContentParent::NotifyTabDestroyed(const TabId& aTabId,
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
nsTArray<TabId> tabIds = cpm->GetTabParentsByProcessId(this->ChildID());
|
||||
|
||||
if (tabIds.Length() == 1 && !ShouldKeepProcessAlive()) {
|
||||
if (tabIds.Length() == 1 && !ShouldKeepProcessAlive() && !TryToRecycle()) {
|
||||
// In the case of normal shutdown, send a shutdown message to child to
|
||||
// allow it to perform shutdown tasks.
|
||||
MessageLoop::current()->PostTask(NewRunnableMethod
|
||||
@ -2103,6 +2139,7 @@ ContentParent::ContentParent(ContentParent* aOpener,
|
||||
: nsIContentParent()
|
||||
, mSubprocess(nullptr)
|
||||
, mLaunchTS(TimeStamp::Now())
|
||||
, mActivateTS(TimeStamp::Now())
|
||||
, mOpener(aOpener)
|
||||
, mRemoteType(aRemoteType)
|
||||
, mChildID(gContentChildID++)
|
||||
|
@ -750,6 +750,17 @@ private:
|
||||
// called after the process has been transformed to browser.
|
||||
void ForwardKnownInfo();
|
||||
|
||||
/**
|
||||
* We might want to reuse barely used content processes if certain criteria are met.
|
||||
*/
|
||||
bool TryToRecycle();
|
||||
|
||||
/**
|
||||
* Removing it from the static array so it won't be returned for new tabs in
|
||||
* GetNewOrUsedBrowserProcess.
|
||||
*/
|
||||
void RemoveFromList();
|
||||
|
||||
/**
|
||||
* Decide whether the process should be kept alive even when it would normally
|
||||
* be shut down, for example when all its tabs are closed.
|
||||
@ -1182,6 +1193,7 @@ private:
|
||||
|
||||
GeckoChildProcessHost* mSubprocess;
|
||||
const TimeStamp mLaunchTS; // used to calculate time to start content process
|
||||
TimeStamp mActivateTS;
|
||||
ContentParent* mOpener;
|
||||
|
||||
nsString mRemoteType;
|
||||
|
@ -43,6 +43,7 @@ public:
|
||||
void AllocateOnIdle();
|
||||
void AllocateNow();
|
||||
already_AddRefed<ContentParent> Take();
|
||||
bool Provide(ContentParent* aParent);
|
||||
|
||||
private:
|
||||
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
|
||||
@ -163,9 +164,26 @@ PreallocatedProcessManagerImpl::RereadPrefs()
|
||||
already_AddRefed<ContentParent>
|
||||
PreallocatedProcessManagerImpl::Take()
|
||||
{
|
||||
if (!mEnabled || mShutdown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mPreallocatedProcess.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
PreallocatedProcessManagerImpl::Provide(ContentParent* aParent)
|
||||
{
|
||||
if (mEnabled && !mShutdown && !mPreallocatedProcess) {
|
||||
mPreallocatedProcess = aParent;
|
||||
}
|
||||
|
||||
// We might get a call from both NotifyTabDestroying and NotifyTabDestroyed with the same
|
||||
// ContentParent. Returning true here for both calls is important to avoid the cached process
|
||||
// to be destroyed.
|
||||
return aParent == mPreallocatedProcess;
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::Enable()
|
||||
{
|
||||
@ -282,4 +300,10 @@ PreallocatedProcessManager::Take()
|
||||
return GetPPMImpl()->Take();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
PreallocatedProcessManager::Provide(ContentParent* aParent)
|
||||
{
|
||||
return GetPPMImpl()->Provide(aParent);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
*/
|
||||
static already_AddRefed<ContentParent> Take();
|
||||
|
||||
static bool Provide(ContentParent* aParent);
|
||||
|
||||
private:
|
||||
PreallocatedProcessManager();
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
|
||||
|
Loading…
x
Reference in New Issue
Block a user