端子出力バッファサイズ制限

端子出力バッファサイズ制限

端末アプリケーションがバッファリングしてディスプレイに出力するテキストの量を制限する方法はありますか?

たとえば、stdoutに2,000,000行をできるだけ早く作成するアプリケーションを呼び出すと、アプリケーションはすばやく返されますが、端末は点滅しているテキストの壁を表示して数分後にアイドルプロンプトに戻ります。おそらく、この2,000,000行のテキストがバッファリングされており、ターミナルアプリケーションはバッファを介して動作し、何千ものディスプレイアップデートを生成します。たとえば、まだレンダリングする行が1,000を超える場合、最も古い行が削除されるようにバッファサイズを制限する方法はありますか?

答え1

stdoutに2,000,000行を書き込むアプリケーションをできるだけ早く呼び出すと、アプリケーションがすばやく返される可能性があります。

そのようなことは起こりませんでした。

パイプと同様に、ttyラインも比較的小さいバッファサイズを持ちます。カーネルのターミナルラインバッファサイズは約12kBのようです。

(それはどうすればわかりますか?既存のソースコードを調べたりテストツールを作成したくなかったので、ターミナルエミュレータを起動して使用していたtty行を照会しました(コマンドは次のようになりますtty/dev/pts/5。次に停止しました。端末から非ブロック書き込みを使用して、一部のバイトを端末線に送信しますdd if=/dev/zero of=/dev/pts/5 bs=65536 oflag=nonblock

互いに接続されている複数のバッファがある可能性があります。たとえば、実行中またはtmux類似の場合、データはtty行とtmuxの内部バッファリングの両方を通過するか、sshsshサーバー、ネットワーク、およびsshクライアントを実行している場合は一部追加しますが、合計バッファサイズは処理中のデータ量(1行あたり平均50バイトを仮定すると、約100MB)よりもはるかに低いです。

端子エミュレータはまた、約4~8kB程度の小さなチャンク単位で入力を読み出します。

/proc/<terminal's pid>/fd(どうすればわかりますか?どのファイルディスクリプタがターミナルラインの基本的な側面に対応しているかを確認し、ターミナルエミュレータを追跡して/dev/ptmxこのファイルディスクリプタで読み取ったものを見つけました。)

アプリケーションが読み込み速度が遅いプロセスにデータが多すぎると、アプリケーションは実行する書き込み操作をブロックすることがよくあります。つまり、スローリーダーはライターの速度も遅くします(より正確には、端末が一部のデータを消費し、プロセスがtty行に書き換えられるまでカーネルが別のプロセスを実行できるように定期的に「休止」状態にするです)。 。

自分で確認するには、cat largefile実行に1分かかります。別の端末cat(たとえばpidof cat)で見つかったPIDが12345であるとします。次に、どのfdがcat入力ファイルに接続されているかを確認ls -l /proc/12345/fdし、そのファイルに属する行largefile(おそらくfd番号3)を見つけます。これで、cat入力ファイルを読み取る場所からファイルオフセットを要求しますcat /proc/12345/fdinfo/3。端末がこれらすべてのデータを処理すると、このオフセットはほぼ線形的に増加することがわかります。catビジュアル端末アクティビティが停止する前にもう少し早く終了します(この違いは手動で実行されたコマンドでも測定できない場合があります)。


もっと数分

かなり平均的なノートブックでは、ターミナルエミュレータのパフォーマンスはまともなレベルであり(最高ではありませんが悪くありません)、100 MBのデータを処理するのに約10秒かかります。

何千ものディスプレイを更新

ほとんどすべてのグラフィカル端末エミュレータは、常にディスプレイを更新せずにできるだけ早く入力を処理します(これは耐えられないほど遅い)、時には(理想的には毎秒60回、モニタの更新頻度に合わせて調整されます)、更新するために入力処理をしばらく停止します。表示する。一部の端末エミュレータはこのリフレッシュレートを維持し、一部は処理する入力ストリームが連続しているときに適応的にフレームをスキップします。私のモニターは毎秒約25回ディスプレイを更新します。これは、100MBのストリームを処理するときに約250回です。

コンピュータが悪い、端末エミュレータが悪い、誇張されている、またはデータが大きい。


たとえば、まだレンダリングする行が1,000を超える場合、最も古い行が削除されるようにバッファサイズを制限する方法はありますか?

端末にはそのような機能はありません。

まず、スキップできるかどうかを判断するには、より大きな入力バッファが必要です。通常の動作では、大きな入力バッファは不要なディスプレイ更新遅延を意味する可能性があります。

次に、スクロールバックバッファが破棄され、前の出力を見るためにスクロールバックできなくなります。

第三に、たとえば、色を変更するエスケープシーケンスが欠落している場合、現在の状態も破損する可能性があります。

いいえ、それは完全に間違った特性です。端末エミュレータは受信するすべてのデータを処理する必要があります。


それでは、実行中のプロセスが大量のデータを印刷して数分間待たなければならない場合はどうすればよいですか?

(SIGINT)を使用してプロセスを中断することができますがCtrl+C、それでも機能しない場合は通常、より積極的なCtrl+\(SIGQUIT)を試すことができます。プロデューサーアプリケーションはほとんど確実に実行され続け、中断しない限りこのデータをまだ印刷していないことに注意してください。

他の端末エミュレータタブまたは別のアプリケーションに切り替えて目的の操作を実行してから、この端末に戻ることができます。

短い休憩を取って、ストレッチをして、数秒間遠くを見つめることができますが、これは驚くべきことです。

大量のデータをどれだけ早く処理できるかによって、好みの端末エミュレータを選択できます。

ワークフローから定期的にこのような多くのデータをエンドポイントに送信する場合は、ワークフローを再設計してください。たとえば、特定のアプリケーションの出力をパイプすることで、tail端末エミュレータよりも速くデータを処理できます(該当するデータとはるかに少ない)。

100 MBのデータ(200万行)を端末に送信することは、一般的なワークフローの一部にはならないはずです。人間として、あなたはそれを適切に扱うことはもちろん、探索することもできません。それでは、ポイントは何ですか?端末に送る2M回線はデータではなくゴミだ。これは時々そしてまれに起こる必要があるため、これを待つ必要があるか、アプリケーションを終了してかなり低い詳細レベルで再起動する必要は問題ではありません。

お役に立てば幸いです。

関連情報