зеркало из https://github.com/mozilla/gecko-dev.git
Bug 977940, part 1 - Don't run the ghost window detector more than every 45 seconds. r=smaug
This commit is contained in:
Родитель
9d8a267db1
Коммит
260d421e2f
|
@ -24,11 +24,22 @@ using namespace mozilla;
|
|||
|
||||
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
|
||||
|
||||
/**
|
||||
* Don't trigger a ghost window check when a DOM window is detached if we've
|
||||
* run it this recently.
|
||||
*/
|
||||
const int32_t kTimeBetweenChecks = 45; /* seconds */
|
||||
|
||||
nsWindowMemoryReporter::nsWindowMemoryReporter()
|
||||
: mCheckForGhostWindowsCallbackPending(false)
|
||||
: mLastCheckForGhostWindows(TimeStamp::NowLoRes())
|
||||
{
|
||||
}
|
||||
|
||||
nsWindowMemoryReporter::~nsWindowMemoryReporter()
|
||||
{
|
||||
KillCheckTimer();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
|
||||
nsSupportsWeakReference)
|
||||
|
||||
|
@ -626,12 +637,38 @@ nsWindowMemoryReporter::ObserveDOMWindowDetached(nsISupports* aWindow)
|
|||
|
||||
mDetachedWindows.Put(weakWindow, TimeStamp());
|
||||
|
||||
if (!mCheckForGhostWindowsCallbackPending) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this,
|
||||
&nsWindowMemoryReporter::CheckForGhostWindowsCallback);
|
||||
NS_DispatchToCurrentThread(runnable);
|
||||
mCheckForGhostWindowsCallbackPending = true;
|
||||
AsyncCheckForGhostWindows();
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsWindowMemoryReporter::CheckTimerFired(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
if (sWindowReporter) {
|
||||
sWindowReporter->CheckForGhostWindows();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowMemoryReporter::AsyncCheckForGhostWindows()
|
||||
{
|
||||
if (mCheckTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If more than kTimeBetweenChecks seconds have elapsed since the last check,
|
||||
// timerDelay is 0. Otherwise, it is kTimeBetweenChecks, reduced by the time
|
||||
// since the last check. Reducing the delay by the time since the last check
|
||||
// prevents the timer from being completely starved if it is repeatedly killed
|
||||
// and restarted.
|
||||
int32_t timeSinceLastCheck = (TimeStamp::NowLoRes() - mLastCheckForGhostWindows).ToSeconds();
|
||||
int32_t timerDelay = (kTimeBetweenChecks - std::min(timeSinceLastCheck, kTimeBetweenChecks)) * PR_MSEC_PER_SEC;
|
||||
|
||||
CallCreateInstance<nsITimer>("@mozilla.org/timer;1", getter_AddRefs(mCheckTimer));
|
||||
|
||||
if (mCheckTimer) {
|
||||
mCheckTimer->InitWithFuncCallback(CheckTimerFired, nullptr,
|
||||
timerDelay, nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -664,13 +701,6 @@ nsWindowMemoryReporter::ObserveAfterMinimizeMemoryUsage()
|
|||
&minTimeStamp);
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowMemoryReporter::CheckForGhostWindowsCallback()
|
||||
{
|
||||
mCheckForGhostWindowsCallbackPending = false;
|
||||
CheckForGhostWindows();
|
||||
}
|
||||
|
||||
struct CheckForGhostWindowsEnumeratorData
|
||||
{
|
||||
nsTHashtable<nsCStringHashKey> *nonDetachedDomains;
|
||||
|
@ -808,6 +838,9 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
return;
|
||||
}
|
||||
|
||||
mLastCheckForGhostWindows = TimeStamp::NowLoRes();
|
||||
KillCheckTimer();
|
||||
|
||||
nsTHashtable<nsCStringHashKey> nonDetachedWindowDomains;
|
||||
|
||||
// Populate nonDetachedWindowDomains.
|
||||
|
@ -820,7 +853,7 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
|||
// if it's not null.
|
||||
CheckForGhostWindowsEnumeratorData ghostEnumData =
|
||||
{ &nonDetachedWindowDomains, aOutGhostIDs, tldService,
|
||||
GetGhostTimeout(), TimeStamp::Now() };
|
||||
GetGhostTimeout(), mLastCheckForGhostWindows };
|
||||
mDetachedWindows.Enumerate(CheckForGhostWindowsEnumerator,
|
||||
&ghostEnumData);
|
||||
}
|
||||
|
@ -836,6 +869,15 @@ nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
|
|||
return ghostWindows.Count();
|
||||
}
|
||||
|
||||
void
|
||||
nsWindowMemoryReporter::KillCheckTimer()
|
||||
{
|
||||
if (mCheckTimer) {
|
||||
mCheckTimer->Cancel();
|
||||
mCheckTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static PLDHashOperator
|
||||
UnlinkGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void *)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -139,6 +140,8 @@ public:
|
|||
|
||||
static void Init();
|
||||
|
||||
~nsWindowMemoryReporter();
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Unlink all known ghost windows, to enable investigating what caused them
|
||||
|
@ -187,13 +190,6 @@ private:
|
|||
void ObserveDOMWindowDetached(nsISupports* aWindow);
|
||||
void ObserveAfterMinimizeMemoryUsage();
|
||||
|
||||
/**
|
||||
* When we observe a DOM window being detached, we enqueue an asynchronous
|
||||
* event which calls this method. This method then calls
|
||||
* CheckForGhostWindows.
|
||||
*/
|
||||
void CheckForGhostWindowsCallback();
|
||||
|
||||
/**
|
||||
* Iterate over all weak window pointers in mDetachedWindows and update our
|
||||
* accounting of which windows meet ghost criterion (2).
|
||||
|
@ -209,6 +205,19 @@ private:
|
|||
*/
|
||||
void CheckForGhostWindows(nsTHashtable<nsUint64HashKey> *aOutGhostIDs = nullptr);
|
||||
|
||||
/**
|
||||
* Eventually do a check for ghost windows, if we haven't done one recently
|
||||
* and we aren't already planning to do one soon.
|
||||
*/
|
||||
void AsyncCheckForGhostWindows();
|
||||
|
||||
/**
|
||||
* Kill the check timer, if it exists.
|
||||
*/
|
||||
void KillCheckTimer();
|
||||
|
||||
static void CheckTimerFired(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
/**
|
||||
* Maps a weak reference to a detached window (nsIWeakReference) to the time
|
||||
* when we observed that the window met ghost criterion (2) above.
|
||||
|
@ -222,9 +231,12 @@ private:
|
|||
nsDataHashtable<nsISupportsHashKey, mozilla::TimeStamp> mDetachedWindows;
|
||||
|
||||
/**
|
||||
* True if we have an asynchronous call to CheckForGhostWindows pending.
|
||||
* Track the last time we ran CheckForGhostWindows(), to avoid running it
|
||||
* too often after a DOM window is detached.
|
||||
*/
|
||||
bool mCheckForGhostWindowsCallbackPending;
|
||||
mozilla::TimeStamp mLastCheckForGhostWindows;
|
||||
|
||||
nsCOMPtr<nsITimer> mCheckTimer;
|
||||
};
|
||||
|
||||
#endif // nsWindowMemoryReporter_h__
|
||||
|
|
Загрузка…
Ссылка в новой задаче