배포판에서 이식 가능한 메모리 용량을 어떻게 확보 할 수 있습니까?


12

메모리를보고하는 표준 파일 / 도구는 Linux 배포판마다 형식이 다른 것 같습니다. 예를 들어, 아치와 우분투에서.

  • 아치

    $ free
                  total        used        free      shared  buff/cache   available
    Mem:        8169312     3870392     2648348       97884     1650572     4110336
    Swap:      16777212      389588    16387624
    
    
    $ head /proc/meminfo 
    MemTotal:        8169312 kB
    MemFree:         2625668 kB
    MemAvailable:    4088520 kB
    Buffers:          239688 kB
    Cached:          1224520 kB
    SwapCached:        17452 kB
    Active:          4074548 kB
    Inactive:        1035716 kB
    Active(anon):    3247948 kB
    Inactive(anon):   497684 kB
    
  • 우분투

    $ free
                 total       used       free     shared    buffers     cached
    Mem:      80642828   69076080   11566748    3063796     150688   58358264
    -/+ buffers/cache:   10567128   70075700
    Swap:     20971516    5828472   15143044
    
    
    $ head /proc/meminfo 
    MemTotal:       80642828 kB
    MemFree:        11565936 kB
    Buffers:          150688 kB
    Cached:         58358264 kB
    SwapCached:      2173912 kB
    Active:         27305364 kB
    Inactive:       40004480 kB
    Active(anon):    7584320 kB
    Inactive(anon):  4280400 kB
    Active(file):   19721044 kB
    

그렇다면 어떻게 소프트웨어를 특정 시간에 사용할 수있는 스왑을 제외한 메모리 양을 안정적으로 확보하고 (리눅스 배포판에서만) 어떻게 신뢰할 수 있습니까? 아마도 그것은 아치 의 출력 free과 출력에서 "사용 가능"과 "MemAvailable"로 표시 cat /proc/meminfo되지만 우분투 또는 다른 배포판에서 어떻게 동일합니까?

답변:


18

MemAvailable/proc/meminfo커널 3.14 이후 버전에 포함되어 있습니다 . commit 34e431b0a 에 의해 추가되었습니다 . 그것이 당신이 보여주는 출력 변화의 결정 요소입니다. 커밋 메시지는 MemAvailable다음을 수행 하지 않고 사용 가능한 메모리를 추정하는 방법을 나타냅니다 .

현재로 교환 시스템을 누르지 않고, 새로운 작업에 필요한 메모리의 양이 추정 될 수있다 MemFree, Active(file), Inactive(file), 및 SReclaimable,뿐만 아니라 "낮은"워터 마크로부터 /proc/zoneinfo.

낮은 워터 마크는 시스템이 교환 할 수준입니다. 그래서이없는 경우에 MemAvailable당신이 적어도 주어진 값을 추가 할 수 있습니다 MemFree, Active(file), Inactive(file)SReclaimable(현재의입니다 중을 /proc/meminfo),과에서 저 워터 마크를 뺍니다 /proc/zoneinfo. 후자는 또한 영역 당 사용 가능한 페이지 수를 나열하며 비교에 유용 할 수 있습니다.

완전한 알고리즘은 패치에 제공 meminfo.c되며 쉽게 적응할 수 있습니다.

  • 모든 영역에 걸쳐 낮은 워터 마크를 합산하십시오.
  • 식별 된 여유 메모리를 가져옵니다 ( MemFree).
  • 낮은 워터 마크를 빼십시오 (스왑을 피하기 위해 만지지 않아야합니다).
  • 페이지 캐시에서 사용할 수있는 메모리 양을 합산하십시오 (합계 Active(file)Inactive(file)). 즉, 페이지 캐시에서 사용 된 메모리 양에서 페이지 캐시의 절반을 빼거나 낮은 워터 마크 중 작은 쪽입니다.
  • SReclaimable동일한 알고리즘에 따라 회수 할 수있는 메모리 양을 추가하십시오 ( ).

따라서이 모든 것을 종합하면 다음을 통해 새 프로세스에 사용할 수있는 메모리를 얻을 수 있습니다.

awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') \
 '{a[$1]=$2}
  END{ 
   print a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]-(12*low); 
  }' /proc/meminfo 

아, 좋습니다. 적어도 같은 커널 버전에서 이식 할 수 있어야합니다. 그 거에요 awk -v low=$(grep low /proc/zoneinfo | awk '{k+=$2}END{print k}') '{a[$1]=$2}END{m=a["MemFree:"]+a["Active(file):"]+a["Inactive(file):"]+a["SReclaimable:"]; print a["MemAvailable:"],m-low}' /proc/meminfo동일한 번호를 두 번 인쇄 해야하는 제안을 테스트하고 있습니다 . 그러나 두 번째 숫자 (내가 제안한 알고리즘에 대한 이해)는에 MemAvailable표시된 것보다 높습니다 /proc/meminfo. 내가 무엇을 잘못하고 있지?
terdon

2
/proc/zoneinfo크기가 4KB 인 페이지를 계산합니다 amd64. 또한 페이지 캐시 및 회수 가능한 메모리에 추가 된 추가 안전 기능이 없습니다. 후자를 단순화하면 낮은 워터 마크를 세 번 빼서 m-12*low(3 × 4KB) 시스템에 올바른 결과를 제공합니다. (이 단순화는 페이지 캐시 또는 회수 가능한 메모리가 낮은 워터 마크의 두 배보다 작은 경우 사용 가능한 메모리를 과소 평가하지만, 그 상황에서 메모리를 많이 사용하고 싶지 않아 합리적인 타협으로 보일 수 있습니다.)
Stephen Kitt

1
@StephenKitt 전체 (file)또는 SReclaimable항목 이없는 오래된 커널에 대해 어떻게 계산 하겠습니까? 커널 v 2.6.18-348.16.1.el5xen (당 uname -r)이 있는 오래된 centos 상자에서 이것은 내가 얻는 결과입니다 : pastebin.com/iFWiM1kX . 당신의 계산은 단지 MemFree부분을 가져옵니다
Mitch

@Mitch 잘 모르겠습니다. 이전 커널에서 사용 가능한 정보가 사용 가능한 메모리 (스왑하기 전에)를 정확하게 결정하기에 충분하지는 않습니다.
Stephen Kitt

이 글타래에 기여한 모든 분들께 감사드립니다. MemAvailable의 계산은 Linux 4.5에서 약간 조정되었습니다. 그러나 새로운 MemAvailable 계산은 항상 이전 계산보다 약간 높아야하며, 따라서 모든 경우에 이전 계산을 사용하는 것이 안전해야합니다. gitlab.com/procps-ng/procps/issues/42
sourcejedi

7

Stephen의 대답은 충분하고주의를 기울이는 동안 최소 비교를 포함하여 전체 논리를 작성하기로 결정했습니다. 먼저 / proc / meminfo에서 정보를 읽고 변수에 저장하여 메모리 세부 사항이 일관되게합니다.

LOW_WATERMARK=$(awk '$1 == "low" {LOW_WATERMARK += $2} END {print LOW_WATERMARK * 4096}' /proc/zoneinfo)

MEMINFO=$(</proc/meminfo)

MEMINFO_MEMFREE=$(echo "${MEMINFO}" | awk '$1 == "MemFree:" {print $2 * 1024}')
MEMINFO_FILE=$(echo "${MEMINFO}" | awk '{MEMINFO[$1]=$2} END {print (MEMINFO["Active(file):"] + MEMINFO["Inactive(file):"]) * 1024}')
MEMINFO_SRECLAIMABLE=$(echo "${MEMINFO}" | awk '$1 == "SReclaimable:" {print $2 * 1024}')

MEMINFO_MEMAVAILABLE=$((
  MEMINFO_MEMFREE - LOW_WATERMARK
  + MEMINFO_FILE - ((MEMINFO_FILE/2) < LOW_WATERMARK ? (MEMINFO_FILE/2) : LOW_WATERMARK)
  + MEMINFO_SRECLAIMABLE - ((MEMINFO_SRECLAIMABLE/2) < LOW_WATERMARK ? (MEMINFO_SRECLAIMABLE/2) : LOW_WATERMARK)
))

if [[ "${MEMINFO_MEMAVAILABLE}" -le 0 ]]
then
  MEMINFO_MEMAVAILABLE=0
fi

변수에 저장된 결과는 바이트입니다.


이 답변은 커밋 34e431b0a의 계산을 구현하지만 Stephen Kitt의 답변은 테스트 한 5 대 중 2 대의 컴퓨터에서 더 정확한 추정치를 제공했습니다. 다섯 대의 컴퓨터에서 두 대답 모두 / proc / meminfo에서 직접 읽는 MemAvailable보다 큰 추정값을 제공했습니다. 아마도 더 안전한 방법은 2 사이의 크기를 작게하고 0.95 정도를 곱하는 것입니다.
toddwz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.