private WaitHandle[] SelectWaitMode(WaitHandle[] paranoidModeHandles, WaitHandle[] memoryAvailableHandles) { var memoryInfoResult = MemoryInformation.GetMemoryInfo(); var handles = (memoryInfoResult.AvailableMemory + GetCurrentProcessMemoryMappedShared()).GetValue(SizeUnit.Bytes) < _lowMemoryThreshold * 2 ? paranoidModeHandles : memoryAvailableHandles; return(handles); }
public static Size GetCurrentProcessMemoryMappedShared() { // because we are usually using memory mapped files, we don't want // to account for memory that was loaded into our own working set // but that the OS can discard with no cost (because it can load // the data from disk without needing to write it) var stats = MemoryInformation.MemoryStats(); var sharedMemory = stats.WorkingSet - stats.TotalUnmanagedAllocations - stats.ManagedMemory - stats.MappedTemp; // if this is negative, we'll just ignore this var mappedShared = new Size(Math.Max(0, sharedMemory), SizeUnit.Bytes); return(mappedShared); }
private void SimulateLowMemory() { _simulatedLowMemory.Reset(); LowMemoryState = !LowMemoryState; var memInfoForLog = MemoryInformation.GetMemoryInfo(); var availableMemForLog = memInfoForLog.AvailableMemory.GetValue(SizeUnit.Bytes); AddLowMemEvent(LowMemoryState ? LowMemReason.LowMemStateSimulation : LowMemReason.BackToNormalSimulation, availableMemForLog, -2, memInfoForLog.TotalPhysicalMemory.GetValue(SizeUnit.Bytes), memInfoForLog.CurrentCommitCharge.GetValue(SizeUnit.Bytes)); if (_logger.IsInfoEnabled) { _logger.Info("Simulating : " + (LowMemoryState ? "Low memory event" : "Back to normal memory usage")); } RunLowMemoryHandlers(LowMemoryState); }
private void MonitorMemoryUsage() { NativeMemory.EnsureRegistered(); int clearInactiveHandlersCounter = 0; var memoryAvailableHandles = new WaitHandle[] { _simulatedLowMemory, _shutdownRequested }; var paranoidModeHandles = new WaitHandle[] { _simulatedLowMemory, _shutdownRequested, _warnAllocation }; var timeout = 5 * 1000; while (true) { long totalUnmanagedAllocations = 0; var handles = SelectWaitMode(paranoidModeHandles, memoryAvailableHandles); switch (WaitHandle.WaitAny(handles, timeout)) { case WaitHandle.WaitTimeout: if (++clearInactiveHandlersCounter > 60) // 5 minutes == WaitAny 5 Secs * 60 { clearInactiveHandlersCounter = 0; ClearInactiveHandlers(); } foreach (var stats in NativeMemory.ThreadAllocations.Values) { if (stats.ThreadInstance.IsAlive == false) { continue; } totalUnmanagedAllocations += stats.TotalAllocated; } var memInfo = MemoryInformation.GetMemoryInfo(); var currentProcessMemoryMappedShared = GetCurrentProcessMemoryMappedShared(); var availableMem = (memInfo.AvailableMemory + currentProcessMemoryMappedShared).GetValue(SizeUnit.Bytes); if (availableMem < _lowMemoryThreshold && // at all times, we want 2% or 1 GB, the lowest of the two memInfo.AvailableMemory < Size.Min((memInfo.TotalPhysicalMemory / 50), new Size(1, SizeUnit.Gigabytes))) { if (LowMemoryState == false) { if (_logger.IsInfoEnabled) { _logger.Info("Low memory detected, will try to reduce memory usage..."); } AddLowMemEvent(LowMemReason.LowMemOnTimeoutChk, availableMem, totalUnmanagedAllocations, memInfo.TotalPhysicalMemory.GetValue(SizeUnit.Bytes)); } LowMemoryState = true; clearInactiveHandlersCounter = 0; RunLowMemoryHandlers(true); timeout = 500; } else { if (LowMemoryState) { if (_logger.IsInfoEnabled) { _logger.Info("Back to normal memory usage detected"); } AddLowMemEvent(LowMemReason.BackToNormal, availableMem, totalUnmanagedAllocations, memInfo.TotalPhysicalMemory.GetValue(SizeUnit.Bytes)); } LowMemoryState = false; RunLowMemoryHandlers(false); timeout = availableMem < _lowMemoryThreshold * 2 ? 1000 : 5000; } break; case 0: _simulatedLowMemory.Reset(); LowMemoryState = !LowMemoryState; var memInfoForLog = MemoryInformation.GetMemoryInfo(); var availableMemForLog = memInfoForLog.AvailableMemory.GetValue(SizeUnit.Bytes); AddLowMemEvent(LowMemoryState ? LowMemReason.LowMemStateSimulation : LowMemReason.BackToNormalSimulation, availableMemForLog, totalUnmanagedAllocations, memInfoForLog.TotalPhysicalMemory.GetValue(SizeUnit.Bytes)); if (_logger.IsInfoEnabled) { _logger.Info("Simulating : " + (LowMemoryState ? "Low memory event" : "Back to normal memory usage")); } RunLowMemoryHandlers(LowMemoryState); break; case 2: // check allocations _warnAllocation.Reset(); goto case WaitHandle.WaitTimeout; case 1: // shutdown requested return; default: return; } } }
private void MonitorMemoryUsage() { NativeMemory.EnsureRegistered(); int clearInactiveHandlersCounter = 0; var memoryAvailableHandles = new WaitHandle[] { _simulatedLowMemory, _shutdownRequested }; var paranoidModeHandles = new WaitHandle[] { _simulatedLowMemory, _shutdownRequested, _warnAllocation }; var timeout = 5 * 1000; long totalUnmanagedAllocations = 0; while (true) { var handles = MemoryInformation.GetMemoryInfo().AvailableMemory.GetValue(SizeUnit.Bytes) < _lowMemoryThreshold * 2 ? paranoidModeHandles : memoryAvailableHandles; switch (WaitHandle.WaitAny(handles, timeout)) { case WaitHandle.WaitTimeout: if (++clearInactiveHandlersCounter > 60) // 5 minutes == WaitAny 5 Secs * 60 { clearInactiveHandlersCounter = 0; ClearInactiveHandlers(); } foreach (var stats in NativeMemory.ThreadAllocations.Values) { if (stats.ThreadInstance.IsAlive == false) { continue; } totalUnmanagedAllocations += stats.TotalAllocated; } var memInfo = MemoryInformation.GetMemoryInfo(); var availableMem = memInfo.AvailableMemory.GetValue(SizeUnit.Bytes); if (availableMem < _lowMemoryThreshold && totalUnmanagedAllocations > memInfo.TotalPhysicalMemory.GetValue(SizeUnit.Bytes) * _physicalRatioForLowMemDetection) { if (LowMemoryState == false && _logger.IsInfoEnabled) { _logger.Info("Low memory detected, will try to reduce memory usage..."); } LowMemoryState = true; clearInactiveHandlersCounter = 0; RunLowMemoryHandlers(true); timeout = 500; } else { if (LowMemoryState && _logger.IsInfoEnabled) { _logger.Info("Back to normal memory usage detected"); } LowMemoryState = false; RunLowMemoryHandlers(false); timeout = availableMem < _lowMemoryThreshold * 2 ? 1000 : 5000; } break; case 0: _simulatedLowMemory.Reset(); LowMemoryState = !LowMemoryState; if (_logger.IsInfoEnabled) { _logger.Info("Simulating : " + (LowMemoryState ? "Low memory event" : "Back to normal memory usage")); } RunLowMemoryHandlers(LowMemoryState); break; case 2: // check allocations _warnAllocation.Reset(); goto case WaitHandle.WaitTimeout; case 1: // shutdown requested return; default: return; } } }
internal int CheckMemoryStatus(SmapsReader smapsReader) { int timeout; bool isLowMemory; long totalUnmanagedAllocations; (Size AvailableMemory, Size TotalPhysicalMemory, Size CurrentCommitCharge)stats; try { totalUnmanagedAllocations = MemoryInformation.GetUnManagedAllocationsInBytes(); isLowMemory = GetLowMemory(out stats, smapsReader); } catch (OutOfMemoryException) { isLowMemory = true; stats = (new Size(), new Size(), new Size()); totalUnmanagedAllocations = -1; } if (isLowMemory) { if (LowMemoryState == false) { try { if (_logger.IsInfoEnabled) { _logger.Info("Low memory detected, will try to reduce memory usage..."); } AddLowMemEvent(LowMemReason.LowMemOnTimeoutChk, stats.AvailableMemory.GetValue(SizeUnit.Bytes), totalUnmanagedAllocations, stats.TotalPhysicalMemory.GetValue(SizeUnit.Bytes), stats.CurrentCommitCharge.GetValue(SizeUnit.Bytes)); } catch (OutOfMemoryException) { // nothing we can do, we'll wait and try again } } LowMemoryState = true; _clearInactiveHandlersCounter = 0; RunLowMemoryHandlers(true); timeout = 500; } else { if (LowMemoryState) { if (_logger.IsInfoEnabled) { _logger.Info("Back to normal memory usage detected"); } AddLowMemEvent(LowMemReason.BackToNormal, stats.AvailableMemory.GetValue(SizeUnit.Bytes), totalUnmanagedAllocations, stats.TotalPhysicalMemory.GetValue(SizeUnit.Bytes), stats.CurrentCommitCharge.GetValue(SizeUnit.Bytes)); } LowMemoryState = false; RunLowMemoryHandlers(false); timeout = stats.AvailableMemory < _lowMemoryThreshold * 2 ? 1000 : 5000; } return(timeout); }