ブライアンカーニハンは、このビデオで、メモリの制限に基づいている小さな言語/プログラムへの初期のベル研究所の魅力を説明しています
大きなマシンは64kバイト(MやGではなくK)であるため、個々のプログラムをそれほど大きくすることはできません。そのため、小さなプログラムを作成する傾向があり、基本的にはパイプメカニズムが入力されます。出力リダイレクトにより、あるプログラムを別のプログラムにリンクできるようになりました。
ただし、プログラム間で送信するにはデータをRAMに保存する必要があることを考えると、これによってメモリ使用量がどのように制限されるのかわかりません。
ウィキペディアから:
ほとんどのUnixライクなシステムでは、パイプラインのすべてのプロセスが同時に開始されます[私の強調] 、ストリームが適切に接続され、マシン上で実行されている他のすべてのプロセスとともにスケジューラーによって管理されます。これの重要な側面は、他のパイプ実装とは別にUnixパイプを設定することです。たとえば、送信プログラムは1秒あたり5000バイトを生成し、受信プログラムは1秒あたり100バイトしか受け入れられない場合がありますが、データが失われます。代わりに、送信プログラムの出力はバッファーに保持されます。受信プログラムがデータを読み取る準備ができると、パイプライン内の次のプログラムがバッファから読み取ります。 Linuxでは、バッファーのサイズは65536バイト(64KB)です。必要に応じて、bfrと呼ばれるオープンソースのサードパーティ製フィルターを使用して、より大きなバッファーを提供できます。
これは、小さなプログラムの目的を完全に無効にするため、私をさらに混乱させます(ただし、特定の規模までモジュール化されます)。
私が最初の質問(サイズデータに依存して問題となるメモリ制限)の解決策として考えることができる唯一のことは、大きなデータセットは当時は単純に計算されておらず、パイプラインが解決することを意図していた実際の問題はプログラム自体に必要なメモリの量。しかし、ウィキペディアの引用の太字のテキストを考えると、これでも私を混乱させます。一度に1つのプログラムが実装されていないためです。
一時ファイルが使用された場合、これはすべて非常に理にかなっていますが、パイプはディスクに書き込まないことを理解しています(スワップが使用されていない場合)。
例:
sed 'simplesubstitution' file | sort | uniq > file2
sed
であることは私には明らかです ファイルを読み込んで、1行ずつ吐き出します。しかし、sort
、BKがリンクされた動画で述べているように、終止符であるため、すべてのデータをメモリに読み込む必要があります(または、そうしますか?)。その後、uniq
に渡されます。 、これは(私の考えでは)一度に1行のプログラムになります。しかし、最初のパイプと2番目のパイプの間では、すべてのデータがメモリ内にある必要がありますね。
承認された回答:
データをRAMに保存する必要はありません。リーダーがそこにいないか、追いつけない場合、パイプはライターをブロックします。 Linux(および他のほとんどの実装では想像できます)では、ある程度のバッファリングがありますが、それは必須ではありません。 mtraceurとJdeBP(後者の回答を参照)で述べたように、初期バージョンのUnixはディスクへのパイプをバッファリングし、これがメモリ使用量を制限するのに役立ちました。処理パイプラインを小さなプログラムに分割し、それぞれが一部のデータを処理する可能性があります。 、ディスクバッファの制限内。小さなプログラムはメモリをあまり消費せず、パイプを使用することで処理をシリアル化できます。最初のプログラムが実行され、出力バッファがいっぱいになり、一時停止され、次に2番目のプログラムがスケジュールされ、バッファが処理されます。初期のUnixシステムよりも桁違いに大きく、多くのパイプを並行して実行できます。ただし、大量のデータについても同様の効果が見られます(この種の手法のバリエーションは、「ビッグデータ」処理に使用されます)。
あなたの例では、
sed 'simplesubstitution' file | sort | uniq > file2
sed
file
からデータを読み取ります 必要に応じて、sort
である限り書き込みます それを読む準備ができています。 sort
の場合 準備ができていません、書き込みブロック。データは実際に最終的にメモリに保存されますが、これはsort
に固有のものです。 、およびsort
あらゆる問題に対処する準備ができています(ソートするデータの量が多すぎる場合は一時ファイルを使用します)。
実行するとブロック動作を確認できます
strace seq 1000000 -1 1 | (sleep 120; sort -n)
これにより、かなりの量のデータが生成され、何かを読み取る準備ができていないプロセスにパイプされます。 最初の2分間。いくつかのwrite
が表示されます 操作は実行されますが、非常に迅速にseq
停止し、カーネルによってブロックされて2分が経過するのを待ちます(write
システムコールは待機します)。