หน่วยความจำแบบ "แคช" ปราศจากความจริงหรือไม่


11

เมื่อทำงานcat /proc/meminfoคุณจะได้รับ 3 ค่าเหล่านี้ที่ด้านบน:

MemTotal:        6291456 kB
MemFree:         4038976 kB
Cached:          1477948 kB

เท่าที่ฉันรู้ค่า "แคช" คือดิสก์แคชที่ทำโดยระบบ Linux ที่จะถูกปล่อยทันทีหากแอปพลิเคชันใด ๆ ที่ต้องการ RAM เพิ่มขึ้นดังนั้น Linux จะไม่หมดหน่วยความจำจนกว่า MemFree และ Cache จะเป็นศูนย์

น่าเสียดายที่ "MemAvailable" ไม่มีการรายงานโดย / proc / meminfo อาจเป็นเพราะมันทำงานในเซิร์ฟเวอร์เสมือน (เวอร์ชั่นเคอร์เนลคือ 4.4)

ดังนั้นสำหรับการใช้งานจริง RAM สำหรับแอปพลิเคชันนั้นเป็น MemFree

มุมมองนั้นถูกต้องหรือไม่


1
ฉันไม่ต้องการค้อนทองคำปิด แต่คำถามนี้เกี่ยวข้องถ้าไม่ซ้ำ ฉันประหลาดใจที่คุณไม่มีMemAvailableมันเพิ่มเข้ามาใน 3.14
สตีเฟ่น Kitt

คำตอบที่ได้รับการยอมรับจากคำถามที่ใช้ / proc / zoneinfo ซึ่งไม่สามารถใช้ได้ใน vserver ของฉันเช่นกัน
Roland Seuhs

uname -a: โฮสต์ Linux 4.4.0-042stab134.8 # 1 SMP ศุกร์ 7 ธ.ค. 17:16:09 MSK 2018 x86_64 x86_64 x86_64 GNU / Linux
Roland Seuhs

ฉันสงสัยว่านี่เป็นระบบ OpenVZ ที่มีเคอร์เนลซึ่งเป็นจริงตาม 2.6.32 ไม่ใช่ 4.4
Stephen Kitt

1
@sourcejedi และมันถูกรวบรวมในเวลาเดียวกันกับเคอร์เนล 4.4!
สตีเฟ่น Kitt

คำตอบ:


10

มุมมองนั้นอาจทำให้เข้าใจผิดมากในบางกรณีในโลกแห่งความจริง

เคอร์เนลจะแสดงหน่วยความจำที่มีอยู่โดยประมาณในMemAvailableฟิลด์ MemFree + Cachedค่านี้เป็นอย่างมีนัยสำคัญที่แตกต่างจาก

/ proc / meminfo: จัดเตรียมหน่วยความจำที่มีให้โดยประมาณ [คำอธิบายการเปลี่ยนแปลงเคอร์เนล 2014]

โปรแกรมโหลดบาลานซ์และการวางเวิร์กโหลดจำนวนมากตรวจสอบ / proc / meminfo เพื่อประเมินจำนวนหน่วยความจำที่ว่าง พวกเขามักจะทำสิ่งนี้โดยการเพิ่ม "ฟรี" และ "แคช" ซึ่งใช้ได้เมื่อสิบปีที่แล้ว แต่รับประกันได้เลยว่าจะผิดในวันนี้

มันผิดเพราะ Cached มีหน่วยความจำที่ไม่ว่างเป็นหน้าแคชเช่นเซ็กเมนต์หน่วยความจำที่ใช้ร่วมกัน, tmpfs และ ramfs และไม่รวมหน่วยความจำพื้นแบบเรียกคืนได้ซึ่งอาจใช้หน่วยความจำระบบจำนวนมากในระบบที่ไม่ทำงาน ไฟล์จำนวนมาก

ปัจจุบันจำนวนหน่วยความจำที่มีอยู่สำหรับภาระงานใหม่โดยไม่ต้องผลักดันระบบให้สลับสามารถประมาณได้จาก MemFree, Active (ไฟล์), Inactive (ไฟล์) และ SReclaimable รวมถึงลายน้ำ "ต่ำ" จาก / proc / zoneinfo อย่างไรก็ตามสิ่งนี้อาจมีการเปลี่ยนแปลงในอนาคตและพื้นที่ผู้ใช้ไม่ควรคาดหวังว่าจะรู้ว่าเคอร์เนลภายในเกิดขึ้นโดยประมาณสำหรับจำนวนหน่วยความจำที่ว่าง จะสะดวกกว่าในการจัดทำประมาณการเช่นนี้ใน / proc / meminfo หากสิ่งต่าง ๆ เปลี่ยนแปลงในอนาคตเราจะต้องเปลี่ยนมันในที่เดียว
...

เอกสาร / filesystems / proc.txt:
...
MemAvailable: การประเมินจำนวนหน่วยความจำที่พร้อมใช้งานสำหรับการเริ่มต้นแอปพลิเคชันใหม่โดยไม่ต้องสลับ คำนวณจาก MemFree, SReclaimable, ขนาดของรายการไฟล์ LRU และลายน้ำต่ำในแต่ละโซน การประมาณการนั้นคำนึงถึงว่าระบบต้องการแคชของเพจบางส่วนเพื่อให้ทำงานได้ดีและแผ่นหินที่เรียกคืนได้จะไม่สามารถเรียกคืนได้เนื่องจากรายการที่ใช้งานอยู่ ผลกระทบของปัจจัยเหล่านั้นจะแตกต่างกันไปตามระบบ

1. รายละเอียด MemAvailable

ตามที่กล่าวไว้ข้างต้น tmpfs และShmemหน่วยความจำอื่นไม่สามารถทำให้เป็นอิสระได้ย้ายไปเพื่อสลับเท่านั้น Cachedใน/proc/meminfoอาจทำให้เข้าใจผิดมากเนื่องจากรวมถึงShmemหน่วยความจำชนิดถอดเปลี่ยนได้นี้ หากคุณมีไฟล์จำนวนมากเกินไปใน tmpfs อาจเป็นเพราะหน่วยความจำของคุณ :-) Shmemยังสามารถรวมการจัดสรรหน่วยความจำกราฟิกบางอย่างซึ่งอาจมีขนาดใหญ่มาก

MemAvailableโดยเจตนาไม่รวมหน่วยความจำแบบถอดเปลี่ยนได้ การสลับมากเกินไปอาจทำให้เกิดความล่าช้าได้นาน คุณอาจเลือกที่จะทำงานโดยไม่มีพื้นที่สว็อปหรืออนุญาตให้ใช้ในปริมาณที่ จำกัด เท่านั้น

ฉันต้องตรวจสอบอีกครั้งว่าMemAvailableทำงานอย่างไร เมื่อมองแวบแรกรหัสไม่ได้พูดถึงความแตกต่างนี้

/*
 * Not all the page cache can be freed, otherwise the system will
 * start swapping. Assume at least half of the page cache, or the
 * low watermark worth of cache, needs to stay.
 */
pagecache = pages[LRU_ACTIVE_FILE] + pages[LRU_INACTIVE_FILE];
pagecache -= min(pagecache / 2, wmark_low);
available += pagecache;

อย่างไรก็ตามฉันพบว่ามันถูกต้องถือว่าShmemเป็น "ใช้" หน่วยความจำ ฉันสร้างไฟล์ 1GB หลายไฟล์ใน tmpfs การเพิ่มขึ้น 1GB แต่ละครั้งจะShmemลดลงMemAvailable1GB ดังนั้นขนาดของ "รายการไฟล์ LRU" จึงไม่รวมหน่วยความจำที่แชร์หรือหน่วยความจำแบบถอดเปลี่ยนได้อื่น ๆ (ฉันสังเกตเห็นว่าจำนวนหน้าเดียวกันนี้ยังใช้ในรหัสที่คำนวณ "ขีด จำกัด สกปรก" )

การMemAvailableคำนวณนี้ยังอนุมานว่าคุณต้องการเก็บแคชไฟล์อย่างน้อยพอให้เท่ากับ "ลายน้ำต่ำ" ของเคอร์เนล หรือครึ่งหนึ่งของแคชปัจจุบัน - แล้วแต่จำนวนใดจะน้อยกว่า (มันทำให้สมมติฐานเดียวกันสำหรับแผ่นพื้นเรียกคืนได้เช่นกัน) เคอร์เนลของ "ลายน้ำต่ำ" สามารถปรับ แต่มันมักจะเป็นประมาณ 2% ของแรมระบบ ดังนั้นหากคุณต้องการประมาณการแบบคร่าวๆคุณสามารถละเว้นส่วนนี้ :-)

เมื่อคุณรันfirefoxด้วยโค้ดโปรแกรมประมาณ 100MB ที่แม็พไว้ในแคชของเพจโดยทั่วไปคุณต้องการเก็บ 100MB นั้นไว้ใน RAM :-) มิฉะนั้นที่ดีที่สุดคุณจะประสบความล่าช้าที่เลวร้ายที่สุดระบบจะใช้เวลาตลอดเวลาการฟาดระหว่างโปรแกรมที่แตกต่างกัน ดังนั้นMemAvailableจะช่วยให้เปอร์เซ็นต์ของ RAM ขนาดเล็กสำหรับสิ่งนี้ อาจไม่อนุญาตเพียงพอหรืออาจใจกว้างเกินไป "ผลกระทบของปัจจัยเหล่านั้นจะแตกต่างกันไปในแต่ละระบบ"

สำหรับพีซีจำนวนมากประเด็นเกี่ยวกับ "ไฟล์จำนวนมาก" อาจไม่เกี่ยวข้องกัน ถึงกระนั้นตอนนี้ฉันมีหน่วยความจำพื้นแบบดึงกลับได้ 500MB บนแล็ปท็อปของฉัน (จาก RAM 8GB) นี่คือสาเหตุที่ext4_inode_cache(วัตถุมากกว่า 300K) มันเกิดขึ้นเพราะเมื่อเร็ว ๆ นี้ฉันต้องสแกนระบบไฟล์ทั้งหมดเพื่อค้นหาสิ่งที่ใช้พื้นที่ดิสก์ของฉัน :-) ฉันใช้คำสั่งdf -x / | sort -nแต่เช่น Gnome Disk Usage Analyzer จะทำสิ่งเดียวกัน

2. [แก้ไข] หน่วยความจำในกลุ่มควบคุม

ที่เรียกว่า "ภาชนะลินุกซ์" จะถูกสร้างขึ้นจากnamespaces, cgroupsและคุณสมบัติอื่น ๆ ตามรสนิยม :-) พวกเขาอาจมีสภาพแวดล้อมที่น่าเชื่อถือเพียงพอที่จะเรียกใช้บางสิ่งบางอย่างที่เหมือนกับระบบ Linux เต็มรูปแบบ บริการโฮสติ้งสามารถสร้างตู้คอนเทนเนอร์แบบนี้และขายเป็น "เซิร์ฟเวอร์เสมือน" :-)

เซิร์ฟเวอร์ที่โฮสต์อาจสร้าง "เซิร์ฟเวอร์เสมือน" โดยใช้คุณสมบัติที่ไม่ได้อยู่ในการฉีด Linux ภาชนะบรรจุOpenVZก่อนฉีดกลุ่ม cg ล่วงหน้าสองปีและอาจใช้ "beancounters" เพื่อ จำกัด หน่วยความจำ ดังนั้นคุณจึงไม่สามารถเข้าใจได้อย่างชัดเจนว่าหน่วยความจำเหล่านั้นทำงานอย่างไรถ้าคุณอ่านเอกสารหรือถามคำถามเกี่ยวกับเคอร์เนล mainline cat /proc/user_beancountersแสดงการใช้งานและขีด จำกัด ปัจจุบัน vzubcนำเสนอในรูปแบบที่เป็นมิตรขึ้นเล็กน้อย หน้าหลัก beancountersเอกสารชื่อแถว

กลุ่มควบคุมรวมถึงความสามารถในการตั้งค่าขีด จำกัด หน่วยความจำในกระบวนการภายใน หากคุณเรียกใช้แอปพลิเคชันของคุณภายในกลุ่ม cgroup แอปพลิเคชัน :-) จะไม่สามารถใช้หน่วยความจำระบบทั้งหมดได้ ดังนั้นเราจะดูหน่วยความจำที่มีอยู่ในกรณีนี้ได้อย่างไร

อินเตอร์เฟซสำหรับความแตกต่างในหลายวิธีขึ้นอยู่กับว่าคุณใช้cgroup-V1หรือcgroup-v2

แล็ปท็อปของฉันติดตั้งใช้ cgroup-v1 ฉันสามารถวิ่งcat /sys/fs/cgroup/memory/memory.statได้ แสดงให้เห็นว่าไฟล์สาขาต่าง ๆ ได้แก่total_rss, ,total_cache total_shmemshmem รวมถึง tmpfs นับรวมถึงขีด จำกัด หน่วยความจำ ผมคิดว่าคุณสามารถดูเป็นเทียบเท่าผกผันของtotal_rss MemFreeและยังมีไฟล์memory.kmem.usage_in_bytesซึ่งเป็นตัวแทนหน่วยความจำเคอร์เนลรวมถึงแผ่นพื้น (ฉันถือว่าmemory.kmem.ยังรวมถึงmemory.kmem.tcp.และส่วนขยายใด ๆ ในอนาคตแม้ว่าจะไม่ได้บันทึกไว้อย่างชัดเจน) ไม่มีตัวนับที่แยกต่างหากเพื่อดูหน่วยความจำพื้นแบบเรียกคืนได้ เอกสารสำหรับ cgroup-v1 กล่าวว่าการกดปุ่มขีด จำกัด หน่วยความจำไม่ทำให้เกิดการเรียกคืนหน่วยความจำแบบพื้นใด ๆ (เอกสารมีข้อจำกัดความรับผิดชอบว่าเป็น "ล้าสมัยอย่างสิ้นหวัง" และคุณควรตรวจสอบซอร์สโค้ดปัจจุบัน)

cgroup-v2 นั้นแตกต่างกัน ฉันคิดว่ากลุ่ม cgroup รูท (ระดับบนสุด) ไม่รองรับบัญชีหน่วยความจำ cgroup-v2 ยังมีmemory.statไฟล์อยู่ เขตข้อมูลทั้งหมดรวมกับกลุ่มเด็กดังนั้นคุณไม่จำเป็นต้องค้นหาtotal_...เขตข้อมูล มีfileสนามซึ่งหมายความว่าสิ่งเดียวกันcacheได้ รำคาญฉันไม่เห็นสนามโดยรวมเช่นrssภายในmemory.stat; ฉันเดาว่าคุณจะต้องเพิ่มแต่ละฟิลด์ มีสถิติแยกต่างหากสำหรับหน่วยความจำพื้นแบบเรียกคืนได้และไม่สามารถเรียกคืนได้ ฉันคิดว่า v2 cgroup ออกแบบมาเพื่อเรียกคืนแผ่นพื้นเมื่อเริ่มมีหน่วยความจำเหลือน้อย

Linux cgroups จะไม่จำลองเสมือนโดยอัตโนมัติ/proc/meminfo(หรือไฟล์อื่น ๆ/proc) ดังนั้นจะแสดงค่าสำหรับเครื่องทั้งหมด สิ่งนี้จะสร้างความสับสนให้กับลูกค้า VPS แต่มันเป็นไปได้ที่จะใช้ namespaces เพื่อแทนที่/proc/meminfoด้วยไฟล์ปลอมขึ้นโดยซอฟต์แวร์ภาชนะที่เฉพาะเจาะจง คุณค่าของปลอมมีประโยชน์อย่างไรขึ้นอยู่กับว่าซอฟต์แวร์นั้นทำอะไร

systemdเชื่อว่า cgroup-v1 ไม่สามารถมอบหมายอย่างปลอดภัยเช่นคอนเทนเนอร์ ฉันดูในsystemd-nspawnตู้คอนเทนเนอร์ในระบบ cgroup-v1 ของฉัน ฉันสามารถเห็น cgroup มันถูกวางไว้ภายในและบัญชีหน่วยความจำในที่ ในทางตรงกันข้ามที่มีอยู่systemdไม่ได้ตั้งค่ากลุ่มบริการต่อการบัญชีทรัพยากร หากการบัญชีหน่วยความจำไม่ได้เปิดใช้งานภายใน cgroup นี้ฉันคิดว่าคอนเทนเนอร์จะไม่สามารถเปิดใช้งานได้

ฉันคิดว่าถ้าคุณอยู่ใน cgroup-v2 container มันจะดูแตกต่างจากรูทของระบบ cgroup-v2 จริงและคุณจะสามารถเห็นการบัญชีหน่วยความจำสำหรับ cgroup ระดับบนสุด หรือถ้ากลุ่ม cg ที่คุณเห็นไม่ได้เปิดใช้งานการบัญชีหน่วยความจำหวังว่าคุณจะได้รับอนุญาตจากคุณเพื่อให้คุณสามารถเปิดใช้งานการบัญชีหน่วยความจำในsystemd (หรือเทียบเท่า)


1
เอกสารอย่างเป็นทางการelixir.bootlin.com/linux/v5.0-rc5/source/Documentation/...
สิ้นเชิง

1
มันหนาวหน่อย ฉันใช้ลิงก์ GitHub เพราะพวกเขาแสดงรุ่นแรกที่มีการส่งมอบ (คล้ายกับgit describe --contains) พบว่ามันเชื่อมโยงกันเป็น TL; DR โดยคำถาม SU ซึ่งกลายเป็นเพียงการอ้างถึงส่วนที่เพิ่มใน proc.txt แต่สำหรับคำถามนี้คำอธิบายการคอมมิชชันนั้นสมบูรณ์แบบเพียง IMO :-)
sourcejedi

ดูเหมือนว่า MemAvailable จะไม่พร้อมใช้งานบนเซิร์ฟเวอร์เสมือนส่วนใหญ่แล้วจะทำอย่างไร?
Roland Seuhs

@RolandSeuhs อาจเรียนรู้ "beancounters" ดูการแก้ไขด้วยตัวหนา หากคุณมีคำถามเกี่ยวกับ beancounters ฉันจะขอบคุณถ้าคุณถามคำถามใหม่ เราสามารถเชื่อมโยงได้จากสิ่งนี้เสมอ แต่รายละเอียดอาจไม่เกี่ยวข้องกับผู้อ่านที่ใช้เคอร์เนล mainline linux
sourcejedi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.