Linuxファイルシステムキャッシュから特定のファイルを削除しますか?

Linuxファイルシステムキャッシュから特定のファイルを削除しますか?

私もできることを知っていますLinuxファイルシステムキャッシュのすべてのエントリを削除するところで、特定のファイルを1つだけ削除する方法はありますか?それともファイルがキャッシュされないようにしますか?または、プロセスが作成したファイルをキャッシュしないように指示しますか?

多くの小さなファイルを読み取り、1つの大きなファイルに書き込むプロセスがあります。ディスクの検索を避けるために、小さなファイルをキャッシュに保存したいので、大きなファイルキャッシュには興味がありません。

答え1

潜在的な方法 #1 - F_DROP_CACHES

私はこのメールスレッドでLinuxカーネルに提案されたパッチを議論する2012年の方法を見つけました。Re: [RFC パッチ] fs: ファイル別削除キャッシュの実装

抜粋

Cong>ファイル別削除キャッシュを実装するためのドラフトパッチです。

興味深い。では、プロセスの外部でこれを行うことができますか?私はシステム管理者なので、システムがストレスを受けたときにパフォーマンスの問題を見つけて修正することが私の視点です。

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がキャッシュを放棄したはずです。

Cong> 以下は、このパッチの小さなテストケースです。

fs/drop_caches.cこのスレッドには、を呼び出すアドオンを追加するLinuxカーネル内の複数のファイルのテストケースと実際のパッチが含まれています。この機能は、drop_pagecache_file(struct file *filp)フロントエンドツールを介してコマンドを介してアクセスできます。この例では、次の関数を呼び出します。fnctl.cF_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) 1年前

以下はパッチの例です。
  • ファイル全体のキャッシュを削除することをお勧めします

     $ 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. ファイルを開き、現在使用可能なメモリ量を確認します。fatraceこのファイルを注意深く見てくださいsample.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.txtRAMのサイズを確認してください。第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
これで、ターミナル#4のRAMからファイルを削除します。
$ 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のRAMを確認してください。
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

したがって、RAM内のファイルが消費するすべてが解放されたように見えます。

潜在的なアプローチ #3 - python-fadvise

[pyadvise][4]@frostchutzのコメントのおかげで、上記の方法よりも簡単なインターフェースを提供するPython Scriptという別のツールがあります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.

答え2

O_DIRECT@geekosaurの回答を拡張すると、LD_PRELOADとここの手順を使用して強制的に適用できます。http://aighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

このコードはO_DIRECTすべてのファイルで動作します。ただし、strncmpロジックを追加すると、__do_wrap_openO_DIRECTをオプションで適用できます。

免責事項:私はこれをテストしていません。

答え3

このフラグを使用して単一のファイルを開くことができますO_DIRECT(参照man 2 open) - 読み取りノートそのマンページのセクションを注意深く読んで、自分が欲しいかどうかを検討してくださいO_SYNC

答え4

ファイルが常にO_SYNCを使用するようにするには、拡張属性に表示するだけですchattr +S $file

男性チャット:

「S」属性が設定されているファイルが変更されると、変更はディスクに同期的に書き込まれます。これは、ファイルサブセットに適用される「同期」マウントオプションと同じです。

O_SYNCはデータ+メタデータを強制的にディスクバッファに書き込みますが、それでもページキャッシュを通過します。 O_DIRECTはページキャッシュをバイパスします。

ただし、O_DIRECTで開くとパフォーマンスに有害な影響を与える可能性がありますが、大きなファイルを追加するだけでは違いが少なくなる可能性があります。ただし、大容量ファイルを任意の場所に上書きすると、O_DIRECTがキャッシュにあることを考慮してもパフォーマンスに大きな影響を与え、いくつかの小さな読み取りファイルをキャッシュから削除できます。

小さなファイルをすべて保存できるメモリがある場合は、別の方法でこの問題を解決できます。小さなファイルが常にメモリにあることを確認し、そのファイルを次の場所にコピーすることをお勧めします。一時ファイルシステム:

tmpfsはすべてを内部カーネルキャッシュに保存し、埋め込みファイルを収容できるように拡張および縮小します。

関連情報