터미널 에뮬레이터가 텍스트 기반 애플리케이션을 그릴 때 여전히 시각적 아티팩트가 있는 이유는 무엇입니까? 이는 아티팩트 없는 앤티앨리어싱 벡터 글꼴을 포함하여 3D 게임 및 GUI 창을 렌더링하는 최신 컴퓨터에서 작동합니다.
화면 업데이트 프로세스의 중간 단계를 나타내는 다음과 같은 아티팩트를 자주 볼 수 있습니다.
- 터미널 커서 이동(업데이트 중에 커서가 화면에서 깜박이거나 점프합니다.)
- 눈물(화면의 일부에는 오래된 콘텐츠가 표시되고 다른 부분에는 새로운 콘텐츠가 표시됩니다)
- 스크롤(새 스크롤 위치가 즉시 표시되지 않고 스크롤이 눈에 띕니다)
이러한 아티팩트는 1초 미만의 간격으로만 나타나며 대부분의 화면 업데이트 중에는 나타나지 않습니다. 하지만 깜박임 없는 GUI에서 자란 저는 여전히 이를 방지하는 방법이 궁금합니다. 좀 더 복잡한 화면을 그리기 시작하면 위의 모든 아티팩트(스크롤 제외)를 다음 ASCIInema 비디오에서 볼 수 있습니다.MapSCII - 콘솔에서 전 세계를 만나보세요!
느린 업데이트에 대해서도 구체적으로 말하는 것이 아닙니다. 업데이트가 항상 즉시 이루어지면 좋겠지만, 네트워크 및 처리 지연으로 인해 이것이 항상 가능하지는 않습니다. 여기서 말하는 의미는 부분적으로 그려진 화면이 잠깐 보이는 경우가 많다는 것입니다. 대부분의 최신 GUI에서는 완전히 완성된 화면만 사용자에게 표시되며 부분적으로 그려진 아티팩트는 매우 드뭅니다.
내 생각에 터미널 에뮬레이션 파이프라인은 다음과 같습니다.
- 사용자가 키보드의 키를 누른다
- 커널은 키보드 드라이버에서 윈도우 시스템으로 키 입력을 전달합니다.
- 윈도우 시스템은 키 누르기를 터미널 에뮬레이터에 전달합니다.
- 터미널 에뮬레이터는 키 누르기를 의사 터미널(pty) 커널 장치에 전달합니다.
- Pty는 키 입력을 해석하고 결과를 텍스트 기반 애플리케이션에 전달합니다.
- 애플리케이션은 키 누름에 응답하여 명령을 실행합니다.
- 애플리케이션은 내부 버퍼에 새 화면(문자 셀 그리드)을 렌더링합니다.
curses
문자 셀 그리드를 ANSI 이스케이프 코드로 변환하여 터미널에 해당 화면을 렌더링하는 애플리케이션 호출 또는 기타 라이브러리- 라이브러리는 이러한 ANSI 이스케이프 코드를 pty 장치에 기록합니다.
- Pty는 어떤 방식으로든 기록된 데이터를 처리합니다.
- 터미널 에뮬레이터는 pty에서 일부 청크의 처리된 데이터를 읽습니다.
- 터미널 에뮬레이터는 윈도우 시스템을 호출하여 터미널 창에 ANSI 이스케이프 코드의 결과를 렌더링합니다.
위 단계 중 터미널 에뮬레이터가 최종 결과 대신 중간 렌더링 단계를 표시하도록 프로세스 속도를 늦출 수 있는 단계는 무엇입니까?
하드웨어 터미널(직렬 포트 연결)의 속도는 하드웨어에 따라 결정되는 것 같습니다.전송 속도변경할 수 있지만
tcsetattr()
여러 소스를 통해 전송 속도 설정이 터미널 에뮬레이터에서 사용하는 의사 터미널(pty) 장치에 영향을 미치지 않는다는 것을 알고 있습니다. 이것은 Unix 커널이 의도적으로 pty 통신 속도를 제한하지 않는다는 것을 의미합니까?애플리케이션이나 렌더링 라이브러리(저주 등)가 텍스트와 ANSI 코드를 한 번의 쓰기로 보내는 대신 여러 번 쓰기로 보내나요
write()
?Unix 커널에는 내부 I/O 버퍼에 대한 크기 제한이 있으며, 이는 무엇보다도 차단 없이 파이프를 통해 전송할 수 있는 최대 데이터 양에 영향을 미칩니다. 이것이 많은 세부 사항(텍스트 화면, 다양한 색상 등)이 포함된 터미널 화면 렌더링에 영향을 줍니까? 결합된 텍스트와 ANSI 이스케이프 코드는 pty 드라이버의 버퍼에 맞지 않는 너무 많은 데이터를 생성하여 화면 업데이트를 응용 프로그램에 대한 여러 쓰기와 터미널 에뮬레이터에 대한 여러 쓰기 작업으로 나눌 수 있다고 생각합니다. 터미널 에뮬레이터가 다음 읽기를 처리하기 전에 각 읽기의 결과를 표시하려고 하면 배치의 최종 읽기가 처리될 때까지 디스플레이가 깜박이게 됩니다.
터미널 에뮬레이터 또는 pty 드라이버는 의도적으로 배치 시간 초과를 설정하여 해당 동작이 하드웨어 터미널과 더 유사하게 느껴지거나, 더 자연스럽게 느껴지거나, 디스플레이 속도보다 더 중요하다고 간주되는 다른 문제를 해결하도록 합니까?
최근에는 더 빠르게 렌더링하는 새로운 터미널 에뮬레이터를 만들기 위한 노력이 있었습니다(예: 비디오 메모리의 OpenGL 텍스처로 글꼴을 사전 렌더링하는 방식). 그러나 이러한 노력은 그리드를 계산한 후 화면 비트맵에 문자 셀 그리드를 렌더링하는 속도를 높이는 것으로만 보입니다.
매우 빠른 컴퓨터에서도 이러한 것들이 근본적으로 느린 데에는 다른 이유가 있는 것 같습니다. 생각해 보십시오. 터미널 에뮬레이터가 화면 비트맵에 무엇이든 렌더링하기 전에 문자 셀 격자를 가져오기 위해 모든 ANSI 코드를 처리하는 경우 문자 격자 비트맵 렌더링 루틴이 얼마나 느린지는 중요하지 않습니다. 깜박임이 없어야 합니다. 적어도 우리가 많이 볼 수 있는 하드웨어 터미널의 커서 움직임에 분명히 해당하는 깜박임은 아닙니다. 터미널 에뮬레이터가 화면에 특정 문자 셀 그리드를 그리는 데 1초가 걸리더라도 깜박임이 아닌 1초의 비활성 시간만 발생합니다.
비슷한 문제는 Unix clear
와 reset
명령이 수행하는 작업에 비해 매우 느리다는 것입니다(GUI 사용자의 관점에서 볼 때 비트맵을 다시 그리는 것보다 더 복잡한 작업은 수행하지 않습니다). 어쩌면 관련된 이유 때문일 수도 있습니다.
답변1
시스템을 사용할 때는 이러한 깜박임을 눈치채지 못했기 때문에 어떻게 그렇게 눈에 띄는 깜박임이 발생하는지 자세히 알고 싶습니다.
내 시스템에서 VTE(GNOME 터미널 뒤의 엔진)는 약 10MB/s의 수신 데이터를 처리할 수 있습니다. 다른 시뮬레이터의 성능은 크게 다르지 않으며 양방향으로 3~5배 정도 될 수 있습니다. 깜박임 없는 업데이트를 위해서는 이 정도면 충분합니다.
전체 화면 터미널에는 수만 개의 문자 셀이 포함될 수 있다는 점을 명심하십시오. UTF-8 문자는 여러 바이트로 구성됩니다. 다른 속성(색상, 굵게 등)으로 전환하려면 이스케이프 시퀀스가 필요합니다. 이 시퀀스는 3~4바이트에서 10~20바이트(특히 256색 및 트루컬러 확장)로 쉽게 확장될 수 있습니다. 따라서 정말 복잡한 레이아웃에는 100kB 이상이 필요할 수 있습니다. 이것은 확실히 한 단계에서 tty 라인을 전달할 수 없습니다. 일부 응용 프로그램(또는 화면 그리기 라이브러리)이 한 단계로 전체 출력을 버퍼링할 의향이 있는지조차 확신할 수 없습니다. 아마도 그들은 printf()를 사용하고 stdio가 8kB 정도마다 플러시하도록 할 것입니다. 이것이 느린 또 다른 이유일 수 있습니다.
나는 두 프로세스와 사용자/커널 모드 사이를 앞뒤로 전환해야 하는지 또는 멀티스레드 CPU에서 동시에 실행할 수 있는지와 같은 커널의 스케줄링 동작에 대해 잘 알지 못합니다. 요즘 대부분의 CPU처럼 멀티 코어 CPU에서 동시에 실행될 수 있었으면 좋겠습니다.
스토리에는 의도적인 컷이 없습니다. 그러나 에뮬레이터가 데이터 읽기를 계속할지 화면을 업데이트할지 결정할 때 추측이 발생할 수 있습니다. 예를 들어, 터미널 에뮬레이터가 애플리케이션이 내보낼 수 있는 것보다 더 빠르게 입력을 처리하는 경우 첫 번째 블록을 처리한 후 입력이 중단되는 것을 확인하고 UI를 업데이트하기로 합리적으로 결정할 수 있습니다.
커서는 콘텐츠가 업데이트될 때 화면을 따라 움직이기 때문에 깜박이기 가장 쉬운 것 같습니다. 같은 곳에 머물 수는 없습니다. 에뮬레이터가 입력 데이터를 수신할 때 화면을 한 번만 업데이트하고 커서가 동일한 위치에 머무르는 경우 이러한 깜박임이 표시될 수 있습니다.
당신은 이것에 관심이 있을 수 있습니다원자적 업데이트 제안(여기서 토론하세요), 이는 터미널 에뮬레이터와 내부에서 실행되는 애플리케이션이 모두 지원하는 경우 대부분 문제를 해결합니다.
키보드 스크롤 경험이 왜 그렇게 좋은지에 관심이 있을 수도 있습니다.퍽퍽한거겠지키보드 반복 속도와 모니터 새로 고침 빈도 간의 간섭으로 인해 본질적으로 깜박이지 않는 것이 불쾌한 경험을 초래할 수 있습니다.