Пример #1
0
        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;
        }
Пример #2
0
        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);
        }
Пример #7
0
        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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }