วางไฟล์เฉพาะจากแคชระบบไฟล์ Linux?


23

ฉันรู้ว่าฉันสามารถวางทุกอย่างจากแคชระบบไฟล์ Linuxแต่มีวิธีที่จะวางเพียงไฟล์เดียว? หรือป้องกันไฟล์จากการถูกแคช? หรือบอกขั้นตอนการไม่แคชไฟล์ใด ๆ ที่มันเขียน?

ฉันมีกระบวนการที่อ่านไฟล์ขนาดเล็กจำนวนมากและเขียนไฟล์ขนาดใหญ่ ฉันต้องการเก็บไฟล์เล็ก ๆ ไว้ในแคชเพื่อหลีกเลี่ยงการค้นหาดิสก์และฉันไม่สนใจที่จะแคชไฟล์ขนาดใหญ่


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

คำตอบ:


21

ศักยภาพวิธี # 1 - F_DROP_CACHES

ผมพบว่าวิธีการจาก 2012 ที่กล่าวถึงแพทช์เสนอให้เคอร์เนลในหัวข้อจดหมายนี้หัวข้อ: Re: [RFC Patch] FS: ดำเนินการต่อไฟล์แคชลดลง

สิ่งที่สกัดมา

Cong> นี่เป็นแพตช์แบบร่างในการนำแคชแคชแบบดรอปต่อไฟล์

น่าสนใจ ดังนั้นฉันสามารถทำสิ่งนี้จากนอกกระบวนการได้หรือไม่? ฉันคือ SysAdmin ดังนั้น POV ของฉันจึงสังเกตเห็นค้นหาและแก้ไขปัญหาประสิทธิภาพเมื่อระบบอยู่ภายใต้แรงกดดัน

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

ฉันจะบอกได้อย่างไรว่าไฟล์ถูกใช้ไปมากแค่ไหน? และประสิทธิภาพการทำงานของสิ่งนี้เมื่อทำงานบนระบบไม่ว่างคืออะไร? และแพทช์นี้ซื้ออะไรให้เราตั้งแต่ฉันคิดว่า VM ควรจะวางแคชไว้แล้วเมื่อระบบมาภายใต้ความกดดัน mem ...

Cong> ด้านล่างเป็นกรณีทดสอบขนาดเล็กสำหรับแพทช์นี้:

เธรดประกอบด้วยทั้ง testcase และ patch ที่แท้จริงไปยังหลาย ๆ ไฟล์ภายในเคอร์เนล Linux ซึ่งเพิ่มฟังก์ชันเพิ่มเติมเพื่อfs/drop_caches.cเรียกdrop_pagecache_file(struct file *filp)ใช้ ฟังก์ชั่นนี้เป็นแล้วสามารถเข้าถึงได้ผ่านเครื่องมือส่วนหน้า, ผ่านคำสั่งfnctl.c F_DROP_CACHESกรณีนี้เรียกใช้ฟังก์ชันนี้:

file_drop_caches(filp, arg);

ซึ่งจัดการกับการลดลงของแคชทั้งหมดที่เกี่ยวข้องกับไฟล์ที่กำหนด จากไฟล์include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
ดังนั้นสิ่งนี้สามารถใช้?

ฉันไม่พบหลักฐานว่าแพตช์นี้เข้ามาในพื้นที่เก็บข้อมูลโค้ดเคอร์เนลหลักของ Linux ดังนั้นตัวเลือกนี้จะปรากฏขึ้นให้ใช้งานได้เฉพาะในกรณีที่คุณต้องการคอมไพล์เคอร์เนล Linux อีกครั้ง

ศักยภาพวิธี # 2 - การใช้ dd

ddในหัวข้อเดียวกันกับที่ผู้ใช้อื่นกล่าวถึงวิธีการที่แตกต่างอย่างสิ้นเชิงที่ทำให้การใช้

ข้อความต่อไปนี้เป็นข้อความที่ตัดตอนมาจาก

นี่คือฟังก์ชั่นที่มีประโยชน์ แม้ว่าจะไม่ได้บัญญัติไว้แล้วด้วย POSIX_FADV_DONTNEED? ฟังก์ชั่นนี้ถูกบันทึกGNU DD (8.11) ในปีที่ผ่านมา

นี่คือตัวอย่างจากแพทช์ที่:
  • แนะนำให้วางแคชสำหรับไฟล์ทั้งหมด

     $ dd if=ifile iflag=nocache count=0
    
  • ตรวจสอบให้แน่ใจว่าวางแคชสำหรับไฟล์ทั้งหมด

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • วางแคชสำหรับส่วนของไฟล์

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • สตรีมข้อมูลโดยใช้แคชการอ่านล่วงหน้า

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
ทดสอบมันออกมา

ฉันไม่ได้เป็นบวก 100% วิธีทดสอบสิ่งนี้ แต่ฉันคิดวิธีต่อไปนี้

  1. ทำไฟล์ 100MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. ไฟล์การสืบค้นกลับเข้าถึงโดยใช้ fatrace

    $ sudo fatrace | grep sample.txt
    
  3. เรียกใช้topเพื่อให้เราสามารถตรวจสอบการใช้งานหน่วยความจำทราบจำนวนฟรี

    $ top
    
  4. เปิดไฟล์บันทึกจำนวนหน่วยความจำว่างในขณะนี้ หมายเหตุของไฟล์fatracesample.txt

    $ cat sample.txt > /dev/null
    
  5. ปล่อยไฟล์จากหน่วยความจำจำนวนหน่วยความจำว่างในขณะนี้ หมายเหตุ: fatraceการส่งออกของ

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

ตัวอย่าง

ในเทอร์มินัล # 1:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
ในเทอร์มินัล # 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
ในเทอร์มินัล # 3:
$ sudo fatrace | grep sample.txt
ตอนนี้เปิดไฟล์sample.txtและจดบันทึกจำนวน RAM ในเทอร์มินัล # 1
$ cat sample.txt > /dev/null
ในเทอร์มินัล # 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
สังเกตเห็นผลลัพธ์ของfatraceในเทอร์มินัล # 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
ตอนนี้ลบไฟล์ออกจาก RAM ใน terminal # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
บันทึกผลลัพธ์ของfatraceในเทอร์มินัล # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
บันทึกแรมในเทอร์มินัล # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

ดังนั้นดูเหมือนว่าไฟล์ทั้งหมดใน RAM ที่ถูกใช้หมด

ศักยภาพวิธี # 3 - python-fadvise

ขอบคุณที่คอมเมนต์โดย @frostchutz มีเครื่องมืออีกอันสคริปต์ Python ชื่อ[pyadvise][4]ซึ่งให้ส่วนต่อประสานที่ง่ายกว่าddวิธีการด้านบน สคริปต์นี้ใช้ประโยชน์จากposix_fadvise(2)อินเทอร์เฟซเดียวกัน

ตัวอย่าง
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

และถ้าเราทำซ้ำการทดสอบข้างต้นและใช้pyadviseแทนdd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

ddฉันสังเกตเห็นการลดลงเหมือนกันในแรมถูกใช้เป็นมาก่อนเมื่อผมใช้


ddทำงานได้สำหรับฉัน ฉันลงเอยด้วยchris-lamb.co.uk/projects/python-fadviseตัวเองซึ่งเป็นสิ่งเดียวกันในคำสั่งที่ชัดเจนยิ่งขึ้น
frostschutz

@ frostschutz - ยอดเยี่ยมมาก ฉันไม่เคยได้ยินเรื่องนี้จนกว่า Gilles จะถามว่าใครรู้วิธีการทำเช่นนี้ในการแชท เป็นเรื่องง่ายที่ผมได้เพิ่มเป็นตัวอย่างที่แสดงให้เห็นpython-fadvise dd
slm

ลิงค์สำหรับสคริปต์ไพ ธ อนควรถูกย้ายไปที่เนื้อหาหลักของคำถาม ความคิดเห็นสามารถหายไปอย่างไร้ร่องรอย การแก้ไขที่เลวร้ายที่สุดจะยังคงอยู่ในประวัติศาสตร์ ต้องบอกว่าการค้นหาของ Google พบว่าง่ายดายดังนั้นจึงไม่ใช่เรื่องใหญ่
Faheem Mitha

ดูเหมือนว่ามันจะทำงานได้โดยไม่ต้อง sudo ดังนั้นใครก็ตามที่สามารถดูไฟล์ (แม้ไม่ได้รับอนุญาตให้เขียน) สามารถทำให้แคชของมันลดลงนั่นคือ ... น่าสนใจ
frostschutz

1
มีos.posix_fadvise()บรรณารักษ์มาตรฐานของไพ ธ อนในตอนนี้
kawing-chiu

3

การขยายคำตอบของ @ geekosaur คุณสามารถบังคับให้ใช้O_DIRECTโดยใช้ LD_PRELOAD และโปรแกรมได้ที่นี่: http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

รหัสนั้นบังคับO_DIRECTให้สำหรับไฟล์ทั้งหมด อย่างไรก็ตามเพียงเพิ่มตรรกะ strncmp เพิ่มเติมบางรายการใน__do_wrap_openO_DIRECT คุณสามารถเลือกใช้

คำเตือน: ฉันยังไม่ได้ทดสอบนี้


2

คุณสามารถเปิดแต่ละไฟล์ด้วยการO_DIRECTตั้งค่าสถานะ (ดูman 2 open) - อ่านส่วนหมายเหตุของ manpage นั้นอย่างรอบคอบและพิจารณาว่าคุณต้องการ / จำเป็นO_SYNCหรือไม่


1
ขั้นตอนของฉันคือcatและฉันไม่อยากเขียนมันอีก :) ฉันหวังว่าเครื่องมือบรรทัดคำสั่งหรือ/proc/sysลูกบิด
Jay Hacker

2
ยิ่งกว่านั้นฉันสงสัยว่าคุณหมายถึงคุณกำลังใช้การเปลี่ยนเส้นทางดังนั้นกระบวนการของคุณจึงเป็นเชลล์ ฉันไม่รู้จักวิธีต่อไฟล์ในการควบคุมสิ่งนี้นอกเหนือจากการopenตั้งค่าสถานะ แน่นอนคุณจะต้องเขียนโปรแกรมเพื่อทำมัน ( cat -uปิดใช้งานการstdioบัฟเฟอร์เท่านั้นไม่ใช่การบัฟเฟอร์ของระบบปฏิบัติการ)
geekosaur

-2

หากคุณต้องการบังคับให้ไฟล์ใช้ O_SYNC ทุกครั้งคุณสามารถทำเครื่องหมายเป็นเช่นนั้นในแอททริบิวต์ส่วนขยายด้วยchattr +S $file:

ผู้ชาย chattr:

เมื่อไฟล์ที่มีชุดคุณลักษณะ 'S' ถูกแก้ไขการเปลี่ยนแปลงจะถูกเขียนพร้อมกันบนดิสก์ นี่เทียบเท่ากับตัวเลือกการเมาท์ 'ซิงค์' ที่ใช้กับชุดย่อยของไฟล์

O_SYNC บังคับให้ข้อมูล + ข้อมูลเมตาถูกเขียนไปยังดิสก์บัฟเฟอร์ แต่มันยังคงผ่านหน้าแคช O_DIRECT บายพาสแคชหน้า

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

หากคุณมีหน่วยความจำเก็บไฟล์เล็ก ๆ ไว้ที่นั่นคุณสามารถแก้ไขปัญหาด้วยวิธีอื่นได้ ตรวจสอบให้แน่ใจว่าไฟล์ขนาดเล็กอยู่ใน RAM ตลอดเวลาจากนั้นฉันแนะนำให้คัดลอกไฟล์ไปยังtmpfs :

tmpfs ใส่ทุกอย่างลงในแคชภายในเคอร์เนลและขยายและย่อขนาดเพื่อรองรับไฟล์ที่มีอยู่


chattr +Sไม่ได้เป็นสิ่งเดียวกับมันเป็นสิ่งเดียวกับO_DIRECT ทำให้อ่านไม่ถูกแคช (ซึ่งเป็นสิ่งที่คำถามนี้เกี่ยวกับ) และเขียนไม่ให้ถูกบัฟเฟอร์โดยไม่มีการรับประกัน สาเหตุที่เขียนเท่านั้นที่จะไม่ถูกบัฟเฟอร์ O_SYNCO_DIRECTO_SYNC
Gilles 'หยุดชั่วร้าย'

@Gilles คุณถูกต้องฉันอ่านคำถามและคิดเกี่ยวกับการล้างข้อมูลลงดิสก์ตามที่ฉันเคยทำมาก่อน และมีความละเอียดอ่อนอื่น แต่ที่สำคัญในกรณีนี้ความแตกต่างระหว่าง O_DIRECT และ O_SYNC, O_DIRECT เลี่ยงผ่านแคชของหน้า แต่ O_SYNC ไม่ใช่มันบังคับให้ข้อมูล (และเมตาดาต้า) ถูกล้างออกไปยังดิสก์ แต่ผ่านแคชหน้าและ ถูกเก็บไว้ที่นั่นเพื่อเร่งการอ่าน ฉันควรเปลี่ยน O_DIRECT สำหรับ O_SYNC ในคำตอบของฉันเพื่อไม่ให้อยู่กับการยืนยันผิดหรือไม่?
Jorge Nerín

คำถามนี้ถามเกี่ยวกับการเก็บไฟล์ขนาดใหญ่ที่ถูกเขียนออกมาจากแคช ฉันคิดว่าการเปิดไฟล์ด้วย O_DIRECT จะเป็นอันตรายต่อประสิทธิภาพการทำงานและหากไฟล์ขนาดใหญ่มันเพิ่งถูกต่อท้ายความแตกต่างอาจมีขนาดเล็ก แต่ถ้าไฟล์ขนาดใหญ่มันถูกเขียนใหม่ในสถานที่สุ่ม O_DIRECT จะได้รับความนิยมอย่างมากในเรื่องประสิทธิภาพแม้จะคำนึงถึงความเป็นไปได้ว่ามันอาจจะถูกไล่ออกจากแคชของไฟล์อ่านขนาดเล็กบางไฟล์
Jorge Nerín

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