追加読書

追加読書

ブライアン・カーニガンが説明します。この動画初期のBell Labsが小さな言語/プログラムに魅力を感じたのは、メモリの制約によるものです。

大きなマシンは64キロバイト(MやGではなくK)を持っているため、個々のプログラムは非常に大きくできないため、小さなプログラムを書くのは自然な傾向があり、基本的には入力出力であるパイプメカニズムがあります。リダイレクトを使用すると、あるプログラムを別のプログラムにリンクできます。

ただし、プログラム間で転送するには、データをRAMに保存する必要があることを考慮すると、これがメモリ使用量を制限する方法はわかりません。

~からウィキペディア:

ほとんどのUnixシリーズシステムではパイプラインのすべてのプロセスが同時に開始されます。、対応するストリームは、適切に接続され、マシン上で実行される他のすべてのプロセスとともにスケジューラによって管理されます。 Unixパイプを他のパイプ実装と区別する重要な側面は、バッファリングの概念です。たとえば、送信者は毎秒5000バイトを生成できますが、受信者はデータを失うことなく1秒あたり100バイトしか許可できません。代わりに、送信プログラムの出力がバッファに格納されます。受信プログラムがデータを読み取る準備が整うと、パイプラインの次のプログラムはバッファからデータを読み取ります。 Linuxでは、バッファサイズは65536バイト(64KB)です。必要に応じて、bfrというオープンソースのサードパーティ製フィルタを使用してより大きなバッファを提供できます。

これはアプレットの目的を完全に崩壊させるので、私をさらに混乱させます(たとえ特定の規模でモジュール化されても)。

最初の問題(メモリ制限がデータサイズに依存する問題)を解決するために私が考えることができる唯一の方法は、大規模なデータセットが当時まったく計算されず、実際の問題はパイプラインです。 。しかし、Wikipediaの引用に太字で表示されている内容を見ると、これさえ私を混乱させます。なぜなら、プログラムは一度に1つずつ実装されていないからです。

これはすべて一時ファイルを使用する場合は意味がありますが、パイプは(スワップを使用しない限り)ディスクに書き込まないことです。

例:

sed 'simplesubstitution' file | sort | uniq > file2

sedファイルを1行ずつ読み、吐き出すことは明らかです。ただし、sortリンクされたビデオではBKが述べたようにピリオドなので、すべてのデータをメモリに読み込む必要があります(それともそうですか?)。それからに渡す必要があります。uniq(私の考えには)一度に1行になります。プログラム。ただし、最初のパイプと2番目のパイプの間には、すべてのデータがメモリに存在する必要があります。そうですか?

ベストアンサー1

データをRAMに保存する必要はありません。読者がそこにいないかフォローできない場合、パイプはライターをブロックします。 Linux(そして私が考えている他のほとんどの実装)には少しバッファリングがありますが、必要ではありません。言ったように追跡装置そしてジェイドBP(望むより後者の答え)、Unixの初期バージョンはディスクへのパイプをバッファリングし、これがメモリ使用量を制限するのに役立つ方法です。処理パイプは小さなプログラムに分割することができ、各プログラムはディスクバッファの制限内でいくつかのデータを処理します。小さなプログラムはメモリを少なくし、パイプを使用すると、処理がシリアル化される可能性があることを意味します。最初のプログラムが実行され、出力バッファを埋め、一時停止され、次に2番目のプログラムがスケジュールされ、バッファを処理するなどの操作を実行します。最新のシステムは初期のUnixシステムよりもはるかに大きく、複数のパイプラインを並列に実行できますが、大量のデータに対しても同様の効果を見ることができます(この技術のバリエーションは「ビッグデータ」処理に使用されます)。

あなたの例では

sed 'simplesubstitution' file | sort | uniq > file2

sedデータは必要に応じて読み取られ、読み取る準備が整うとすぐに書き込まれfileますsortsort準備ができていない場合、書き込みはブロックされます。データはメモリに保存されますが、これは具体的でsortあり、sortすべての問題を処理する準備ができています(ソートするデータ量が多すぎる場合は一時ファイルを使用します)。

以下を実行して、ブロックの動作を確認できます。

strace seq 1000000 -1 1 | (sleep 120; sort -n)

これは大量のデータを生成し、読み取る準備ができていないプロセスに転送します。何もない最初の2分。多くのwrite作業が進行中であることがわかりますが、seqまもなく停止してカーネルによってブロックされ、2分が経過するのを待ちます(システムコールを待つwrite)。

おすすめ記事