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  }