Lepaskan file tertentu dari cache sistem file Linux?

23

Saya tahu saya bisa menghapus semuanya dari cache sistem file Linux , tetapi apakah ada cara untuk menjatuhkan hanya satu file tertentu? Atau mencegah file di-cache? Atau katakan proses untuk tidak men-cache file yang ditulisnya?

Saya memiliki proses yang membaca banyak file kecil dan menulis file besar. Saya ingin menyimpan file-file kecil dalam cache untuk menghindari mencari disk, dan saya tidak peduli tentang caching file besar.

Jay Hacker
sumber
1
Mengenai karunia, saya secara khusus tertarik pada pertanyaan judul: menjatuhkan file tertentu dari cache (sebagai lawan mencegahnya dari sana di tempat pertama).
Gilles 'SO- stop being evil'

Jawaban:

21

Metode Potensial # 1 - F_DROP_CACHES

Saya menemukan metode dari 2012 yang membahas tambalan yang diusulkan ke kernel Linux di utas surat ini berjudul: Re: [Patch RFC] fs: menerapkan cache penurunan per file .

kutipan

Cong> Ini adalah draft patch implementasi drop cache per file.

Menarik. Jadi bisakah saya melakukan ini dari luar proses? Saya seorang SysAdmin, jadi POV saya mulai memperhatikan, menemukan, dan memperbaiki masalah kinerja ketika sistem berada di bawah tekanan.

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.

Bagaimana saya bisa tahu berapa banyak cache yang digunakan oleh file? Dan apa dampak kinerja ini ketika dijalankan pada sistem yang sibuk? Dan apa patch ini membeli kita karena saya pikir VM seharusnya sudah menjatuhkan cache setelah sistem datang di bawah tekanan ...

Cong> Di bawah ini adalah test case kecil untuk patch ini:

Utas termasuk testcase dan tambalan aktual ke beberapa file dalam kernel Linux yang menambahkan fungsi tambahan untuk fs/drop_caches.cdipanggil drop_pagecache_file(struct file *filp). Fungsi ini kemudian dapat diakses melalui alat frontend, fnctl.cmelalui perintah F_DROP_CACHES. Kasing ini memanggil fungsi ini:

file_drop_caches(filp, arg);

Yang menangani menjatuhkan semua cache yang terkait dengan file yang diberikan. Dari file include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Jadi ini bisa digunakan?

Saya tidak menemukan bukti bahwa tambalan ini pernah masuk ke repositori kode kernel Linux utama, sehingga opsi ini tampaknya tersedia, hanya jika Anda bersedia mengkompilasi ulang kernel Linux sendiri.

Metode Potensial # 2 - Menggunakan dd

Di utas yang sama, pengguna lain menyebutkan metodologi yang sama sekali berbeda yang memanfaatkan dd.

Berikut ini kutipan dari email itu

Ini adalah fungsi yang berguna. Padahal bukankah sudah disediakan POSIX_FADV_DONTNEED? Fungsionalitas ini ditambahkan ke GNU dd (8.11) setahun yang lalu .

Berikut adalah contoh dari tambalan itu:
  • Anjurkan untuk menjatuhkan cache untuk seluruh file

     $ dd if=ifile iflag=nocache count=0
    
  • Pastikan drop cache untuk seluruh file

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Jatuhkan cache untuk sebagian file

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Alirkan data hanya dengan menggunakan cache baca-depan

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Mengujinya

Saya tidak 100% positif bagaimana menguji ini tetapi saya datang dengan pendekatan berikut.

  1. buat file 100MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. melacak akses file menggunakan fatrace

    $ sudo fatrace | grep sample.txt
    
  3. Jalankan topsehingga kita dapat memantau penggunaan memori, jumlah catatan gratis.

    $ top
    
  4. buka file, catat jumlah memori bebas sekarang. Perhatikan fatracefile tersebut sample.txt.

    $ cat sample.txt > /dev/null
    
  5. jatuhkan file dari memori, catat jumlah memori bebas sekarang. Perhatikan output dari fatrace.

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

Contoh

Di terminal # 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
Di terminal # 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Di terminal # 3:
$ sudo fatrace | grep sample.txt
Sekarang buka file sample.txt,, dan perhatikan jumlah RAM. Di terminal # 1.
$ cat sample.txt > /dev/null
Di terminal # 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Perhatikan output fatracedi terminal # 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
Sekarang hapus file dari RAM, di terminal # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Perhatikan output fatracedi terminal # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Perhatikan RAM di terminal # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Jadi sepertinya semua yang dikonsumsi oleh file dalam RAM dibebaskan.

Metode Potensial # 3 - python-fadvise

Berkat komentar oleh @frostchutz, ada alat lain, skrip Python, bernama [pyadvise][4]yang menyediakan antarmuka yang jauh lebih sederhana daripada ddmetode di atas . Script ini menggunakan posix_fadvise(2)antarmuka yang sama .

Contoh
$ 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

Dan jika kita mengulangi tes di atas dan digunakan pyadvisesebagai pengganti dd:

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

Saya perhatikan penurunan identik dalam RAM yang dikonsumsi seperti sebelumnya ketika saya gunakan dd.

slm
sumber
ddbekerja untukku. Saya berakhir dengan chris-lamb.co.uk/projects/python-fadvise sendiri yang merupakan hal yang sama dalam perintah yang lebih jelas.
frostschutz
@frostschutz - sangat keren. Saya belum pernah mendengar ini sampai Gilles bertanya apakah ada yang tahu bagaimana melakukan ini dalam obrolan. python-fadvisejauh lebih mudah, saya telah menambahkan contoh yang menunjukkan dd.
slm
Tautan untuk skrip python harus dipindahkan ke bagian utama dari pertanyaan. Komentar dapat menghilang tanpa jejak. Hasil edit akan tetap terburuk dalam sejarah. Karena itu, pencarian Google menemukannya dengan mudah, jadi bukan masalah besar.
Faheem Mitha
Bahkan tampaknya berfungsi tanpa sudo, jadi siapa pun yang dapat melihat file (bahkan tanpa izin menulis) dapat memiliki cache-nya turun, itu ... menarik.
frostschutz
1
Ada os.posix_fadvise()dalam libray standar Python sekarang.
kawing-chiu
3

Memperluas jawaban geekosaur, Anda dapat memaksakan penggunaan O_DIRECTdengan menggunakan LD_PRELOAD dan programnya di sini: http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

Kode itu memaksa O_DIRECTsemua file. Namun, cukup menambahkan beberapa logika strncmp di __do_wrap_openAnda dapat menerapkan O_DIRECT secara selektif.

Penafian: Saya belum menguji ini.

Mark Wagner
sumber
2

Anda dapat membuka file individual dengan O_DIRECTflag (lihat man 2 open) - baca bagian CATATAN dari halaman manual itu dengan hati-hati, dan pertimbangkan apakah Anda juga menginginkan / membutuhkan O_SYNC.

geekosaurus
sumber
1
Ya, proses saya adalah cat, dan saya lebih suka tidak menulis ulang. :) Saya berharap untuk alat baris perintah atau /proc/systombol.
Jay Hacker
2
Lebih buruk dari itu, saya curiga Anda benar-benar bermaksud menggunakan redirection, jadi proses Anda adalah shell. Saya tidak tahu cara per file untuk mengontrol ini selain dari openbendera; Anda memang perlu menulis sebuah program untuk melakukannya. ( cat -uhanya menonaktifkan stdiobuffering, bukan buffering OS.)
geekosaur
-2

Jika Anda ingin memaksa file untuk selalu menggunakan O_SYNC, Anda dapat menandainya sebagai atribut tambahan dengan chattr +S $file:

man chattr:

Ketika file dengan set atribut 'S' dimodifikasi, perubahan ditulis secara sinkron pada disk; ini sama dengan opsi mount 'sync' yang diterapkan pada subset file.

O_SYNC memaksa data + metadata untuk ditulis ke buffer disk, tetapi masih melewati cache halaman. O_DIRECT mem-bypass cache halaman.

Namun ketahuilah bahwa membukanya dengan O_DIRECT akan merusak kinerja, jika file besar itu hanya ditambahkan, perbedaannya mungkin kecil. Tetapi jika file besar itu telah ditulis ulang di tempat-tempat acak O_DIRECT akan menjadi hit besar pada kinerja, bahkan dengan mempertimbangkan bahwa itu dalam cache mungkin dapat mengusir dari cache beberapa file kecil yang dibaca.

Jika Anda memiliki ram untuk menyimpan semua file kecil di sana, Anda bisa mendekati masalahnya dengan cara lain. Pastikan file kecil selalu di ram, maka saya sarankan untuk menyalinnya ke tmpfs :

tmpfs menempatkan semuanya ke dalam cache internal kernel dan tumbuh dan menyusut untuk mengakomodasi file yang dikandungnya

Jorge Nerín
sumber
chattr +Sbukan hal yang sama dengan O_DIRECT, itu adalah hal yang sama dengan O_SYNC. O_DIRECTmenyebabkan membaca tidak akan di-cache (yang adalah tentang pertanyaan ini), dan menulis untuk tidak di-buffer, tanpa jaminan. O_SYNChanya menyebabkan menulis tidak buffered.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Anda benar, saya membaca pertanyaan dan berpikir tentang membuang data ke disk seperti yang telah saya lakukan sebelumnya. Dan ada perbedaan lain yang halus, tetapi penting dalam hal ini, antara O_DIRECT dan O_SYNC, O_DIRECT mem-bypass cache halaman, tetapi O_SYNC tidak, itu memaksa data (dan metadata) untuk disiram ke disk, tetapi melewati cache halaman dan disimpan di sana untuk mempercepat membaca. Haruskah saya mengubah O_DIRECT untuk O_SYNC dalam jawaban saya agar tidak membiarkannya tetap dengan afirmasi yang salah?
Jorge Nerín
Pertanyaan ini menanyakan tentang menyimpan file besar yang telah dihapus dari cache. Saya pikir membukanya dengan O_DIRECT akan merusak kinerja, dan jika file besar itu hanya ditambahkan perbedaannya mungkin kecil. Tetapi jika file besar itu telah ditulis ulang di tempat-tempat acak O_DIRECT akan menjadi hit yang sangat besar pada kinerja, bahkan dengan mempertimbangkan bahwa itu dapat mengusir dari cache beberapa file kecil yang telah dibaca.
Jorge Nerín
Mengubah O_DIRECTke O_SYNCakan membuat jawaban Anda konsisten secara internal, tetapi masih salah mempertimbangkan pertanyaan itu.
Gilles 'SANGAT berhenti menjadi jahat'