зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1382254
- Only disallow budget throttling. r=ehsan
Don't consider WebSockets, IndexedDB, etc when considering background tabs for ordinary throttling since that makes us throttle way less than we used to.
This commit is contained in:
Родитель
8aab64fd68
Коммит
4a297f87de
|
@ -10,6 +10,7 @@
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
#include "mozilla/ThrottledEventQueue.h"
|
#include "mozilla/ThrottledEventQueue.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
#include "nsIDocShell.h"
|
||||||
#include "nsITimeoutHandler.h"
|
#include "nsITimeoutHandler.h"
|
||||||
#include "mozilla/dom/TabGroup.h"
|
#include "mozilla/dom/TabGroup.h"
|
||||||
#include "OrderedTimeoutIterator.h"
|
#include "OrderedTimeoutIterator.h"
|
||||||
|
@ -107,10 +108,6 @@ TimeoutManager::IsActive() const
|
||||||
// A window is considered active if:
|
// A window is considered active if:
|
||||||
// * It is a chrome window
|
// * It is a chrome window
|
||||||
// * It is playing audio
|
// * It is playing audio
|
||||||
// * If it is using user media
|
|
||||||
// * If it is using WebRTC
|
|
||||||
// * If it has open WebSockets
|
|
||||||
// * If it has active IndexedDB databases
|
|
||||||
//
|
//
|
||||||
// Note that a window can be considered active if it is either in the
|
// Note that a window can be considered active if it is either in the
|
||||||
// foreground or in the background.
|
// foreground or in the background.
|
||||||
|
@ -124,45 +121,6 @@ TimeoutManager::IsActive() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there are any active IndexedDB databases
|
|
||||||
if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we have active GetUserMedia
|
|
||||||
if (MediaManager::Exists() &&
|
|
||||||
MediaManager::Get()->IsWindowStillActive(mWindow.WindowID())) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool active = false;
|
|
||||||
#if 0
|
|
||||||
// Check if we have active PeerConnections This doesn't actually
|
|
||||||
// work, since we sometimes call IsActive from Resume, which in turn
|
|
||||||
// is sometimes called from nsGlobalWindow::LeaveModalState. The
|
|
||||||
// problem here is that LeaveModalState can be called with pending
|
|
||||||
// exeptions on the js context, and the following call to
|
|
||||||
// HasActivePeerConnection is a JS call, which will assert on that
|
|
||||||
// exception. Also, calling JS is expensive so we should try to fix
|
|
||||||
// this in some other way.
|
|
||||||
nsCOMPtr<IPeerConnectionManager> pcManager =
|
|
||||||
do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID);
|
|
||||||
|
|
||||||
if (pcManager && NS_SUCCEEDED(pcManager->HasActivePeerConnection(
|
|
||||||
mWindow.WindowID(), &active)) &&
|
|
||||||
active) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif // MOZ_WEBRTC
|
|
||||||
|
|
||||||
// Check if we have web sockets
|
|
||||||
RefPtr<WebSocketEventService> eventService = WebSocketEventService::Get();
|
|
||||||
if (eventService &&
|
|
||||||
NS_SUCCEEDED(eventService->HasListenerFor(mWindow.WindowID(), &active)) &&
|
|
||||||
active) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +204,7 @@ TimeoutManager::MinSchedulingDelay() const
|
||||||
TimeDuration unthrottled =
|
TimeDuration unthrottled =
|
||||||
isBackground ? TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)
|
isBackground ? TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)
|
||||||
: TimeDuration();
|
: TimeDuration();
|
||||||
if (mBudgetThrottleTimeouts && mExecutionBudget < TimeDuration()) {
|
if (BudgetThrottlingEnabled() && mExecutionBudget < TimeDuration()) {
|
||||||
// Only throttle if execution budget is less than 0
|
// Only throttle if execution budget is less than 0
|
||||||
double factor = 1.0 / GetRegenerationFactor(mWindow.IsBackgroundInternal());
|
double factor = 1.0 / GetRegenerationFactor(mWindow.IsBackgroundInternal());
|
||||||
return TimeDuration::Min(
|
return TimeDuration::Min(
|
||||||
|
@ -373,7 +331,7 @@ TimeoutManager::UpdateBudget(const TimeStamp& aNow, const TimeDuration& aDuratio
|
||||||
// window is active or not. If throttling is enabled and the window
|
// window is active or not. If throttling is enabled and the window
|
||||||
// is active and then becomes inactive, an overdrawn budget will
|
// is active and then becomes inactive, an overdrawn budget will
|
||||||
// still be counted against the minimum delay.
|
// still be counted against the minimum delay.
|
||||||
if (mBudgetThrottleTimeouts) {
|
if (BudgetThrottlingEnabled()) {
|
||||||
bool isBackground = mWindow.IsBackgroundInternal();
|
bool isBackground = mWindow.IsBackgroundInternal();
|
||||||
double factor = GetRegenerationFactor(isBackground);
|
double factor = GetRegenerationFactor(isBackground);
|
||||||
TimeDuration regenerated = (aNow - mLastBudgetUpdate).MultDouble(factor);
|
TimeDuration regenerated = (aNow - mLastBudgetUpdate).MultDouble(factor);
|
||||||
|
@ -1241,6 +1199,66 @@ ThrottleTimeoutsCallback::Notify(nsITimer* aTimer)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TimeoutManager::BudgetThrottlingEnabled() const
|
||||||
|
{
|
||||||
|
// A window can be throttled using budget if
|
||||||
|
// * It isn't active
|
||||||
|
// * If it isn't using user media
|
||||||
|
// * If it isn't using WebRTC
|
||||||
|
// * If it hasn't got open WebSockets
|
||||||
|
// * If it hasn't got active IndexedDB databases
|
||||||
|
//
|
||||||
|
// Note that we allow both foreground and background to be
|
||||||
|
// considered for budget throttling. What determines if they are if
|
||||||
|
// budget throttling is enabled is the regeneration factor.
|
||||||
|
|
||||||
|
if (!mBudgetThrottleTimeouts || IsActive()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there are any active IndexedDB databases
|
||||||
|
if (mWindow.AsInner()->HasActiveIndexedDBDatabases()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have active GetUserMedia
|
||||||
|
if (MediaManager::Exists() &&
|
||||||
|
MediaManager::Get()->IsWindowStillActive(mWindow.WindowID())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool active = false;
|
||||||
|
#if 0
|
||||||
|
// Check if we have active PeerConnections This doesn't actually
|
||||||
|
// work, since we sometimes call IsActive from Resume, which in turn
|
||||||
|
// is sometimes called from nsGlobalWindow::LeaveModalState. The
|
||||||
|
// problem here is that LeaveModalState can be called with pending
|
||||||
|
// exeptions on the js context, and the following call to
|
||||||
|
// HasActivePeerConnection is a JS call, which will assert on that
|
||||||
|
// exception. Also, calling JS is expensive so we should try to fix
|
||||||
|
// this in some other way.
|
||||||
|
nsCOMPtr<IPeerConnectionManager> pcManager =
|
||||||
|
do_GetService(IPEERCONNECTION_MANAGER_CONTRACTID);
|
||||||
|
|
||||||
|
if (pcManager && NS_SUCCEEDED(pcManager->HasActivePeerConnection(
|
||||||
|
mWindow.WindowID(), &active)) &&
|
||||||
|
active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // MOZ_WEBRTC
|
||||||
|
|
||||||
|
// Check if we have web sockets
|
||||||
|
RefPtr<WebSocketEventService> eventService = WebSocketEventService::Get();
|
||||||
|
if (eventService &&
|
||||||
|
NS_SUCCEEDED(eventService->HasListenerFor(mWindow.WindowID(), &active)) &&
|
||||||
|
active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimeoutManager::StartThrottlingTimeouts()
|
TimeoutManager::StartThrottlingTimeouts()
|
||||||
{
|
{
|
||||||
|
|
|
@ -148,6 +148,8 @@ private:
|
||||||
void UpdateBudget(const TimeStamp& aNow,
|
void UpdateBudget(const TimeStamp& aNow,
|
||||||
const TimeDuration& aDuration = TimeDuration());
|
const TimeDuration& aDuration = TimeDuration());
|
||||||
|
|
||||||
|
bool BudgetThrottlingEnabled() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Timeouts {
|
struct Timeouts {
|
||||||
explicit Timeouts(const TimeoutManager& aManager)
|
explicit Timeouts(const TimeoutManager& aManager)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче