ฉันจะได้รับจำนวนหน่วยความจำที่พร้อมใช้งานแบบพกพาข้ามการกระจายได้อย่างไร


12

ไฟล์ / เครื่องมือมาตรฐานที่รายงานหน่วยความจำดูเหมือนจะมีรูปแบบที่แตกต่างกันในการแจกแจง Linux ที่แตกต่างกัน ตัวอย่างเช่นบน Arch และ Ubuntu

  • โค้ง

    $ 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
    

ดังนั้นฉันจะพกพาได้อย่างไร (ข้าม Linux distros เท่านั้น) และได้รับปริมาณหน่วยความจำที่เชื่อถือได้ - ไม่รวมการสลับ - ที่มีให้ซอฟต์แวร์ของฉันใช้ในเวลาใดเวลาหนึ่ง? น่าจะเป็นสิ่งที่แสดงเป็น "พร้อมใช้" และ "MemAvailable" ในผลลัพธ์ของfreeและcat /proc/meminfoใน Arch แต่ฉันจะได้รับเหมือนกันใน Ubuntu หรือการกระจายอื่นได้อย่างไร

คำตอบ:


18

MemAvailableรวมอยู่ใน/proc/meminfoตั้งแต่รุ่น 3.14 ของเคอร์เนล; มันก็เพิ่มขึ้นโดยการกระทำ 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) ให้ผลลัพธ์ที่ถูกต้องในระบบของฉัน (ความเรียบง่ายนี้ดูถูกหน่วยความจำที่มีอยู่ถ้าแคชหน้าหรือหน่วยความจำคืนดีมีขนาดเล็กกว่าสองเท่าของลายน้ำต่ำ แต่คุณจะไม่ต้องการที่จะใช้หน่วยความจำมากในสถานการณ์ที่อยู่แล้วดังนั้นที่ดูเหมือนว่าจะมีการประนีประนอมที่เหมาะสม.)
สตีเฟ่นกิต

1
@StephenKitt คุณจะคำนวณเกี่ยวกับเมล็ดที่เก่ากว่าที่ไม่มี(file)การSReclaimableเข้าหรือรายการได้อย่างไร บน CentOS เก่ากล่องที่มีเคอร์เนลวี 2.6.18-348.16.1.el5xen (ต่อuname -r) นี่คือผลลัพธ์ที่ฉันได้รับ: pastebin.com/iFWiM1kX การคำนวณของคุณดึงเฉพาะMemFreeส่วน
มิทช์

@ Mitch ฉันไม่รู้ฉันไม่แน่ใจว่าข้อมูลที่มีจากเคอร์เนลเก่าของคุณเพียงพอที่จะกำหนดหน่วยความจำที่มีอยู่ (ก่อนการแลกเปลี่ยน) ได้อย่างถูกต้อง
Stephen Kitt

ขอบคุณทุกคนที่มีส่วนร่วมในกระทู้นี้มันเป็นข้อมูลอ้างอิงที่ดี การคำนวณ MemAvailable ได้รับการปรับเล็กน้อยใน Linux 4.5 อย่างไรก็ตามการคำนวณ MemAvailable ใหม่ควรสูงกว่า (หรืออาจเหมือนกับ) เก่าเล็กน้อยดังนั้นควรจะปลอดภัยที่จะใช้การคำนวณแบบเก่าในทุกกรณี gitlab.com/procps-ng/procps/issues/42
sourcejedi

7

ในขณะที่คำตอบของสตีเฟ่นนั้นสมบูรณ์เพียงพอและผิดพลาดไปด้วยความระมัดระวังฉันตัดสินใจที่จะเขียนตรรกะทั้งหมดรวมถึงการเปรียบเทียบขั้นต่ำ ข้อมูลจะถูกอ่านจาก / 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 ให้การประมาณการที่แม่นยำยิ่งขึ้นสำหรับ 2 เครื่องจาก 5 เครื่องที่ฉันทดสอบ ในเครื่องทั้ง 5 เครื่องทั้งสองคำตอบนั้นให้ค่าประมาณที่มากกว่าการอ่าน MemAvailable โดยตรงจาก / proc / meminfo อาจเป็นวิธีที่ปลอดภัยกว่าคือการได้ขนาดเล็กลงระหว่าง 2 และคูณด้วย 0.95 หรือมากกว่านั้น
toddwz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.