터미널 애플리케이션이 버퍼링하고 디스플레이에 출력하는 텍스트의 양을 제한하는 방법이 있습니까?
예를 들어, 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의 내부 버퍼링을 모두 통과하거나 ssh
ssh 서버, 네트워크 및 ssh 클라이언트를 실행 중인 경우 일부 추가 하지만 전체 버퍼 크기는 처리 중인 데이터의 양(행당 평균 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
시각적 터미널 활동이 중지되기 전에 조금 더 일찍 종료됩니다(이 차이는 수동으로 실행된 명령으로도 측정할 수 없을 수도 있습니다).
몇 분 더
상당히 평균적인 노트북에서 터미널 에뮬레이터 성능은 괜찮은 수준이며(최고는 아니지만 나쁘지는 않음) 100MB의 데이터를 처리하는 데 약 10초가 걸립니다.
수천 개의 디스플레이 업데이트
거의 모든 그래픽 터미널 에뮬레이터는 항상 디스플레이를 업데이트하지 않고 가능한 한 빨리 입력을 처리하며(이는 견딜 수 없을 정도로 느립니다) 때로는(이상적으로는 초당 60회, 모니터의 새로 고침 빈도에 맞게 조정됨) 업데이트하기 위해 입력 처리를 잠시 중지합니다. 표시하다. 일부 터미널 에뮬레이터는 이 새로 고침 빈도를 유지하고 일부는 처리할 입력 스트림이 연속적으로 있을 때 적응적으로 프레임을 건너뜁니다. 내 모니터는 초당 약 25회 디스플레이를 새로 고칩니다. 이는 100MB 스트림을 처리할 때 약 250회입니다.
컴퓨터가 좋지 않거나 터미널 에뮬레이터가 좋지 않거나 과장되었거나 데이터가 더 큽니다.
예를 들어 아직 렌더링할 행이 1,000개가 넘는 경우 가장 오래된 행이 삭제되도록 버퍼 크기를 제한하는 방법이 있습니까?
터미널에는 그러한 기능이 없습니다.
첫째, 건너뛰기를 할 수 있는지 여부를 결정하려면 더 큰 입력 버퍼가 필요합니다. 정상 작동 시 큰 입력 버퍼는 불필요한 디스플레이 업데이트 지연을 의미할 수 있습니다.
둘째, 스크롤백 버퍼가 파괴되어 이전 출력을 보기 위해 뒤로 스크롤할 수 없게 됩니다.
셋째, 예를 들어 색상을 변경하는 이스케이프 시퀀스가 누락된 경우 현재 상태도 손상될 수 있습니다.
아니요, 그것은 완전히 잘못된 특성입니다. 터미널 에뮬레이터는 수신하는 모든 데이터를 처리해야 합니다.
그렇다면 실행 중인 프로세스가 많은 양의 데이터를 인쇄하고 몇 분 동안 기다려야 한다면 어떻게 해야 할까요?
(SIGINT)를 사용하여 프로세스를 중단 할 수 있으며 Ctrl+C
, 그래도 작동하지 않으면 일반적으로 더 공격적인 Ctrl+\
(SIGQUIT)을 시도할 수 있습니다. 생산자 애플리케이션은 거의 확실하게 계속 실행 중이며 중단하지 않는 한 이 데이터를 아직 인쇄하지 않았다는 점을 명심하세요.
다른 터미널 에뮬레이터 탭이나 다른 애플리케이션으로 전환하여 원하는 작업을 수행한 다음 이 터미널로 돌아올 수 있습니다.
짧은 휴식을 취하고, 스트레칭을 하고, 몇 초 동안 먼 곳을 응시할 수 있는데, 이는 놀라운 일입니다.
대량의 데이터를 얼마나 빨리 처리할 수 있는지에 따라 선호하는 터미널 에뮬레이터를 선택할 수 있습니다.
워크플로에서 정기적으로 이렇게 많은 데이터를 엔드포인트로 보내는 경우 워크플로를 다시 설계하세요. 예를 들어 특정 애플리케이션의 출력을 파이프하면 tail
터미널 에뮬레이터(해당 데이터와 관련이 훨씬 적음)보다 더 빠르게 데이터를 처리할 수 있습니다.
100MB의 데이터(200만 행)를 터미널로 보내는 것은 일반적인 작업 흐름의 일부가 되어서는 안 됩니다. 인간으로서 당신은 그것을 적절하게 처리하는 것은 물론이고 탐색할 수도 없습니다. 그렇다면 요점은 무엇입니까? 단말로 보내는 2M 회선은 데이터가 아니라 쓰레기다. 이는 가끔 그리고 드물게 발생해야 하므로 이를 기다려야 하거나 애플리케이션을 종료하고 상당히 낮은 상세 수준으로 다시 시작해야 하는 것은 문제가 되지 않습니다.
도움이 되었기를 바랍니다.