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


35

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

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

編集: 可能な解決策としてrsync、ディスクドライブをRAMドライブと同期するために10秒ごとに実行されるデーモンを起動することを考えました。次に、RAMドライブからコンパイルを実行します。rsync速く燃えるれるが、これは実際に動作しますか?確かにOSの方がうまくいく可能性があります。...


tmpfsとext3 / 4の違いはキャッシュだけではありません。たとえば、ジャーナリングがあり、キャッシングに関係なく書き込まれます。
アンドレパラメス

1
timeあなたの編集と結果を私たちと共有してもらえますか?それはいくつかの論争を払拭するだろう。make clean && /usr/bin/time -v maketimeコマンドに組み込まれているbashを使用しないでください)
シェルホリック

1
@sheなぜbashの組み込みコマンドではないのですか?
シェパン

3
@Tshepang time組み込みbash(help time)はman time、I / O、コンテキストスイッチなどに関するGNU時間()よりも詳細が少ない(冗長オプションなし)
...-shellholic

回答:


18

多くのファイルをキャッシュに保持する明白な方法は、頻繁にアクセスすることです。Linuxはスワッピングとキャッシングの調停にかなり優れているので、速度の違いは、実際にはOSがキャッシュに物を保持していないためではなく、tmpfsの使用と他の試行の違いによるものと思われます。

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

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

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

私もこの気持ちを持っています。コンパイルはIOではなくCPUを集中的に使用します。
プネヘヘ

うーん、ここで@JaredCからのコメントを見て、Gillesの仮説を確認または否定します。1.5 5対minues ...かなり大きな違いである
ダニエル・アルダー

8

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

ポイントはを変更することswappinessです。アクティブプログラム、非アクティブプログラム、ディスクキャッシュの3つの主な種類のメモリ使用について考えてみましょう。明らかに、アクティブなプログラムが使用するメモリはスワップアウトされるべきではなく、他の2つを選択することはまったく任意です。高速プログラム切り替えまたは高速ファイルアクセスが必要ですか?低swappinessををすることを好むメモリ内のプログラムを保つ(長時間使用しない場合でも)と高い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、その他の使用済みプログラムをキャッシュに保持するのに十分な空きメモリが必要です。


これは一般的には便利ですが、私が本当に望んでいるのは、ソースコードのスワップ性を低くすることですが、他のすべては通常のスワップ性を持つことです。基本的に、バックグラウンドで多くの処理を行っていますが、ソースコード用に他の2 GB を常に維持しながら、8 GBのうち6つに制限したいと思います。スワップされる可能性はありません...これは...面倒だからです。
JaredC

Swappinessはシステム全体です。実際、何か他のことをしていて、ファイルがメモリからアンロードされる場合は、2行目でリロードする必要があります。メモリを他の何かのために解放する必要がある場合、スワップからそれを「チャンスを取りたい」とは本当に思わないでしょう。ちなみに、tmpfs同じケースではスワップもされます。
シェルホリック

2
個人的に私は、ワークステーションでは絶対にひどい恐ろしいことをしました。一部の機能はより大きなキャッシュ(つまり、より多くのキャッシュされたファイル)によって加速される可能性がありますが、これには代償が伴います:プログラムを切り替えるときの応答性の観点でこれを支払います。。私を電子メールで送信するために、他のブラウザにオフィスにブラウザから切り替えるときだけでスワップ背面に各プログラムのための1-2秒を待つ必要が我慢できないすべての私のLinuxマシンでは、私は一般的に10の低い値にswappinessを設定
フジシンはモニカを復活させます

6

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


6

inosyncそれのようなデーモンの音を使用すると、RAMディスクにrsyncをするつもりなら、あなたが望むものを正確に行います。10秒ごとにrsyncする代わりに、Linuxのinotify機能を使用して、ファイルが変更されたときにrsyncします。Debianリポジトリでinosyncパッケージとして見つけました。または、そのソースはhttp://bb.xnull.de/projects/inosync/で入手できます。


それは非常に便利に聞こえます。調査して報告します。ありがとう!
JaredC

5

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

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

vmtouch -dl /whatever/directory/

私はそれをrootとして実行する必要がありました sudo


1
新規/削除されたファイルは表示されません。
Vi。

3

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

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

オブジェクトと中間ファイルをディスクではなくRAMに構築します。インクリメンタルビルドを行うと、頻繁にビルドすることで大幅に向上する場合があります。ほとんどのプロジェクトでは、毎日のクリーンビルドとその間の増分ビルドを行います。統合ビルドは常にクリーンビルドですが、1日に1未満に制限しようとしています。

atimeをオフにしてext2パーティションを使用すると、パフォーマンスが向上する場合があります。ソースは、ext3 / 4などのジャーナリングされたファイルシステムでバージョン管理されている必要があります。


2

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

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

ディスクIOを監視することは、ディスクIOの負荷に応じてデータを多かれ少なかれ再読み取りするように信号を送るため、固定間隔を使用するよりも望ましいです。

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.