github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/memsys/pressure.go (about) 1 // Package memsys provides memory management and slab/SGL allocation with io.Reader and io.Writer interfaces 2 // on top of scatter-gather lists of reusable buffers. 3 /* 4 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 5 */ 6 package memsys 7 8 import ( 9 "strconv" 10 11 "github.com/NVIDIA/aistore/sys" 12 ) 13 14 // memory _pressure_ 15 16 const ( 17 PressureLow = iota 18 PressureModerate 19 PressureHigh 20 PressureExtreme 21 OOM 22 ) 23 24 const highLowThreshold = 40 25 26 var memPressureText = map[int]string{ 27 PressureLow: "low", 28 PressureModerate: "moderate", 29 PressureHigh: "high", 30 PressureExtreme: "extreme", 31 OOM: "OOM", 32 } 33 34 // NOTE: used instead of mem.Free as a more realistic estimate where 35 // mem.BuffCache - kernel buffers and page caches that can be reclaimed - 36 // is always included _unless_ the resulting number exceeds mem.ActualFree 37 // (which is unlikely) 38 func memFree(mem *sys.MemStat) (free uint64) { 39 if free = mem.Free + mem.BuffCache; free > mem.ActualFree { 40 free = mem.ActualFree 41 } 42 return 43 } 44 45 // update swapping state 46 func (r *MMSA) updSwap(mem *sys.MemStat) { 47 var ncrit int32 48 swapping, crit := mem.SwapUsed > r.swap.size.Load(), r.swap.crit.Load() 49 if swapping { 50 ncrit = min(swappingMax, crit+1) 51 } else { 52 ncrit = max(0, crit-1) 53 } 54 r.swap.crit.Store(ncrit) 55 r.swap.size.Store(mem.SwapUsed) 56 } 57 58 // returns an estimate for the current memory pressure expressed as enumerated values 59 // also, tracks swapping stateful vars 60 func (r *MMSA) Pressure(mems ...*sys.MemStat) (pressure int) { 61 var mem *sys.MemStat 62 if len(mems) > 0 { 63 mem = mems[0] 64 } else { 65 mem = &sys.MemStat{} 66 _ = mem.Get() 67 } 68 free := memFree(mem) 69 ncrit := r.swap.crit.Load() 70 switch { 71 case ncrit > 2: 72 return OOM 73 case ncrit > 1 || mem.ActualFree <= r.MinFree: 74 return PressureExtreme 75 case ncrit > 0: 76 return PressureHigh 77 case free <= r.MinFree: 78 return PressureHigh 79 case free > r.lowWM+(r.lowWM>>4): 80 return PressureLow 81 } 82 83 pressure = PressureModerate 84 x := (free - r.MinFree) * 100 / (r.lowWM - r.MinFree) 85 if x < highLowThreshold { 86 pressure = PressureHigh 87 } 88 return 89 } 90 91 func (r *MMSA) pressure2S(p int) (sp string) { 92 sp = "pressure '" + memPressureText[p] + "'" 93 if crit := r.swap.crit.Load(); crit > 0 { 94 sp += ", swapping(" + strconv.Itoa(int(crit)) + ")" 95 } 96 return sp 97 }