web-dev-qa-db-ja.com

なぜ頭なのか。大きなファイルの末尾に時間がかかる場合とそうでない場合があります。

.txtファイルの最初の10行と最後の10行を読み取るbashスクリプトを書いています。開始(ヘッド)と完了(テール)を探し、grepを使用して発生数を比較します。ファイルが非常に大きいため、テキスト全体ではなく、ファイルの先頭と末尾のみを読み取ることにしました。ただし、スクリプトを実行すると、大きなファイルが「終了」するまでに長い時間がかかります(最初の10行と最後の10行の読み取りと比較で構成され、1、2秒しかかからないタスクです)。

スクリプトの出力テキストを見ていると、この問題に気づきました。そこで、コマンドラインから直接head/tail(およびスクリプトで実行されているものをシミュレートするためのgrep)コマンドを実行した場合にも、同様の時間がかかるかどうかを確認することにしました。驚いたことに、コマンドはほぼ瞬時に実行されました。これは奇妙だと思い、スクリプトをもう一度実行しました。今回は、スクリプトは、head/tail/grepコマンドをまだ実行していない次の「大きな」ファイルに到達するまで、前にスタックしていたファイルを介して悲鳴を上げていました。

これは私に考えさせられました、bashはキャッシュと同様のコマンドの結果を保存しますか?また、これらのコマンドの原因は次のとおりです。

 head -n 10 /file/path/myfile.txt | grep -w -c 'lead Word'
 tail -n 10 /file/path/myfile.txt | grep -w -c 'end Word'

実行に時間がかかるのですか?

編集:問題の原因となっているのが上記のヘッド/テールラインであると私が思う理由は、ヘッド/テールの完了時に個別に印刷するエコーラインがあるためです。ファイルの行サイズを確認しましたが、数分以内に終了するファイルよりもそれほど長くはありません。

誰かが私にヘッド/テールがより技術的なレベルでどのように機能するかについてのより詳細な説明を教えてもらえますか?ファイルの「最初/最後のx行」について、非常に基本的な理解があります。

2
Racehorse35

いいえ、出力は実行ごとに変わる可能性があるため、bashはコマンドの出力をキャッシュしません。 bashには、ファイルが別のプロセスによって変更されたかどうかを追跡する確実な方法がありません。これは重要であるため、bashはキャッシュされた結果がまだ有効かどうかを判断できます。

ただし、ここでは他にもさまざまなことが行われています。シェル(bashなど)を使用すると、システムの複数の部分を同時に操作できます。例えば:

  • シェル自体
  • GNU Readlineは、複数のシェルやその他のツールで使用される行編集インターフェースです。
  • libc実装。これは、ほとんどすべてのプログラムで時々混乱する動作を引き起こす可能性があります。
  • 奇妙な動作をする可能性があり、実際には 独自のコマンド に応答できる端末自体。 (例: Backspack そして Delete 利用できないか、交換されている可能性があります)
  • ターミナルが内部に存在するGUIウィンドウ(該当する場合)。例えば。 [〜#〜] ime [〜#〜] を含めることができます。これにより、特殊なキーシーケンス(たとえば、 Ctrl+Shift+u 数字が続きます。)
  • すべてのモジュールとドライバーを含むカーネル
  • もちろん、ハードウェア自体は、過熱、短絡、電源の緩みなどが発生する可能性があります。

この場合、最大の貢献者はbash自体ではなく、ファイルシステムレベルのキャッシュメカニズムがカーネルに実装されていると言えます。ファイルを一度読み取ると、その大部分がファイルシステムキャッシュに保存される可能性があります。これは、この目的のために予約されているメモリの塊です。

ファイルに対して2回目の操作を実行するとき、シェルは物理ハードウェアの読み取りを再度トリガーしませんが、代わりにキャッシュからファイルの内容を取得します。 bashで(再)実行するほぼすべての操作は、ディスクの読み取りに比べて非常に高速です。遅いディスクの読み取りが欠落しているため、bashが実際にコマンドを再実行していることに気付かないのはそのためです。

1
jpaugh