123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /* -*- Mode: C++; tab-width: 50; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "LoadManager.h"
- #include "LoadMonitor.h"
- #include "nsString.h"
- #include "mozilla/Logging.h"
- #include "prtime.h"
- #include "prinrval.h"
- #include "prsystem.h"
- #include "nsString.h"
- #include "nsThreadUtils.h"
- #include "nsReadableUtils.h"
- #include "nsIObserverService.h"
- #include "mozilla/ArrayUtils.h"
- // MOZ_LOG=LoadManager:5
- mozilla::LazyLogModule gLoadManagerLog("LoadManager");
- #undef LOG
- #undef LOG_ENABLED
- #define LOG(args) MOZ_LOG(gLoadManagerLog, mozilla::LogLevel::Debug, args)
- #define LOG_ENABLED() MOZ_LOG_TEST(gLoadManagerLog, mozilla::LogLevel::Verbose)
- namespace mozilla {
- /* static */ StaticRefPtr<LoadManagerSingleton> LoadManagerSingleton::sSingleton;
- NS_IMPL_ISUPPORTS(LoadManagerSingleton, nsIObserver)
- LoadManagerSingleton::LoadManagerSingleton(bool aEncoderOnly,
- int aLoadMeasurementInterval,
- int aAveragingMeasurements,
- float aHighLoadThreshold,
- float aLowLoadThreshold)
- : mLock("LoadManager"),
- mCurrentState(webrtc::kLoadNormal),
- mOveruseActive(false),
- mLoadSum(0.0f),
- mLoadSumMeasurements(0),
- mLoadMeasurementInterval(aLoadMeasurementInterval),
- mAveragingMeasurements(aAveragingMeasurements),
- mHighLoadThreshold(aHighLoadThreshold),
- mLowLoadThreshold(aLowLoadThreshold)
- {
- LOG(("LoadManager - Initializing (%dms x %d, %f, %f)",
- mLoadMeasurementInterval, mAveragingMeasurements,
- mHighLoadThreshold, mLowLoadThreshold));
- MOZ_ASSERT(mHighLoadThreshold > mLowLoadThreshold);
- if (!aEncoderOnly) {
- mLoadMonitor = new LoadMonitor(mLoadMeasurementInterval);
- mLoadMonitor->Init(mLoadMonitor);
- mLoadMonitor->SetLoadChangeCallback(this);
- }
- mLastStateChange = TimeStamp::Now();
- for (auto &in_state : mTimeInState) {
- in_state = 0;
- }
- }
- LoadManagerSingleton::~LoadManagerSingleton()
- {
- LOG(("LoadManager: shutting down LoadMonitor"));
- MOZ_ASSERT(!mLoadMonitor, "why wasn't the LoadMonitor shut down in xpcom-shutdown?");
- if (mLoadMonitor) {
- mLoadMonitor->Shutdown();
- }
- }
- nsresult
- LoadManagerSingleton::Observe(nsISupports* aSubject, const char* aTopic,
- const char16_t* aData)
- {
- NS_ASSERTION(NS_IsMainThread(), "Observer invoked off the main thread");
- nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
- if (!strcmp(aTopic, "xpcom-shutdown")) {
- obs->RemoveObserver(this, "xpcom-shutdown");
- {
- MutexAutoLock lock(mLock);
- mObservers.Clear();
- }
- if (mLoadMonitor) {
- mLoadMonitor->Shutdown();
- mLoadMonitor = nullptr;
- }
- LOG(("Releasing LoadManager singleton and thread"));
- // Note: won't be released immediately as the Observer has a ref to us
- sSingleton = nullptr;
- }
- return NS_OK;
- }
- void
- LoadManagerSingleton::LoadChanged(float aSystemLoad, float aProcesLoad)
- {
- MutexAutoLock lock(mLock);
- // Update total load, and total amount of measured seconds.
- mLoadSum += aSystemLoad;
- mLoadSumMeasurements++;
- if (mLoadSumMeasurements >= mAveragingMeasurements) {
- double averagedLoad = mLoadSum / (float)mLoadSumMeasurements;
- webrtc::CPULoadState newState = mCurrentState;
- if (mOveruseActive || averagedLoad > mHighLoadThreshold) {
- LOG(("LoadManager - LoadStressed"));
- newState = webrtc::kLoadStressed;
- } else if (averagedLoad < mLowLoadThreshold) {
- LOG(("LoadManager - LoadRelaxed"));
- newState = webrtc::kLoadRelaxed;
- } else {
- LOG(("LoadManager - LoadNormal"));
- newState = webrtc::kLoadNormal;
- }
- if (newState != mCurrentState) {
- LoadHasChanged(newState);
- }
- mLoadSum = 0;
- mLoadSumMeasurements = 0;
- }
- }
- void
- LoadManagerSingleton::OveruseDetected()
- {
- LOG(("LoadManager - Overuse Detected"));
- MutexAutoLock lock(mLock);
- mOveruseActive = true;
- if (mCurrentState != webrtc::kLoadStressed) {
- LoadHasChanged(webrtc::kLoadStressed);
- }
- }
- void
- LoadManagerSingleton::NormalUsage()
- {
- LOG(("LoadManager - Overuse finished"));
- MutexAutoLock lock(mLock);
- mOveruseActive = false;
- }
- void
- LoadManagerSingleton::LoadHasChanged(webrtc::CPULoadState aNewState)
- {
- mLock.AssertCurrentThreadOwns();
- LOG(("LoadManager - Signaling LoadHasChanged from %d to %d to %d listeners",
- mCurrentState, aNewState, mObservers.Length()));
- // Record how long we spent in this state for later Telemetry or display
- TimeStamp now = TimeStamp::Now();
- mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
- mLastStateChange = now;
- mCurrentState = aNewState;
- for (size_t i = 0; i < mObservers.Length(); i++) {
- mObservers.ElementAt(i)->onLoadStateChanged(mCurrentState);
- }
- }
- void
- LoadManagerSingleton::AddObserver(webrtc::CPULoadStateObserver * aObserver)
- {
- LOG(("LoadManager - Adding Observer"));
- MutexAutoLock lock(mLock);
- mObservers.AppendElement(aObserver);
- }
- void
- LoadManagerSingleton::RemoveObserver(webrtc::CPULoadStateObserver * aObserver)
- {
- LOG(("LoadManager - Removing Observer"));
- MutexAutoLock lock(mLock);
- if (!mObservers.RemoveElement(aObserver)) {
- LOG(("LoadManager - Element to remove not found"));
- }
- if (mObservers.Length() == 0) {
- // Record how long we spent in the final state for later Telemetry or display
- TimeStamp now = TimeStamp::Now();
- mTimeInState[mCurrentState] += (now - mLastStateChange).ToMilliseconds();
- float total = 0;
- for (size_t i = 0; i < MOZ_ARRAY_LENGTH(mTimeInState); i++) {
- total += mTimeInState[i];
- }
- for (auto &in_state : mTimeInState) {
- in_state = 0;
- }
- if (mLoadMonitor) {
- // Dance to avoid deadlock on mLock!
- RefPtr<LoadMonitor> loadMonitor = mLoadMonitor.forget();
- MutexAutoUnlock unlock(mLock);
- loadMonitor->Shutdown();
- }
- }
- }
- }
|