internal CacheMemoryStats() { // global memory information UnsafeNativeMethods.MEMORYSTATUSEX memoryStatusEx = new UnsafeNativeMethods.MEMORYSTATUSEX(); memoryStatusEx.Init(); if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatusEx) == 0) { return; } _totalMemory = Math.Min(memoryStatusEx.ullTotalPhys, memoryStatusEx.ullTotalVirtual); // More actual physical memory on this machine means bigger _pressureHigh and _pressureLow _pressureHigh = (int)(Math.Max(MIN_PHYSICAL_MEMORY_HIGH_PRESSURE, (_totalMemory - MIN_FREE_PHYSICAL_MEMORY) * 100 / _totalMemory)); _pressureLow = (int)(Math.Max(MIN_PHYSICAL_MEMORY_LOW_PRESSURE, (_totalMemory - MAX_FREE_PHYSICAL_MEMORY) * 100 / _totalMemory)); // per-process information if (UnsafeNativeMethods.GetModuleHandle(ModName.WP_FULL_NAME) != IntPtr.Zero) { _memoryLimit = UnsafeNativeMethods.PMGetMemoryLimitInMB() << MEGABYTE_SHIFT; } else if (UnsafeNativeMethods.GetModuleHandle(ModName.W3WP_FULL_NAME) != IntPtr.Zero) { _memoryLimit = UnsafeNativeMethods.GetW3WPMemoryLimitInKB() << KILOBYTE_SHIFT; } if (_memoryLimit != 0) { _pid = (uint)SafeNativeMethods.GetCurrentProcessId(); // More actual physical memory on this machine means bigger privateBytesPressureHigh and privateBytesPressureLow int privateBytesPressureHigh = (int)(Math.Max(MIN_PRIVATE_BYTES_HIGH_PRESSURE, (_memoryLimit - MIN_FREE_PRIVATE_BYTES) * 100 / _memoryLimit)); int privateBytesPressureLow = (int)(Math.Max(MIN_PRIVATE_BYTES_LOW_PRESSURE, (_memoryLimit - MAX_FREE_PRIVATE_BYTES) * 100 / _memoryLimit)); privateBytesPressureHigh = (int)(Math.Min(PRIVATE_BYTES_CAP, privateBytesPressureHigh)); if (privateBytesPressureLow > privateBytesPressureHigh) { privateBytesPressureLow = privateBytesPressureHigh * PRIVATE_LOW_PRESSURE_RATIO / 100; } _pressureHigh = Math.Min(_pressureHigh, privateBytesPressureHigh); _pressureLow = Math.Min(_pressureLow, privateBytesPressureLow); } Debug.Assert(_pressureHigh > 0, "_pressureHigh > 0"); Debug.Assert(_pressureLow > 0, "_pressureLow > 0"); _pressureMiddle = (_pressureLow + _pressureHigh) / 2; // init history int pressure = GetCurrentPressure(); _pressureHist = new int[HISTORY_COUNT]; for (int i = 0; i < HISTORY_COUNT; i++) { _pressureHist[i] = pressure; _pressureTotal += pressure; } _pressureAvg = pressure; }
int GetCurrentPressure() { UnsafeNativeMethods.MEMORYSTATUSEX memoryStatusEx = new UnsafeNativeMethods.MEMORYSTATUSEX(); memoryStatusEx.Init(); if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatusEx) == 0) { return(0); } // scale down the ratio if the gc is taking less than 1/4 of the physical memory long gcSize = System.GC.GetTotalMemory(false); int gcLoad = (int)((100 * gcSize) / _totalMemory); gcLoad = Math.Min(4 * gcLoad, 100); int pressure = (gcLoad * memoryStatusEx.dwMemoryLoad) / 100; if (_memoryLimit != 0) { int hr; uint privatePageCount = 0; uint dummy; long privateBytes; hr = UnsafeNativeMethods.GetProcessMemoryInformation(_pid, out privatePageCount, out dummy, 1); if (hr == 0) { privateBytes = (long)privatePageCount << MEGABYTE_SHIFT; int privateBytePressure = (int)((privateBytes * 100 / _memoryLimit)); pressure = Math.Max(pressure, privateBytePressure); } } return(pressure); }
internal static void Check(int minFreeMemoryPercentage) { if ((minFreeMemoryPercentage >= 1) && (minFreeMemoryPercentage <= 0x63)) { UnsafeNativeMethods.MEMORYSTATUSEX memoryStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); GetGlobalMemoryStatus(ref memoryStatus); ulong num = (memoryStatus.ullTotalPageFile / ((ulong)100L)) * minFreeMemoryPercentage; if (memoryStatus.ullAvailPageFile < num) { Thread.Sleep(0); uint sizeToAlloc = 0; if (num < 0x7fffffffL) { sizeToAlloc = (((uint)num) / 2) * 3; } if (sizeToAlloc > 0) { ForcePageFileToGrow(sizeToAlloc); GetGlobalMemoryStatus(ref memoryStatus); num = (memoryStatus.ullTotalPageFile / ((ulong)100L)) * minFreeMemoryPercentage; } if (memoryStatus.ullAvailPageFile < num) { throw FxTrace.Exception.AsError(new InsufficientMemoryException(System.ServiceModel.Activation.SR.Hosting_MemoryGatesCheckFailed(memoryStatus.ullAvailPageFile, minFreeMemoryPercentage))); } } } }
private static void GetGlobalMemoryStatus(ref UnsafeNativeMethods.MEMORYSTATUSEX memoryStatus) { memoryStatus.dwLength = (uint)Marshal.SizeOf(typeof(UnsafeNativeMethods.MEMORYSTATUSEX)); if (!UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatus)) { int error = Marshal.GetLastWin32Error(); throw FxTrace.Exception.AsError(new InvalidOperationException(System.ServiceModel.Activation.SR.Hosting_GetGlobalMemoryFailed, new Win32Exception(error))); } }
static CacheMemoryPressure() { UnsafeNativeMethods.MEMORYSTATUSEX memoryStatusEx = new UnsafeNativeMethods.MEMORYSTATUSEX(); memoryStatusEx.Init(); if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatusEx) != 0) { s_totalPhysical = memoryStatusEx.ullTotalPhys; s_totalVirtual = memoryStatusEx.ullTotalVirtual; } }
protected override int GetCurrentPressure() { UnsafeNativeMethods.MEMORYSTATUSEX memoryStatusEx = new UnsafeNativeMethods.MEMORYSTATUSEX(); memoryStatusEx.Init(); if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatusEx) == 0) { return(0); } int dwMemoryLoad = memoryStatusEx.dwMemoryLoad; if (base._pressureHigh != 0) { PerfCounters.SetCounter(AppPerfCounter.CACHE_PERCENT_MACH_MEM_LIMIT_USED, dwMemoryLoad); } return(dwMemoryLoad); }
internal static bool Check(int minFreeMemoryPercentage, bool throwOnLowMemory, out ulong availableMemoryBytes) { // Boundary check percentage, if out of bounds Gate is turned off. // 0 is defined as disabled. Configuration defines 99 as max allowed so we disable // if we receive something out of range availableMemoryBytes = 0; if (minFreeMemoryPercentage < 1 || minFreeMemoryPercentage > 99) { return(true); } UnsafeNativeMethods.MEMORYSTATUSEX memoryStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); GetGlobalMemoryStatus(ref memoryStatus); if (memoryStatus.ullAvailVirtual < (memoryStatus.ullTotalVirtual / 100 * (ulong)minFreeMemoryPercentage)) { availableMemoryBytes = memoryStatus.ullAvailVirtual; } else if (memoryStatus.ullAvailPhys < (memoryStatus.ullTotalPhys / 100 * (ulong)minFreeMemoryPercentage)) { availableMemoryBytes = memoryStatus.ullAvailPhys; } if (TD.ServiceActivationAvailableMemoryIsEnabled()) { TD.ServiceActivationAvailableMemory(availableMemoryBytes); } if (availableMemoryBytes != 0) { if (throwOnLowMemory) { throw FxTrace.Exception.AsError(new InsufficientMemoryException( SR.Hosting_MemoryGatesCheckFailed(availableMemoryBytes, minFreeMemoryPercentage))); } else { return(false); } } return(true); }
override protected int GetCurrentPressure() { UnsafeNativeMethods.MEMORYSTATUSEX memoryStatusEx = new UnsafeNativeMethods.MEMORYSTATUSEX(); memoryStatusEx.Init(); if (UnsafeNativeMethods.GlobalMemoryStatusEx(ref memoryStatusEx) == 0) { return(0); } int memoryLoad = memoryStatusEx.dwMemoryLoad; if (_pressureHigh != 0) { // PerfCounter: Cache Percentage Machine Memory Limit Used // = total physical memory used / total physical memory used limit PerfCounters.SetCounter(AppPerfCounter.CACHE_PERCENT_MACH_MEM_LIMIT_USED, memoryLoad); } return(memoryLoad); }
internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, Int64 offset, Int64 size) { // MapViewOfFile can only create views that start at a multiple of the system memory allocation // granularity. We decided to hide this restriction form the user by creating larger views than the // user requested and hiding the parts that the user did not request. extraMemNeeded is the amount of // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the // capacity of the view to the nearest multiple of the system page size. Once again, we hide this // from the user by preventing them from writing to any memory that they did not request. ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity(); // newOffset takes into account the fact that we have some extra memory allocated before the requested view ulong newOffset = (ulong)offset - extraMemNeeded; Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0"); // determine size to pass to MapViewOfFile ulong nativeSize; if (size != MemoryMappedFile.DefaultSize) { nativeSize = (ulong)size + (ulong)extraMemNeeded; } else { nativeSize = 0; } if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message // "the parameter is incorrect"; this provides better error message in advance UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(memStatus); ulong totalVirtual = memStatus.ullTotalVirtual; if (nativeSize >= totalVirtual) { throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); } // split the Int64 into two ints uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL); uint offsetHigh = (uint)(newOffset >> 32); // create the view SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle, MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // Query the view for its size and allocation type UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); ulong viewSize = (ulong)viewInfo.RegionSize; // allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option if ((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) { IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)viewSize, UnsafeNativeMethods.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); if (viewHandle.IsInvalid) { __Error.WinIOError(lastError, String.Empty); } } // if the user specified DefaultSize as the size, we need to get the actual size if (size == MemoryMappedFile.DefaultSize) { size = (Int64)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access); return(mmv); }
internal unsafe static MemoryMappedView CreateView(SafeMemoryMappedFileHandle memMappedFileHandle, MemoryMappedFileAccess access, Int64 offset, Int64 size) { // MapViewOfFile can only create views that start at a multiple of the system memory allocation // granularity. We decided to hide this restriction form the user by creating larger views than the // user requested and hiding the parts that the user did not request. extraMemNeeded is the amount of // extra memory we allocate before the start of the requested view. MapViewOfFile will also round the // capacity of the view to the nearest multiple of the system page size. Once again, we hide this // from the user by preventing them from writing to any memory that they did not request. ulong extraMemNeeded = (ulong)offset % (ulong)MemoryMappedFile.GetSystemPageAllocationGranularity(); // newOffset takes into account the fact that we have some extra memory allocated before the requested view ulong newOffset = (ulong)offset - extraMemNeeded; Debug.Assert(newOffset >= 0, "newOffset = (offset - extraMemNeeded) < 0"); // determine size to pass to MapViewOfFile ulong nativeSize; if (size != MemoryMappedFile.DefaultSize) { nativeSize = (ulong)size + (ulong)extraMemNeeded; } else { nativeSize = 0; } if (IntPtr.Size == 4 && nativeSize > UInt32.MaxValue) { throw new ArgumentOutOfRangeException("size", SR.GetString(SR.ArgumentOutOfRange_CapacityLargerThanLogicalAddressSpaceNotAllowed)); } // if request is >= than total virtual, then MapViewOfFile will fail with meaningless error message // "the parameter is incorrect"; this provides better error message in advance UnsafeNativeMethods.MEMORYSTATUSEX memStatus = new UnsafeNativeMethods.MEMORYSTATUSEX(); bool result = UnsafeNativeMethods.GlobalMemoryStatusEx(ref memStatus); ulong totalVirtual = memStatus.ullTotalVirtual; if (nativeSize >= totalVirtual) { throw new IOException(SR.GetString(SR.IO_NotEnoughMemory)); } // split the Int64 into two ints uint offsetLow = (uint)(newOffset & 0x00000000FFFFFFFFL); uint offsetHigh = (uint)(newOffset >> 32); // create the view SafeMemoryMappedViewHandle viewHandle = UnsafeNativeMethods.MapViewOfFile(memMappedFileHandle, MemoryMappedFile.GetFileMapAccess(access), offsetHigh, offsetLow, new UIntPtr(nativeSize)); if (viewHandle.IsInvalid) { __Error.WinIOError(Marshal.GetLastWin32Error(), String.Empty); } // Query the view for its size and allocation type UnsafeNativeMethods.MEMORY_BASIC_INFORMATION viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); ulong viewSize = (ulong)viewInfo.RegionSize; // Allocate the pages if we were using the MemoryMappedFileOptions.DelayAllocatePages option // OR check if the allocated view size is smaller than the expected native size // If multiple overlapping views are created over the file mapping object, the pages in a given region // could have different attributes(MEM_RESERVE OR MEM_COMMIT) as MapViewOfFile preserves coherence between // views created on a mapping object backed by same file. // In which case, the viewSize will be smaller than nativeSize required and viewState could be MEM_COMMIT // but more pages may need to be committed in the region. // This is because, VirtualQuery function(that internally invokes VirtualQueryEx function) returns the attributes // and size of the region of pages with matching attributes starting from base address. // VirtualQueryEx: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366907(v=vs.85).aspx if (((viewInfo.State & UnsafeNativeMethods.MEM_RESERVE) != 0) || (viewSize < nativeSize)) { ulong allocSize = (nativeSize == 0) ? viewSize : nativeSize; IntPtr tempHandle = UnsafeNativeMethods.VirtualAlloc(viewHandle, (UIntPtr)allocSize, UnsafeNativeMethods.MEM_COMMIT, MemoryMappedFile.GetPageAccess(access)); int lastError = Marshal.GetLastWin32Error(); // The following is commented out for backward compatibility. // Previously releases failed to check for this error so introducing this check // could cause new/different exceptions in existing code paths. // if (tempHandle == IntPtr.Zero) { // __Error.WinIOError(lastError, String.Empty); // } // again query the view for its new size viewInfo = new UnsafeNativeMethods.MEMORY_BASIC_INFORMATION(); UnsafeNativeMethods.VirtualQuery(viewHandle, ref viewInfo, (IntPtr)Marshal.SizeOf(viewInfo)); viewSize = (ulong)viewInfo.RegionSize; } // if the user specified DefaultSize as the size, we need to get the actual size if (size == MemoryMappedFile.DefaultSize) { size = (Int64)(viewSize - extraMemNeeded); } else { Debug.Assert(viewSize >= (ulong)size, "viewSize < size"); } viewHandle.Initialize((ulong)size + extraMemNeeded); MemoryMappedView mmv = new MemoryMappedView(viewHandle, (long)extraMemNeeded, size, access); return(mmv); }