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


23

Linuxファイルシステムキャッシュからすべてをドロップできることは知っていますが、特定のファイルを1つだけドロップする方法はありますか?または、ファイルがキャッシュされないようにしますか?または、書き込むファイルをキャッシュしないようにプロセスに指示しますか?

多くの小さなファイルを読み取り、大きなファイルを書き込むプロセスがあります。ディスクシークを回避するために小さなファイルをキャッシュに保持したいのですが、大きなファイルをキャッシュする必要はありません。


1
賞金に関しては、タイトルの質問に特に興味がありますキャッシュから特定のファイルをドロップする(そもそもそこに到達するのを防ぐのではなく)。
ジル 'SO-悪であるのをやめる' 14年

回答:


21

潜在的な方法#1-F_DROP_CACHES

このメールスレッドでLinuxカーネルに提案されたパッチについて説明している2012年の方法を見つけました:Re:[RFC Patch] fs:implement per file drop caches

抜粋

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はすでにキャッシュをドロップしているはずだと考えているため、このパッチは何を私たちに買ってくれますか...

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

スレッドには、テストケースと、Linuxカーネル内のいくつかのファイルへの実際のパッチの両方が含まれており、追加の機能がfs/drop_caches.ccalledに追加され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ですか?この機能は1年前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. ファイルを開き、空きメモリの量をメモします。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

@frostchutzのコメントのおかげ[pyadvise][4]で、上記のddメソッドよりもはるかにシンプルなインターフェースを提供するPythonスクリプトという別のツールがあります。このスクリプトは同じ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たときと同じように、RAMの消費量が消費されていることに気付きました。


dd私のために働く。私は終わったchris-lamb.co.uk/projects/python-fadviseより明白なコマンドでも同じことである自分自身を。
frostschutz 14年

@frostschutz-とてもクール。Gillesがチャットでこれを行う方法を知っているかどうかを尋ねるまで、私はこれを聞いていませんでした。python-fadviseの方がはるかに簡単ddです。
slm

pythonスクリプトへのリンクを質問の本文に移動する必要があります。コメントはトレースなしで消えることがあります。編集は最悪の場合でも履歴に残ります。とはいえ、Google検索では簡単に見つけることができるので、大したことではありません。
ファヒームミタ14

sudoがなくても動作するようです。そのため、ファイルを見ることができる人は誰でも(書き込み許可がなくても)キャッシュをドロップできます。
frostschutz 14年

1
現在os.posix_fadvise()、Pythonの標準ライブラリにあります。
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)— そのマンページのNOTESセクションを注意深く読み、必要かどうかも検討してくださいO_SYNC


1
まあ、私のプロセスはcatであり、私はそれを書き直したくない。:)コマンドラインツールまたは/proc/sysノブを望んでいた。
ジェイハッカー

2
さらに悪いことに、リダイレクトを使用しているのではないかと思うので、プロセスはシェルです。私は、openフラグを別にしてこれを制御するファイルごとの方法を知りません。実際にそれを行うにはプログラムを書く必要があります。(OSバッファリングではなく、バッファリングcat -uのみを無効にしますstdio。)
geekosaur

-2

ファイルが常にO_SYNCを使用するように強制する場合は、拡張属性でそのようにマークできますchattr +S $file

男のおしゃべり:

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

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

ただし、O_DIRECTで開くとパフォーマンスが低下することに注意してください。大きなファイルが追加されるだけで、差が小さくなる場合があります。しかし、大きなファイルがランダムな場所で書き換えられた場合、O_DIRECTはパフォーマンスに大きな影響を与えます。キャッシュに格納すると、小さな読み取りファイルの一部がキャッシュから削除される可能性があることを考慮しても。

すべての小さなファイルをそこに保持するRAMがある場合は、別の方法で問題にアプローチできます。小さなファイルが常にRAMにあることを確認してから、それらをtmpfsにコピーすることをお勧めします。

tmpfsは、すべてをカーネルの内部キャッシュに入れ、それに含まれるファイルに合わせて拡大および縮小します


chattr +S同じものではありませんO_DIRECT、それは同じことですO_SYNCO_DIRECT原因は読み込み(この質問があるものについてである)キャッシュされていない、と保証なしで、バッファリングされていない書き込みます。書き込みO_SYNCのみがバッファリングされません。
ジル 'SO-悪であるのをやめる' 14年

@Gillesあなたは正しいです、私は質問を読んで、以前にやったようにデータをディスクにフラッシュすることを考えました。また、この場合重要な別の微妙な違いがあります。O_DIRECTとO_SYNCの違い、O_DIRECTはページキャッシュをバイパスしますが、O_SYNCはそうではなく、データ(およびメタデータ)をディスクに強制的にフラッシュしますが、ページキャッシュを通過し、読み取りを高速化するために保持されます。O_SYNCのO_DIRECTを変更して、間違った肯定を維持しないようにする必要がありますか?
ホルヘネリン​​14年

この質問は、キャッシュから書き出された大きなファイルを保持するかどうかを尋ねます。O_DIRECTで開くとパフォーマンスに悪影響を与えると思います。大きなファイルが追加されるだけの場合、その差は小さいかもしれません。ただし、大きなファイルをランダムな場所で書き換えると、小さな読み取りファイルの一部がキャッシュから削除される可能性があることを考慮しても、O_DIRECTはパフォーマンスに大きな影響を与えます。
ホルヘネリン​​14年

に変更O_DIRECTするO_SYNCと、回答が内部的に一貫したものになりますが、質問を考慮するとまだ間違っています。
ジル「SO-悪であるのをやめる」14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.