30% ของ RAM คือ“ บัฟเฟอร์” มันคืออะไร?


13
$ free -h
              total        used        free      shared  buff/cache   available
Mem:           501M        146M         19M        9.7M        335M        331M
Swap:          1.0G         85M        938M

$ free -w -h
              total        used        free      shared     buffers       cache   available
Mem:           501M        146M         19M        9.7M        155M        180M        331M
Swap:          1.0G         85M        938M

ฉันจะอธิบายหรืออธิบาย "บัฟเฟอร์" ในผลลัพธ์ของได้freeอย่างไร

ฉันไม่มีปัญหา (รู้) กับระบบนี้ ฉันประหลาดใจและอยากรู้อยากเห็นว่า "บัฟเฟอร์" สูงเกือบเท่า "แคช" (155M กับ 180M) ฉันคิดว่า "แคช" แสดงถึงแคชหน้าของเนื้อหาไฟล์และมีแนวโน้มที่จะเป็นส่วนที่สำคัญที่สุดของ "แคช / บัฟเฟอร์" ฉันไม่ค่อยชัดเจนว่า "บัฟเฟอร์" มีไว้เพื่ออะไร

ตัวอย่างเช่นฉันเปรียบเทียบสิ่งนี้กับแล็ปท็อปซึ่งมี RAM มากกว่า ในแล็ปท็อปของฉันตัวเลข "บัฟเฟอร์" เป็นลำดับที่เล็กกว่า "แคช" (200M เทียบกับ 4G) หากฉันมีความเข้าใจที่ถูกต้องเกี่ยวกับสิ่งที่ "บัฟเฟอร์" เป็นแล้วฉันสามารถเริ่มถามว่าทำไมบัฟเฟอร์อาจเติบโตถึงสัดส่วนที่มากขึ้นในระบบขนาดเล็ก

man proc (ฉันไม่สนใจคำจำกัดความที่ล้าสมัยของ "ใหญ่" อย่างเฮฮา):

บัฟเฟอร์% lu

ที่เก็บข้อมูลชั่วคราวสำหรับบล็อกดิสก์ดิบที่ไม่ควรมีขนาดใหญ่มาก (20MB หรือมากกว่านั้น)

แคช% lu

แคชในหน่วยความจำสำหรับไฟล์ที่อ่านจากดิสก์ (แคชของหน้า) ไม่รวม SwapCached


$ free -V
free from procps-ng 3.3.12
$ uname -r
4.9.0-6-marvell
$ systemd-detect-virt
none

$ cat /proc/meminfo
MemTotal:         513976 kB
MemFree:           20100 kB
MemAvailable:     339304 kB
Buffers:          159220 kB
Cached:           155536 kB
SwapCached:         2420 kB
Active:           215044 kB
Inactive:         216760 kB
Active(anon):      56556 kB
Inactive(anon):    73280 kB
Active(file):     158488 kB
Inactive(file):   143480 kB
Unevictable:       10760 kB
Mlocked:           10760 kB
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         513976 kB
LowFree:           20100 kB
SwapTotal:       1048572 kB
SwapFree:         960532 kB
Dirty:               240 kB
Writeback:             0 kB
AnonPages:        126912 kB
Mapped:            40312 kB
Shmem:              9916 kB
Slab:              37580 kB
SReclaimable:      29036 kB
SUnreclaim:         8544 kB
KernelStack:        1472 kB
PageTables:         3108 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:     1305560 kB
Committed_AS:    1155244 kB
VmallocTotal:     507904 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

$ sudo slabtop --once
 Active / Total Objects (% used)    : 186139 / 212611 (87.5%)
 Active / Total Slabs (% used)      : 9115 / 9115 (100.0%)
 Active / Total Caches (% used)     : 66 / 92 (71.7%)
 Active / Total Size (% used)       : 31838.34K / 35031.49K (90.9%)
 Minimum / Average / Maximum Object : 0.02K / 0.16K / 4096.00K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 59968  57222   0%    0.06K    937       64      3748K buffer_head            
 29010  21923   0%    0.13K    967       30      3868K dentry                 
 24306  23842   0%    0.58K   4051        6     16204K ext4_inode_cache       
 22072  20576   0%    0.03K    178      124       712K kmalloc-32             
 10290   9756   0%    0.09K    245       42       980K kmalloc-96             
  9152   4582   0%    0.06K    143       64       572K kmalloc-node           
  9027   8914   0%    0.08K    177       51       708K kernfs_node_cache      
  7007   3830   0%    0.30K    539       13      2156K radix_tree_node        
  5952   4466   0%    0.03K     48      124       192K jbd2_revoke_record_s   
  5889   5870   0%    0.30K    453       13      1812K inode_cache            
  5705   4479   0%    0.02K     35      163       140K file_lock_ctx          
  3844   3464   0%    0.03K     31      124       124K anon_vma               
  3280   3032   0%    0.25K    205       16       820K kmalloc-256            
  2730   2720   0%    0.10K     70       39       280K btrfs_trans_handle     
  2025   1749   0%    0.16K     81       25       324K filp                   
  1952   1844   0%    0.12K     61       32       244K kmalloc-128            
  1826    532   0%    0.05K     22       83        88K trace_event_file       
  1392   1384   0%    0.33K    116       12       464K proc_inode_cache       
  1067   1050   0%    0.34K     97       11       388K shmem_inode_cache      
   987    768   0%    0.19K     47       21       188K kmalloc-192            
   848    757   0%    0.50K    106        8       424K kmalloc-512            
   450    448   0%    0.38K     45       10       180K ubifs_inode_slab       
   297    200   0%    0.04K      3       99        12K eventpoll_pwq          
   288    288 100%    1.00K     72        4       288K kmalloc-1024           
   288    288 100%    0.22K     16       18        64K mnt_cache              
   287    283   0%    1.05K     41        7       328K idr_layer_cache        
   240      8   0%    0.02K      1      240         4K fscrypt_info           

3
linuxatemyram.comมีประโยชน์ในการอ่าน
Basile Starynkevitch

คำตอบ:


14
  1. ความแตกต่างระหว่าง "บัฟเฟอร์" และแคชอื่นคืออะไร?
  2. ทำไมเราถึงเห็นความแตกต่างนี้เด่นชัด? (เหตุผลทางประวัติศาสตร์ที่เป็นไปได้)
  3. สิ่งที่Buffersใช้?
  4. เหตุใดเราคาดหวังว่าBuffersโดยเฉพาะอย่างยิ่งที่จะใหญ่หรือเล็กกว่า

1. "บัฟเฟอร์" และแคชประเภทอื่นแตกต่างกันอย่างไร

Buffersรายงานจำนวนแคชของเพจที่ใช้สำหรับอุปกรณ์บล็อก Cachedเคอร์เนลมีการจงใจหักเงินจำนวนนี้มาจากส่วนที่เหลือของแคชหน้าเมื่อจะรายงาน

ดูmeminfo_proc_show () :

cached = global_node_page_state(NR_FILE_PAGES) -
         total_swapcache_pages() - i.bufferram;
...

show_val_kb(m, "MemTotal:       ", i.totalram);
show_val_kb(m, "MemFree:        ", i.freeram);
show_val_kb(m, "MemAvailable:   ", available);
show_val_kb(m, "Buffers:        ", i.bufferram);
show_val_kb(m, "Cached:         ", cached);

2. ทำไมเราถึงเห็นความแตกต่างนี้เด่นชัด? (เหตุผลทางประวัติศาสตร์ที่เป็นไปได้)

แคชหน้าทำงานในหน่วยของขนาดหน้า MMU โดยทั่วไปแล้วอย่างน้อย 4096 ไบต์ นี่เป็นสิ่งจำเป็นสำหรับmmap()การเข้าถึงไฟล์เช่นหน่วยความจำที่แมป [1] [2] มันถูกใช้เพื่อแชร์เพจของโค้ดโปรแกรม / ไลบรารีที่โหลดระหว่างกระบวนการอิสระและอนุญาตให้โหลดแต่ละหน้าตามต้องการ (เช่นเดียวกับการยกเลิกการโหลดหน้าเมื่อมีสิ่งอื่นที่ต้องการพื้นที่และพวกเขาไม่ได้ใช้เมื่อเร็ว ๆ นี้)

[1] I / O ที่แมปหน่วยความจำ -คู่มือ GNU C Library
[2] mmap- วิกิพีเดีย

UNIX ก่อนหน้ามี "บัฟเฟอร์แคช" ของบล็อกดิสก์และไม่มี mmap () เห็นได้ชัดว่าเมื่อเพิ่ม mmap () เข้ามาในครั้งแรกพวกเขาเพียงปิดหน้าแคชที่ด้านบนของบัฟเฟอร์แคช มันยุ่งเหยิงอย่างที่มันฟัง ในที่สุดระบบปฏิบัติการที่ใช้ UNIX จะกำจัดแคชบัฟเฟอร์ ดังนั้นตอนนี้แคชไฟล์ทั้งหมดอยู่ในหน่วยของหน้า หน้าต่างๆถูกค้นหาโดย (ไฟล์, ออฟเซ็ต) ไม่ใช่ตามตำแหน่งบนดิสก์ สิ่งนี้เรียกว่า "unified buffer cache" อาจเป็นเพราะคนคุ้นเคยกับ "buffer cache" มากกว่า [3]

[3] UBC: ระบบย่อย I / O Unified ที่มีประสิทธิภาพและหน่วยความจำแคชสำหรับ NetBSD

"สิ่งที่น่าสนใจอย่างหนึ่งที่ Linux เพิ่มคือหมายเลขอุปกรณ์บล็อกที่เก็บเพจไว้ในดิสก์จะถูกเก็บไว้กับเพจในรูปแบบของรายการbuffer_headโครงสร้างเมื่อหน้าแก้ไขจะถูกเขียนกลับไปยังดิสก์ I / O สามารถส่งคำขอไปยังไดรเวอร์อุปกรณ์ได้ทันทีโดยไม่จำเป็นต้องอ่านบล็อกทางอ้อมเพื่อพิจารณาว่าควรเขียนข้อมูลของหน้าไหน "[3]

ใน Linux 2.2 มี "บัฟเฟอร์แคช" แยกต่างหากที่ใช้สำหรับการเขียน แต่ไม่ใช่สำหรับการอ่าน "แคชหน้าใช้บัฟเฟอร์แคชเพื่อเขียนข้อมูลกลับคืนต้องการสำเนาเพิ่มเติมของข้อมูลและเพิ่มความต้องการหน่วยความจำสำหรับการโหลดการเขียนเพิ่มขึ้นสองเท่า" (?) [4] ไม่ต้องกังวลเกี่ยวกับรายละเอียดมากนัก แต่ประวัตินี้อาจเป็นสาเหตุหนึ่งที่ทำให้ Linux รายงานBuffersการใช้งานแยกกัน

[4] การแทนที่หน้าในการจัดการหน่วยความจำ Linux 2.4 , Rik van Riel

ในทางตรงกันข้ามใน Linux 2.4 และสูงกว่าการคัดลอกพิเศษไม่มีอยู่ "ระบบทำดิสก์ IO โดยตรงไปยังและจากหน้าแคชหน้า" [4] Linux 2.4 เปิดตัวในปี 2544

3. Buffersใช้ทำอะไร?

อุปกรณ์บล็อกถือเป็นไฟล์ดังนั้นจึงมีหน้าแคช สิ่งนี้ใช้ "สำหรับข้อมูลเมตาของระบบไฟล์และการแคชอุปกรณ์ raw block" [4] แต่ใน Linux เวอร์ชันปัจจุบันระบบไฟล์จะไม่คัดลอกเนื้อหาของไฟล์ผ่านดังนั้นจึงไม่มี "แคชคู่"

ฉันคิดว่าBuffersส่วนหนึ่งของหน้าแคชเป็นแคชบัฟเฟอร์ Linux แม้ว่าบางแหล่งอาจไม่เห็นด้วยกับคำศัพท์นี้

จำนวนแคชบัฟเฟอร์ที่ระบบไฟล์ใช้ถ้ามีขึ้นอยู่กับรายละเอียดของระบบไฟล์เฉพาะ ระบบในคำถามใช้ ext4 ext3 / ext4 ใช้แคชบัฟเฟอร์ Linux สำหรับเจอร์นัลสำหรับเนื้อหาไดเรกทอรีและข้อมูลเมตาอื่น ๆ

ระบบไฟล์บางระบบรวมถึง ext3, ext4 และ ocfs2 ใช้เลเยอร์ jbd หรือ jbd2 เพื่อจัดการเจอร์นัลบล็อกฟิสิคัลและเลเยอร์นี้ใช้แคชแคชเป็นพื้นฐาน

- บทความอีเมลโดยTed Tso , 2013

ก่อนหน้าเคอร์เนล Linux รุ่น 2.4 Linux มีหน้าที่แยกแคชและบัฟเฟอร์ ตั้งแต่ 2.4 เพจและบัฟเฟอร์แคชจะถูกรวมเข้าด้วยกันและBuffersเป็นบล็อกดิสก์ดิบซึ่งไม่ได้แสดงในแคชหน้าเช่นไม่ใช่ข้อมูลไฟล์

...

บัฟเฟอร์แคชยังคงอยู่อย่างไรก็ตามในขณะที่เคอร์เนลยังคงต้องการบล็อก I / O ในแง่ของบล็อกไม่ใช่หน้าเว็บ เนื่องจากบล็อกส่วนใหญ่แสดงข้อมูลไฟล์แคชบัฟเฟอร์ส่วนใหญ่จะแสดงโดยแคชหน้า แต่ข้อมูลบล็อกจำนวนเล็กน้อยไม่ได้รับการสนับสนุนไฟล์เช่นข้อมูลเมตาและ I / O บล็อกดิบเป็นต้นซึ่งจะแสดงโดยแคชบัฟเฟอร์เท่านั้น

- คู่ของ Quora ตอบโดยRobert Loveอัพเดตล่าสุดปี 2013

ตัวเขียนทั้งสองเป็นนักพัฒนา Linux ที่ทำงานกับการจัดการหน่วยความจำเคอร์เนลของ Linux แหล่งแรกมีความเฉพาะเจาะจงมากขึ้นเกี่ยวกับรายละเอียดทางเทคนิค แหล่งข้อมูลที่สองเป็นข้อมูลสรุปทั่วไปซึ่งอาจขัดแย้งและล้าสมัยในข้อมูลเฉพาะบางอย่าง

มันเป็นความจริงที่ระบบไฟล์อาจดำเนินการเขียนข้อมูลเมตาบางส่วนถึงแม้ว่าแคชจะได้รับการจัดทำดัชนีในหน้าเว็บ แม้แต่กระบวนการของผู้ใช้สามารถทำการเขียนบางส่วนได้เมื่อใช้write()(ตรงข้ามกับmmap()) อย่างน้อยก็โดยตรงไปยังอุปกรณ์บล็อก ใช้กับการเขียนเท่านั้นไม่อ่าน เมื่อคุณอ่านหน้าแคชแคชหน้าจะอ่านหน้าเต็มเสมอ

ไลนัสชอบพูดจาโผงผางว่าไม่จำเป็นต้องใช้แคชบัฟเฟอร์เพื่อทำการเขียนขนาดบล็อกและระบบไฟล์สามารถทำการเขียนข้อมูลเมตาบางส่วนได้แม้จะมีแคชหน้าแนบกับไฟล์ของตัวเองแทนที่จะเป็นอุปกรณ์บล็อก ฉันแน่ใจว่าเขาพูดถูกที่ ext2 ทำเช่นนี้ ext3 / ext4 ที่มีระบบการทำเจอร์นัลไม่ได้ มันไม่ชัดเจนว่าปัญหาที่นำไปสู่การออกแบบนี้คืออะไร ผู้คนที่เขาคุยโวมักเบื่อหน่ายกับการอธิบาย

ext4_readdir () ยังไม่ถูกเปลี่ยนเพื่อให้เป็นที่พอใจของ Linus ฉันไม่เห็นวิธีการที่เขาต้องการใช้ใน readdir () ของระบบไฟล์อื่นเช่นกัน ฉันคิดว่า XFS ใช้บัฟเฟอร์แคชสำหรับไดเรกทอรีเช่นกัน bcachefs ไม่ได้ใช้แคชหน้าสำหรับ readdir () เลย; มันใช้แคชของตัวเองสำหรับ btrees ฉันอาจจะหายไปบางสิ่งบางอย่างใน btrfs

4. ทำไมเราคาดหวังว่าBuffersโดยเฉพาะอย่างยิ่งที่จะใหญ่หรือเล็ก?

ในกรณีนี้ปรากฎขนาดสมุดบันทึก ext4สำหรับระบบไฟล์ของฉันคือ 128M ดังนั้นสิ่งนี้จึงอธิบายว่าทำไม 1) แคชบัฟเฟอร์ของฉันสามารถทำให้เสถียรที่ 128M ขึ้นไปเล็กน้อย 2) บัฟเฟอร์แคชไม่ได้ปรับสัดส่วนตามจำนวน RAM ขนาดใหญ่บนแล็ปท็อปของฉัน

สำหรับสาเหตุที่เป็นไปได้อื่น ๆ ให้ดูที่คอลัมน์บัฟเฟอร์ในเอาต์พุตไม่ว่างคืออะไร โปรดทราบว่า "บัฟเฟอร์" ที่รายงานโดยfreeจริง ๆ แล้วเป็นการรวมกันของBuffersหน่วยความจำพื้นและเรียกคืนได้


ในการตรวจสอบว่าเจอร์นัลเขียนใช้แคชบัฟเฟอร์ฉันจำลองระบบไฟล์ใน RAM เร็ว (tmpfs) ที่ดีและเปรียบเทียบการใช้บัฟเฟอร์สูงสุดสำหรับขนาดเจอร์นัลที่แตกต่างกัน

# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=256
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size:             256M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2521        4321         285          66         947        5105
Swap:          7995           0        7995

# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2523        3872         551         237        1223        4835
Swap:          7995           0        7995

# dd if=/dev/zero of=/tmp/t bs=1M count=1000
...
# mkfs.ext4 /tmp/t -J size=16
...
# LANG=C dumpe2fs /tmp/t | grep '^Journal size'
dumpe2fs 1.43.5 (04-Aug-2017)
Journal size:             16M
# mount /tmp/t /mnt
# cd /mnt
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2507        4337         285          66         943        5118
Swap:          7995           0        7995

# for i in $(seq 40000); do dd if=/dev/zero of=t bs=1k count=1 conv=sync status=none; sync t; sync -f t; done
# free -w -m
              total        used        free      shared     buffers       cache   available
Mem:           7855        2509        4290         315          77         977        5086
Swap:          7995           0        7995

ประวัติของคำตอบนี้: ฉันมาดูวารสารได้อย่างไร

ฉันพบอีเมลของ Ted Tso ก่อนและรู้สึกว่ามันเน้นการเขียนแคช ฉันพบว่ามันน่าประหลาดใจหาก "สกปรก" ข้อมูลที่ไม่ได้เขียนก็สามารถเข้าถึง RAM ได้ 30% ในระบบของฉัน sudo atopแสดงให้เห็นว่าในช่วงเวลา 10 วินาทีระบบที่เป็นปัญหาจะเขียนเพียง 1MB เท่านั้น ระบบไฟล์ที่เกี่ยวข้องจะสามารถรักษาอัตรานี้ได้มากกว่า 100 เท่า (มันอยู่ในฮาร์ดดิสก์ USB2, ปริมาณงานสูงสุด ~ 20MB / s)

การใช้ blktrace ( btrace -w 10 /dev/sda) ยืนยันว่า IOs ที่กำลังถูกแคชจะต้องเขียนเพราะเกือบจะไม่มีข้อมูลที่อ่าน นอกจากนี้ยังmysqldเป็นกระบวนการuserspaceเดียวที่ทำ IO

ฉันหยุดบริการที่รับผิดชอบการเขียน (icinga2 เขียนไปยัง mysql) และตรวจสอบอีกครั้ง ฉันเห็น "บัฟเฟอร์" ต่ำกว่า 20M - ฉันไม่มีคำอธิบายสำหรับเรื่องนั้น - และอยู่ที่นั่น การเริ่มตัวเขียนใหม่อีกครั้งจะแสดง "บัฟเฟอร์" ที่เพิ่มขึ้นโดย ~ 0.1M สำหรับแต่ละช่วงเวลา 10 วินาที ฉันสังเกตว่ามันรักษาอัตรานี้อย่างต่อเนื่องโดยปีนกลับไปที่ 70M ขึ้นไป

การทำงานecho 3 | sudo tee /proc/sys/vm/drop_cachesเพียงพอที่จะลด "บัฟเฟอร์" อีกครั้งถึง 4.5M นี่เป็นการพิสูจน์ว่าการสะสมบัฟเฟอร์ของฉันเป็นแคช "สะอาด" ซึ่ง Linux สามารถวางได้ทันทีเมื่อต้องการ ระบบนี้ไม่ได้เก็บข้อมูลที่ไม่ได้บันทึกไว้ ( drop_cachesไม่ทำการลบข้อมูลใด ๆ ดังนั้นจึงไม่สามารถวางหน้าสกปรกหากคุณต้องการรันการทดสอบที่ล้างแคชก่อนคุณจะต้องใช้syncคำสั่ง)

ไดเรกทอรี mysql ทั้งหมดเป็นเพียง 150M บัฟเฟอร์ที่สะสมจะต้องเป็นตัวแทนบล็อกข้อมูลเมตาจากการเขียน mysql แต่มันทำให้ฉันประหลาดใจที่คิดว่าจะมีบล็อกข้อมูลเมตาจำนวนมากสำหรับข้อมูลนี้


3

เวอร์ชันของคุณfreeมีความคิดที่ถูกต้อง โดยค่าเริ่มต้นมันรวมบัฟเฟอร์และแคชในรายงาน นี่เป็นเพราะพวกเขามีสิ่งเดียวกัน คอมพิวเตอร์ทั้งสองเครื่องจำได้ใน RAM (เร็วกว่าที่เก็บข้อมูลรอง: ดิสก์และ SSD) สิ่งที่เห็นเมื่ออ่านดิสก์และ SSD

หากระบบปฏิบัติการรู้สึกว่าหน่วยความจำนั้นใช้งานได้ดีกว่าอย่างอื่นก็สามารถทำให้เป็นอิสระได้ ดังนั้นไม่ต้องกังวลกับบัฟเฟอร์และแคช

อย่างไรก็ตามการดูดีวีดีอาจทำให้บัฟเฟอร์เพิ่มขึ้นและขับเนื้อหาบัฟเฟอร์ / แคชอื่น ๆ ดังนั้นคุณอาจต้องใช้ nocache เพื่อเรียกใช้เครื่องเล่นดีวีดี ( หากเป็นสาเหตุของปัญหา )

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.