限制終端輸出緩衝區大小
有沒有辦法限制終端應用程序緩衝的文本量,以輸出到顯示器?
例如,如果我要呼叫一個盡可能快地將 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 線不是數據,是垃圾。它應該只是偶然發生並且很少發生,因此必須等待它,或者必須終止應用程序並以顯著降低的詳細程度重新啟動它,不應該成為問題。
希望這可以幫助。