Terminal

限制終端輸出緩衝區大小

  • March 18, 2022

有沒有辦法限制終端應用程序緩衝的文本量,以輸出到顯示器?

例如,如果我要呼叫一個盡可能快地將 2,000,000 行寫入標準輸出的應用程序,該應用程序可能會很快返回,但終端可能會在返回空閒提示之前再花幾分鐘顯示閃爍的文本牆。大概這 2,000,000 行文本已被緩衝,並且終端應用程序正在通過緩衝區工作,生成數千個顯示更新。有沒有辦法限制緩衝區大小,如果有超過例如 1,000 行要渲染,最舊的就被丟棄?

如果我要呼叫一個盡可能快地將 2,000,000 行寫入標準輸出的應用程序,該應用程序可能會很快返回

這不是它的工作原理。

與管道類似,tty 行也具有相對較小的緩衝區大小。在我看來,終端行的核心緩衝區大小約為 12 kB。

(我怎麼知道?我不想研究任何現有的原始碼,也不想編寫測試工具。所以我啟動了一個終端模擬器,查詢它正在使用的 tty 行(tty命令,假設它說/dev/pts/5),然後凍結它通過發送 SIGSTOP。然後,從另一個終端,我使用非阻塞寫入向其終端行發送了一些字節:dd if=/dev/zero of=/dev/pts/5 bs=65536 oflag=nonblock。)

可能有多個緩衝區相互連接,例如,如果您正在執行tmux或類似情況,那麼數據會通過兩條 tty 線路以及 tmux 的內部緩衝,或者如果您ssh在 ssh 伺服器、網路和 ssh 客戶端上工作還要添加一些緩衝區,但是您將擁有的整體緩衝區大小仍然比您正在處理的數據量低很多(大約 100 MB,假設平均每行 50 個字節)。

終端仿真器也以類似的小塊讀取它們的輸入,例如大約 4 - 8 kB。

(我怎麼知道?我檢查了/proc/<terminal's pid>/fd哪個文件描述符對應於終端行的主端/dev/ptmx,並 strace’d 終端仿真器從這個 fd 中尋找讀取。)

當應用程序將這麼多數據發送到讀取速度很慢的程序時,應用程序通常會阻塞它執行的寫入操作。換句話說,讀慢導致寫也跑慢(更準確地說:有規律地進入“睡眠”狀態,這樣核心就可以執行其他程序,直到終端消耗了一些數據,程序可以寫再次到 tty 線)。

自己看:開始一個cat largefile需要一分鐘左右的時間。在另一個終端中找到cat的 PID(例如pidof cat),假設它是 12345。然後查看哪個 fd 連接到cat的輸入文件:ls -l /proc/12345/fd,找到屬於 的行largefile,很可能是 fd 編號 3。現在詢問文件偏移量在哪個cat位置,讀取其輸入文件:cat /proc/12345/fdinfo/3. 您會注意到,當終端處理所有這些數據時,這個偏移量幾乎呈線性增長;並且cat只會在視覺終端活動停止之前退出一點點(這種差異甚至可能無法通過手動執行的命令來衡量)。


再過幾分鐘

在我相當普通的筆記型電腦上,帶有一個性能相當不錯的終端仿真器(不是最好的,但也不錯),處理 100 MB 的數據大約需要 10 秒。

數以千計的顯示更新

幾乎每個圖形終端仿真器都盡可能快地處理輸入,而不會一直更新顯示(這將是難以忍受的慢),有時(理想情況下每秒 60 次,調整為顯示的刷新率)會短暫停止處理輸入為了更新顯示。一些終端模擬器保持這個刷新率,如果有連續的輸入流要處理,一些終端模擬器會自適應地跳過幀。我的顯示器每秒刷新大約 25 次,即在處理 100 MB 流期間大約刷新 250 次。

您要麼擁有性能不佳的電腦或性能不佳的終端仿真器,要麼誇大其詞,或者您的數據更大。


有沒有辦法限制緩衝區大小,如果有超過例如 1,000 行要渲染,最舊的就被丟棄?

終端沒有這樣的功能。

首先,他們需要一個更大的輸入緩衝區,以確定他們是否可以進行這種跳過。大的輸入緩衝區可能意味著在正常操作下不必要的顯示更新延遲。

其次,您的回滾緩衝區將被破壞,您將無法回滾以查看先前的輸出。

第三,即使是目前狀態也可能被破壞,例如,如果它錯過了改變顏色的轉義序列或類似的東西。

不,這將是一個完全錯誤的特徵。終端仿真器必須處理它們收到的所有數據。


那麼,如果有一個正在執行的程序會列印出如此多的數據,以至於您必須等待幾分鐘,您該怎麼辦?

您可以使用 (SIGINT) 中斷該過程Ctrl+C,或者如果這不起作用,您可以嘗試通常更具侵略性的Ctrl+\(SIGQUIT)。請記住,生產者應用程序幾乎肯定仍在執行並且尚未列印這些數據——除非您將其中止。

你可以切換到不同的終端模擬器選項卡或不同的應用程序,在那裡做任何你想做的事情,然後再回到這個終端。

你可以稍作休息,伸展一下,凝視遠處的某個點幾秒鐘,這很好。

您可以根據處理大量數據的速度來選擇您喜歡的終端仿真器。

如果您的工作流程經常涉及將這麼多數據發送到您的終端,那麼重新設計您的工作流程。例如,將給定應用程序的輸出通過管道tail傳輸,顯然,它可以比終端仿真器更快地處理數據(它與該數據的關係要少得多)。

向終端發送 100 MB 數據(200 萬行)不應該成為您正常工作流程的一部分。你作為一個人將無法瀏覽它,更不用說正確處理它了,那有什麼意義呢?發送到終端的 2M 線不是數據,是垃圾。它應該只是偶然發生並且很少發生,因此必須等待它,或者必須終止應用程序並以顯著降低的詳細程度重新啟動它,不應該成為問題。

希望這可以幫助。

引用自:https://unix.stackexchange.com/questions/694666