| File: System\Runtime\Caching\PhysicalMemoryMonitor.cs | Web Access |
| Project: src\runtime\src\libraries\System.Runtime.Caching\src\System.Runtime.Caching.csproj (System.Runtime.Caching) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Runtime.Caching.Configuration; using System.Runtime.InteropServices; using System.Security; namespace System.Runtime.Caching { // PhysicalMemoryMonitor monitors the amound of physical memory used on the machine // and helps us determine when to drop entries to avoid paging and GC thrashing. // The limit is configurable (see ConfigUtil.cs). internal sealed partial class PhysicalMemoryMonitor : MemoryMonitor { private const int MinTotalMemoryTrimPercent = 10; private const long TargetTotalMemoryTrimIntervalTicks = 5 * TimeSpan.TicksPerMinute; // Returns the percentage of physical machine memory that can be consumed by an // application before the cache starts forcibly removing items. internal long MemoryLimit { get { return _pressureHigh; } } private PhysicalMemoryMonitor() { // hide default ctor } internal PhysicalMemoryMonitor(int physicalMemoryLimitPercentage) { /* The chart below shows physical memory in megabytes, and the 1, 3, and 10% values. When we reach "middle" pressure, we begin trimming the cache. RAM 1% 3% 10% ----------------------------- 128 1.28 3.84 12.8 256 2.56 7.68 25.6 512 5.12 15.36 51.2 1024 10.24 30.72 102.4 2048 20.48 61.44 204.8 4096 40.96 122.88 409.6 8192 81.92 245.76 819.2 */ long memory = TotalPhysical; if (memory >= 0x100000000) { _pressureHigh = 99; } else if (memory >= 0x80000000) { _pressureHigh = 98; } else if (memory >= 0x40000000) { _pressureHigh = 97; } else if (memory >= 0x30000000) { _pressureHigh = 96; } else { _pressureHigh = 95; } _pressureLow = _pressureHigh - 9; SetLimit(physicalMemoryLimitPercentage); InitHistory(); } internal override int GetPercentToTrim(DateTime lastTrimTime, int lastTrimPercent) { int percent = 0; if (IsAboveHighPressure()) { // choose percent such that we don't repeat this for ~5 (TARGET_TOTAL_MEMORY_TRIM_INTERVAL) minutes, // but keep the percentage between 10 and 50. DateTime utcNow = DateTime.UtcNow; long ticksSinceTrim = utcNow.Subtract(lastTrimTime).Ticks; if (ticksSinceTrim > 0) { percent = Math.Min(50, (int)((lastTrimPercent * TargetTotalMemoryTrimIntervalTicks) / ticksSinceTrim)); percent = Math.Max(MinTotalMemoryTrimPercent, percent); } #if PERF Debug.WriteLine($"PhysicalMemoryMonitor.GetPercentToTrim: percent={percent:N}, lastTrimPercent={lastTrimPercent:N}, secondsSinceTrim={ticksSinceTrim/TimeSpan.TicksPerSecond:N}{Environment.NewLine}"); #endif } return percent; } internal void SetLimit(int physicalMemoryLimitPercentage) { if (physicalMemoryLimitPercentage == 0) { // use defaults return; } _pressureHigh = Math.Max(3, physicalMemoryLimitPercentage); _pressureLow = Math.Max(1, _pressureHigh - 9); Dbg.Trace("MemoryCacheStats", $"PhysicalMemoryMonitor.SetLimit: _pressureHigh={_pressureHigh}, _pressureLow={_pressureLow}"); } } }