author | Justin Lebar <justin.lebar@gmail.com> |
Wed, 27 Feb 2013 14:28:57 -0500 | |
changeset 123201 | d5cba11c8204b1edb64e62fdb95e11e727b8a424 |
parent 123200 | f3476411480a383c84e017a99af2f9222cd5ab77 |
child 123202 | 7a79ddc7bedf213d15b67f052c7bb06d36fd275d |
push id | 24373 |
push user | ryanvm@gmail.com |
push date | Thu, 28 Feb 2013 01:36:21 +0000 |
treeherder | mozilla-central@8cb9d6981978 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cjones |
bugs | 844970 |
milestone | 22.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/ipc/ProcessPriorityManager.cpp +++ b/dom/ipc/ProcessPriorityManager.cpp @@ -90,27 +90,16 @@ GetContentChildID() if (!contentChild) { return 0; } return contentChild->GetID(); } /** - * Determine if the priority is a backround priority. - */ -bool -IsBackgroundPriority(ProcessPriority aPriority) -{ - return (aPriority == PROCESS_PRIORITY_BACKGROUND || - aPriority == PROCESS_PRIORITY_BACKGROUND_HOMESCREEN || - aPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE); -} - -/** * This class listens to various Gecko events and asks the hal back-end to * change this process's priority when it transitions between various states of * "importance". * * The process's priority determines its CPU priority and also how likely it is * to be killed when the system is running out of memory. * * The most basic dichotomy in the ProcessPriorityManager is between @@ -156,31 +145,22 @@ public: * ProcessPriorityManager.h::TemporarilyLockProcessPriority(). */ void TemporarilyLockProcessPriority(); /** * Recompute this process's priority and apply it, potentially after a brief * delay. * - * If we are transitioning to a priority that is "lower" than the current - * priority (as defined below), that transition happens after a grace period. - * Otherwise the transition happens immediately. - * - * For the purposes of deciding whether to apply a grace period, the - * hierarchy of priorities is + * If we are transitioning to a priority that is lower than the current + * priority, that transition happens after a grace period. Otherwise the + * transition happens immediately. * - * - UNKNOWN - * - FOREGROUND_HIGH - * - FOREGROUND - * - BACKGROUND* - * - * So for example, a transition between any two BACKGROUND* priorites happens - * immediately, but a transition from UNKNOWN to FOREGROUND_HIGH happens - * after a grace period. + * Note that PROCESS_PRIORITY_UNKNOWN is considered the highest priority. + * Going from UNKNOWN to any other priority requires a grace period. */ void ResetPriority(); /** * Recompute this process's priority and apply it immediately. */ void ResetPriorityNow(); @@ -189,57 +169,37 @@ private: /** * Is this process a "critical" process that's holding the "CPU" or * "high-priority" wake lock? */ bool IsCriticalProcessWithWakeLock(); /** - * If this process were in the foreground, what priority would it have? - */ - ProcessPriority GetForegroundPriority(); - - /** - * If this process were in the foreground, what priority would it have? - */ - ProcessPriority GetBackgroundPriority(); - - /** * Compute whether this process is in the foreground and return the result. */ bool ComputeIsInForeground(); - /** - * Set this process's priority to the appropriate FOREGROUND* priority - * immediately if we're upgrading its priority, and after a grace period if - * we're downgrading it or if the current priority is unknown. + * Compute the priority this process ought to have, based on what we know at + * the moment. */ - void SetIsForeground(); + ProcessPriority ComputePriority(); /** - * Set this process's priority to the appropriate FOREGROUND* priority - * immediately. + * Immediately set this process's priority to the given priority. */ - void SetIsForegroundNow(); - - /** - * Set this process's priority to the appropriate BACKGROUND* priority - * immediately. - */ - void SetIsBackgroundNow(); + void SetPriorityNow(ProcessPriority aPriority); /** * If mResetPriorityTimer is null (i.e., not running), create a timer and set * it to invoke ResetPriorityNow() after * dom.ipc.processPriorityManager.aTimeoutPref ms. */ - void - ScheduleResetPriority(const char* aTimeoutPref); + void ScheduleResetPriority(const char* aTimeoutPref); // Tracks whether this process holds the "cpu" lock. bool mHoldsCPUWakeLock; // Tracks whether this process holds the "high-priority" lock. bool mHoldsHighPriorityWakeLock; // mProcessPriority tracks the priority we've given this process in hal. @@ -425,90 +385,45 @@ ProcessPriorityManager::IsCriticalProces if (appType.EqualsLiteral("critical")) { return true; } } return false; } -ProcessPriority -ProcessPriorityManager::GetForegroundPriority() -{ - return IsCriticalProcessWithWakeLock() ? PROCESS_PRIORITY_FOREGROUND_HIGH : - PROCESS_PRIORITY_FOREGROUND; -} - -/** - * Get the appropriate backround priority for this process. - */ -ProcessPriority -ProcessPriorityManager::GetBackgroundPriority() -{ - AudioChannelService* service = AudioChannelService::GetAudioChannelService(); - if (service->ContentOrNormalChannelIsActive()) { - return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE; - } - - bool isHomescreen = false; - - ContentChild* contentChild = ContentChild::GetSingleton(); - if (contentChild) { - const InfallibleTArray<PBrowserChild*>& browsers = - contentChild->ManagedPBrowserChild(); - for (uint32_t i = 0; i < browsers.Length(); i++) { - nsAutoString appType; - static_cast<TabChild*>(browsers[i])->GetAppType(appType); - if (appType.EqualsLiteral("homescreen")) { - isHomescreen = true; - break; - } - } - } - - return isHomescreen ? - PROCESS_PRIORITY_BACKGROUND_HOMESCREEN : - PROCESS_PRIORITY_BACKGROUND; -} - - void ProcessPriorityManager::ResetPriority() { if (!mObservedTabChildCreated) { LOG("ResetPriority bailing because we haven't observed " "a tab-child-created event."); return; } - if (ComputeIsInForeground()) { - SetIsForeground(); - } else if (IsBackgroundPriority(mProcessPriority)) { - // If we're already in the background, recompute our background priority - // and set it immediately. - SetIsBackgroundNow(); - } else { + ProcessPriority processPriority = ComputePriority(); + if (mProcessPriority == PROCESS_PRIORITY_UNKNOWN || + mProcessPriority > processPriority) { ScheduleResetPriority("backgroundGracePeriodMS"); + return; } + + SetPriorityNow(processPriority); } void ProcessPriorityManager::ResetPriorityNow() { if (!mObservedTabChildCreated) { LOG("ResetPriorityNow bailing because we haven't observed " "a tab-child-created event."); return; } - if (ComputeIsInForeground()) { - SetIsForegroundNow(); - } else { - SetIsBackgroundNow(); - } + SetPriorityNow(ComputePriority()); } bool ProcessPriorityManager::ComputeIsInForeground() { // Critical processes holding the CPU/high-priority wake lock are always // considered to be in the foreground. if (IsCriticalProcessWithWakeLock()) { @@ -554,79 +469,94 @@ ProcessPriorityManager::ComputeIsInForeg // We could break out early from this loop if // isActive && mProcessPriority == BACKGROUND, // but then we might not clean up all the weak refs. } return !allHidden; } -void -ProcessPriorityManager::SetIsForeground() +ProcessPriority +ProcessPriorityManager::ComputePriority() { - ProcessPriority foregroundPriority = GetForegroundPriority(); + if (ComputeIsInForeground()) { + if (IsCriticalProcessWithWakeLock()) { + return PROCESS_PRIORITY_FOREGROUND_HIGH; + } + return PROCESS_PRIORITY_FOREGROUND; + } + + AudioChannelService* service = AudioChannelService::GetAudioChannelService(); + if (service->ContentOrNormalChannelIsActive()) { + return PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE; + } + + bool isHomescreen = false; - if (mProcessPriority == PROCESS_PRIORITY_UNKNOWN || - foregroundPriority < mProcessPriority) { - LOG("Giving grace period to %s -> %s transition.", - ProcessPriorityToString(mProcessPriority), - ProcessPriorityToString(foregroundPriority)); - ScheduleResetPriority("backgroundGracePeriodMS"); - } else { - SetIsForegroundNow(); + ContentChild* contentChild = ContentChild::GetSingleton(); + if (contentChild) { + const InfallibleTArray<PBrowserChild*>& browsers = + contentChild->ManagedPBrowserChild(); + for (uint32_t i = 0; i < browsers.Length(); i++) { + nsAutoString appType; + static_cast<TabChild*>(browsers[i])->GetAppType(appType); + if (appType.EqualsLiteral("homescreen")) { + isHomescreen = true; + break; + } + } } + + return isHomescreen ? + PROCESS_PRIORITY_BACKGROUND_HOMESCREEN : + PROCESS_PRIORITY_BACKGROUND; } void -ProcessPriorityManager::SetIsForegroundNow() +ProcessPriorityManager::SetPriorityNow(ProcessPriority aPriority) { - ProcessPriority foregroundPriority = GetForegroundPriority(); - if (foregroundPriority == mProcessPriority) { + if (aPriority == PROCESS_PRIORITY_UNKNOWN) { + MOZ_ASSERT(false); return; } - // Cancel the memory minimization procedure we might have started. - nsCOMPtr<nsICancelableRunnable> runnable = - do_QueryReferent(mMemoryMinimizerRunnable); - if (runnable) { - runnable->Cancel(); - } - - mProcessPriority = foregroundPriority; - LOG("Setting priority to %s.", ProcessPriorityToString(mProcessPriority)); - hal::SetProcessPriority(getpid(), mProcessPriority); -} - -void -ProcessPriorityManager::SetIsBackgroundNow() -{ - ProcessPriority backgroundPriority = GetBackgroundPriority(); - if (mProcessPriority == backgroundPriority) { + if (mProcessPriority == aPriority) { return; } - mProcessPriority = backgroundPriority; - LOG("Setting priority to %s", ProcessPriorityToString(mProcessPriority)); + LOG("Changing priority from %s to %s.", + ProcessPriorityToString(mProcessPriority), + ProcessPriorityToString(aPriority)); + mProcessPriority = aPriority; hal::SetProcessPriority(getpid(), mProcessPriority); - // We're in the background; dump as much memory as we can. - nsCOMPtr<nsIMemoryReporterManager> mgr = - do_GetService("@mozilla.org/memory-reporter-manager;1"); - if (mgr) { + if (aPriority >= PROCESS_PRIORITY_FOREGROUND) { + // Cancel the memory minimization procedure we might have started. nsCOMPtr<nsICancelableRunnable> runnable = do_QueryReferent(mMemoryMinimizerRunnable); - - // Cancel the previous task if it's still pending if (runnable) { runnable->Cancel(); } + } else { + // We're in the background; dump as much memory as we can. + nsCOMPtr<nsIMemoryReporterManager> mgr = + do_GetService("@mozilla.org/memory-reporter-manager;1"); + if (mgr) { + nsCOMPtr<nsICancelableRunnable> runnable = + do_QueryReferent(mMemoryMinimizerRunnable); - mgr->MinimizeMemoryUsage(/* callback = */ nullptr, - getter_AddRefs(runnable)); - mMemoryMinimizerRunnable = do_GetWeakReference(runnable); + // Cancel the previous task if it's still pending + if (runnable) { + runnable->Cancel(); + } + + mgr->MinimizeMemoryUsage(/* callback = */ nullptr, + getter_AddRefs(runnable)); + mMemoryMinimizerRunnable = do_GetWeakReference(runnable); + } } } void ProcessPriorityManager::ScheduleResetPriority(const char* aTimeoutPref) { if (mResetPriorityTimer) { LOG("ScheduleResetPriority bailing; the timer is already running.");