web-dev-qa-db-ja.com

ディレクトリを常にキャッシュに入れる

私は、c ++プロジェクト全体をコンパイルするのにかかる時間を短縮するために、さまざまな方法をテストしてきました。現在、約5分かかります。 distccやccacheなどを試しました。最近、プロジェクト全体をRAMドライブにコピーし、そこからコンパイルすると、コンパイル時間が元の30%に短縮され、わずか1.5分であることがわかりました。

明らかに、RAM=ドライブから作業することは現実的ではありません。そのため、誰かが私ができる方法を知っていますかOSに常に特定のディレクトリをキャッシュしておくことを強制します?Iそれでもディレクトリを通常どおりディスクに同期させたいのですが、常にメモリ内のデータのコピーも必要ですが、これは可能ですか?

編集:可能な解決策として、10秒ごとにrsyncを実行するデーモンを起動して、ディスクドライブをRAM =ドライブ。次に、RAMドライブからコンパイルを実行します。rsyncは非常に高速ですが、これは本当に機能しますか?確かに、OSの方がより良いでしょう...

37
JaredC

多数のファイルをキャッシュに保持する明白な方法は、頻繁にアクセスすることです。 Linuxはスワッピングとキャッシングの仲裁に長けているので、速度の違いは実際にはOSがキャッシュに物を保持していないためではなく、tmpfsの使用と他の試みの間のその他の違いによるものだと思います。

何が行われているかを観察してみてくださいIOそれぞれの場合。そのための基本的なツールは iotop です。他のツールが役立つ場合があります。詳細は LinuxディスクIO負荷の内訳、ファイルシステムパスまたはプロセス、あるいはその両方によって?Linuxのどのプログラムが時間の経過とともにI/Oを測定できるか? 、およびその他のスレッドサーバー障害時。

何が起こっているのかに関するいくつかの仮説を以下に示します。測定する場合は、これらの仮説を確認または反証できるように、それらを提示してください。

  • ファイル access times がオンになっている場合、OSはこれらのアクセス時間を書き込むのにかなりの時間を浪費する可能性があります。アクセス時間はコンパイルツリーには役に立たないため、noatimeマウントオプションでアクセス時間をオフにしてください。 tmpfs + rsyncソリューションはハードディスクからreadsしないので、何度も書き込みに余分な時間を費やす必要はありません。
  • 書き込みが synchronizing の場合、コンパイラーがsync()を呼び出すか、カーネルが出力バッファーを頻繁にフラッシュするため、tmpfsよりもハードディスクへの書き込みに時間がかかります。

LinuxデフォルトではRAMをディスクキャッシュとして使用します。デモンストレーションとして、time find /some/dir/containing/a/lot/of/files > /dev/null 2回、すべてのディスクiノードがキャッシュされるため、2回目ははるかに高速です。ここでのポイントは、このカーネル機能を利用し、それを置き換える試みを止める方法です。

ポイントはswappinessを変更することです。メモリ使用の3つの主なタイプ、アクティブプログラム、非アクティブプログラム、およびディスクキャッシュについて考えてみましょう。明らかに、アクティブなプログラムが使用するメモリはスワップアウトされるべきではなく、他の2つのメモリの選択は非常に恣意的です。高速プログラムスイッチングまたは高速ファイルアクセスをご希望ですか? 低swappinessメモリにプログラムを保持する(長時間使用されない場合でも)を好むhigh swappinesskeepを好むより多くのディスクキャッシュ(未使用のプログラムを交換することにより)。 (swappinessスケールは0から100で、デフォルト値は60です)

あなたの問題に対する私の解決策は、swappinessを非常に高く(100と言っても90-95に)変更し、キャッシュをロードすることです:

echo 95 | Sudo tee /proc/sys/vm/swappiness > /dev/null # once after reboot
find /your/source/directory -type f -exec cat {} \; > /dev/null

ご想像のとおり、すべてのソースファイルとオブジェクトファイル、コンパイラ、インクルードされたヘッダーファイル、リンクされたライブラリ、IDEおよびその他の使用されているプログラムをキャッシュに保持するのに十分な空きメモリが必要です。

8
shellholic

特定のファイルまたはすべてのファイルをキャッシュ内の特定のディレクトリに保持したい場合、このことがうまくいくようです。

vmtouch はまさにそれを行うようです。例5必要なものがあるかもしれません。

vmtouch -dl /whatever/directory/

Sudoを使用してrootとして実行する必要がありました

6
Highstaker

キャッシュの強制は、これを行うための正しい方法ではありません。ソースをハードドライブに保持し、tmpfsでコンパイルすることをお勧めします。 qmakeやCMakeなどの多くのビルドシステムは、ソース外のビルドをサポートしています。

6
gelraen

inosyncデーモンは、ramdiskへのrsyncを実行する場合に、望みどおりの動作をするように聞こえます。 10秒ごとにrsyncする代わりに、ファイルが変更されたときにLinuxのinotify機能を使用してrsyncします。私はそれをinosyncパッケージとしてDebianリポジトリで見つけました、またはそのソースは http://bb.xnull.de/projects/inosync/ で入手できます。

6
Jander

十分なメモリがある場合、ramdiskからのビルドはI/Oを行いません。これにより、ファイルの読み取りや書き込みを高速化できます。 I/Oは最も遅い操作の1つです。ビルドの前にすべてをキャッシュしても、影響は最小限に抑えられますが、書き込み用のI/Oは残っています。

すべてのファイルをキャッシュにプリロードすることで速度が向上する可能性がありますが、それにかかる時間は合計ビルド時間に含まれる必要があります。これはあなたに多くの利点を与えないかもしれません。

オブジェクトと中間ファイルをディスクではなくRAMにビルドします。インクリメンタルビルドを実行すると、頻繁なビルドで大幅な利益が得られる場合があります。ほとんどのプロジェクトでは、間にクリーンビルドとインクリメンタルビルドを毎日行っています。統合ビルド常にクリーンビルドですが、私はそれらを1日あたり1つ未満に制限しようとしています。

Atimeをオフにしてext2パーティションを使用すると、パフォーマンスが向上する場合があります。ソースは、ext3/4のようなジャーナルファイルシステムのバージョン管理下にある必要があります。

3
BillThor

前に述べたように、明白な方法は、キャッシュしたいもののすべてのディレクトリ構造とファイルの内容を読み取ることです。

vmstat 1の出力を監視するスクリプトを記述して(OSに相当するツールを使用して)、これを自動化し、書き込みと読み取りのブロック数の合計を維持できます。合計が選択したしきい値を超えたら、キャッシュするすべてのファイルを読み取り、合計をリセットしてから、vmstat出力の監視を続けます。ファイルをすばやく読み取る場合:ツリーに多数のファイルが含まれている場合は、find ... -exec catを避け、代わりにfind ... -print0 | xargs -0 catまたは各ファイルに対してcatを実行しないカスタムプログラムを試してください。

ディスクIOの負荷に応じてデータを何度も再読み取りするように通知するため、固定間隔を使用するよりもディスクIOを使用することをお勧めします。

この自動化された方法は、ハードディスクドライブのI/Oを回避するために常に高速であるようにいくつかのインデックスファイルの読み取りが必要なシステムでうまく使用しました。また、straceを使用して、ログイン時にアクセスされるすべてのファイルのリストを作成しました。これにより、高速ログインのためにすべてをキャッシュ内でホットに保つことができます。

これは最善の解決策ではないかもしれませんが、私にはよく合いました。

2
filebarn

この script はディレクトリをキャッシュに保存します。

スクリプトは各ディレクトリをループし、ディレクトリの一部を読み取り、5秒間スリープします。スクリプトはバックグラウンドで実行され、各ディレクトリをキャッシュに保存します。

echo $smallnumber > /proc/sys/vm/vfs_cache_pressureは、Linuxがディレクトリキャッシュを自動的に調整する方法です。このスクリプトと連携して、最近使用されたディレクトリをLinuxに通知します。

0
marinara