/// <summary> /// Fires a memory clean up request to those listening. /// </summary> /// <param name="usedMemory"></param> /// <param name="memoryLimit"></param> /// <param name="usedPercentage"></param> public void FireMemoryCleanup(MemoryPressureStates current, MemoryPressureStates old) { try { m_onMemoryCleanUpRequest.Raise(this, new OnMemoryCleanupRequestArgs() { CurrentPressure = current, LastPressure = old } ); } catch (Exception e) { m_baconMan.MessageMan.DebugDia("Memory cleanup fire failed", e); } }
/// <summary> /// Starts the memory thread. /// </summary> public void StartMemoryWatch() { // If we should run. lock(this) { if(_isRunning) { return; } _isRunning = true; } // Kick off a thread. Task.Run(async () => { // Loop forever. while (true) { // Sleep for some time, sleep longer if the memory pressure is lower. int sleepTime; switch(MemoryPressure) { case MemoryPressureStates.None: sleepTime = 500; break; case MemoryPressureStates.VeryLow: sleepTime = 400; break; case MemoryPressureStates.Low: sleepTime = 300; break; case MemoryPressureStates.Medium: case MemoryPressureStates.HighNoAllocations: sleepTime = 100; break; default: throw new ArgumentOutOfRangeException(); } await Task.Delay(sleepTime); // Make sure we aren't stopped. if (!_isRunning) { return; } // Calculate the current memory pressure. var usedMemory = Windows.System.MemoryManager.AppMemoryUsage; var memoryLimit = Windows.System.MemoryManager.AppMemoryUsageLimit; CurrentMemoryUsagePercentage = usedMemory/(double) memoryLimit; // Set the pressure state. var oldPressure = MemoryPressure; if (CurrentMemoryUsagePercentage < CNoneMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.None; } else if (CurrentMemoryUsagePercentage < CVeryLowMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.VeryLow; } else if (CurrentMemoryUsagePercentage < CLowMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.Low; } else if (CurrentMemoryUsagePercentage < CMediumMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.Medium; } else { MemoryPressure = MemoryPressureStates.HighNoAllocations; } // If our new state is higher than our old state if (MemoryPressure > oldPressure) { // We went up a state, Fire the cleanup request since we are at least low. FireMemoryCleanup(MemoryPressure, oldPressure); // Set the count _cleanupTick = 0; } // If our new state is lower than our old state. else if (MemoryPressure < oldPressure) { // We did well, but we can still be at medium or low, reset the counter. _cleanupTick = 0; } else { // Things are the same, if we are low or above take action. if (MemoryPressure >= MemoryPressureStates.Low) { // Count _cleanupTick++; // Get the rollover count. var tickRollover = MemoryPressure == MemoryPressureStates.Low ? CLowTickRollover : CMediumAndHighTickRollover; // Check for roll over if (_cleanupTick > tickRollover) { FireMemoryCleanup(MemoryPressure, oldPressure); _cleanupTick = 0; } } } // For now since this is only used by developer settings, don't bother // if it isn't enabled. if (_nestMan.UiSettingsMan.DeveloperShowMemoryOverlay) { // Check if we need to send a report, we only want to send a report every // 10 ticks so we don't spam too many. Also report if the state changed. _reportTick++; if (_reportTick > 5 || oldPressure != MemoryPressure) { FireMemoryReport(usedMemory, memoryLimit, CurrentMemoryUsagePercentage); _reportTick = 0; } } } }); }
/// <summary> /// Fires a memory clean up request to those listening. /// </summary> /// <param name="current"></param> /// <param name="old"></param> public void FireMemoryCleanup(MemoryPressureStates current, MemoryPressureStates old) { try { _onMemoryCleanUpRequest.Raise(this, new OnMemoryCleanupRequestArgs { CurrentPressure = current, LastPressure = old }); } catch (Exception e) { _nestMan.MessageMan.DebugDia("Memory cleanup fire failed", e); TelemetryManager.ReportUnExpectedEvent(this, "MemeoryCleanupFiredFailed", e); } }
/// <summary> /// Starts the memory thread. /// </summary> public void StartMemoryWatch() { // If we should run. lock (this) { if (m_isRunning) { return; } m_isRunning = true; } // Kick off a thread. Task.Run(async() => { // Loop forever. while (true) { // Sleep for some time, sleep longer if the memory pressure is lower. int sleepTime = 100; switch (MemoryPressure) { case MemoryPressureStates.None: sleepTime = 500; break; case MemoryPressureStates.Low: sleepTime = 300; break; case MemoryPressureStates.Medium: case MemoryPressureStates.HighNoAllocations: sleepTime = 100; break; } await Task.Delay(sleepTime); // Make sure we aren't stopped. if (!m_isRunning) { return; } // Calculate the current memory pressure. ulong usedMemory = Windows.System.MemoryManager.AppMemoryUsage; ulong memoryLimit = Windows.System.MemoryManager.AppMemoryUsageLimit; CurrentMemoryUsagePercentage = (double)usedMemory / (double)memoryLimit; // Set the pressure state. MemoryPressureStates oldPressure = MemoryPressure; if (CurrentMemoryUsagePercentage < c_noneMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.None; } else if (CurrentMemoryUsagePercentage < c_veryLowMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.VeryLow; } else if (CurrentMemoryUsagePercentage < c_lowMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.Low; } else if (CurrentMemoryUsagePercentage < c_mediumMemoryPressueLimit) { MemoryPressure = MemoryPressureStates.Medium; } else { MemoryPressure = MemoryPressureStates.HighNoAllocations; } // If our new state is higher than our old state if (MemoryPressure > oldPressure) { // We went up a state, Fire the cleanup request since we are at least low. FireMemoryCleanup(MemoryPressure, oldPressure); // Set the count m_cleanupTick = 0; } // If our new state is lower than our old state. else if (MemoryPressure < oldPressure) { // We did well, but we can still be at medium or low, reset the counter. m_cleanupTick = 0; } else { // Things are the same, if we are low or above take action. if (MemoryPressure >= MemoryPressureStates.Low) { // Count m_cleanupTick++; // Get the rollover count. int tickRollover = MemoryPressure == MemoryPressureStates.Low ? c_lowTickRollover : c_mediumAndHighTickRollover; // Check for roll over if (m_cleanupTick > tickRollover) { FireMemoryCleanup(MemoryPressure, oldPressure); m_cleanupTick = 0; } } } // For now since this is only used by developer settings, don't bother // if it isn't enabled. if (m_baconMan.UiSettingsMan.Developer_ShowMemoryOverlay) { // Check if we need to send a report, we only want to send a report every // 10 ticks so we don't spam too many. Also report if the state changed. m_reportTick++; if (m_reportTick > 5 || oldPressure != MemoryPressure) { FireMemoryReport(usedMemory, memoryLimit, CurrentMemoryUsagePercentage); m_reportTick = 0; } } } }); }