Windows 终端延迟 (2024)
Terminal Latency on Windows (2024)

原始链接: https://chadaustin.me/2024/02/windows-terminal-latency/

## Windows Terminal 对决:延迟与性能评测 Windows Terminal 的一次更新(v1.19)将其延迟减半,使其更接近 MinTTY 等竞争对手。这促使人们重新评估 Windows 终端,回顾了自 2009 年 MinTTY 被认为是最佳终端以来一直探讨的话题。 测试重点关注关键特性——24 位色、字体支持、输入延迟、吞吐量和标签页支持,涵盖 conhost.exe(传统控制台)、MinTTY、Alacritty、WezTerm 和 Windows Terminal。结果显示,**conhost.exe 一致地提供最低的延迟**,紧随其后的是 MinTTY。**MinTTY 在吞吐量方面表现出色**,在处理大文件输出时显著优于其他终端。 然而,**WezTerm 显示出异常高的 CPU 使用率**,可能表明存在错误。空闲 CPU 消耗也是一个问题,大多数终端(conhost.exe 除外)即使在不活动时也会使用大量资源。令人惊讶的是,Windows Terminal 比传统控制台使用了更多的 RAM 和 CPU。 最终,**MinTTY 仍然是一个强有力的竞争者**,在性能、功能和更好的默认调色板之间取得了平衡。虽然 Windows Terminal 已经有所改进,但延迟仍然是需要优化的关键领域。作者计划继续调查 MinTTY 的空闲 CPU 使用情况,并认为所有测试的终端都有改进的空间。

最近 Hacker News 的讨论围绕一篇分析 Windows 终端延迟的博文展开。一个关键更新指出,Windows Terminal 1.22 显著提高了吞吐量——在某些情况下快高达 16 倍,这得益于一个特定的拉取请求。 对话延伸到人们在 Windows 上使用终端的原因,挑战了它“只是一个游戏操作系统”的观点。用户强调了 Windows Terminal 与 WSL 结合用于开发的优势,特别是考虑到 Windows 机器的性价比。另一些人则简单地为使用 Windows 的各种目的辩护。 进一步的讨论涉及期望的功能,例如原生串口 (DB9/RS232) 通信支持和 GPU 渲染管道问题(特别是 WezTerm 中的 NVIDIA 和 DXGI)。一个长期存在的困扰——点击窗口时输出暂停的问题也被提出,但用户指出它由“QuickEdit 模式”控制,可以禁用。
相关文章

原文

UPDATE 2024-04-15: Windows Terminal 1.19 contains a fix that reduces latency by half! It’s now competitive with WSLtty on my machine. Details in the GitHub Issue.

In 2009, I wrote about why MinTTY is the best terminal on Windows. Even today, that post is one of my most popular.

MinTTY in 2009
MinTTY in 2009

Since then, the terminal situation on Windows has improved:

  • Cygwin defaults to MinTTY; you no longer need to manually install it.
  • Windows added PTY support, obviating the need for offscreen console window hacks that add latency.
  • Windows added basically full support for ANSI terminal sequences in both the legacy conhost.exe consoles and its new Windows Terminal.
  • We now have a variety of terminals to choose from, even on Windows: Cmder, ConEmu, Alacritty, WezTerm, xterm.js (component of Visual Studio Code)

The beginning of a year is a great time to look at your tools and improve your environment.

I’d already enabled 24-bit color in all of my environments and streamlined my tmux config. It’s about time that I take a look at the newer terminals.

Roughly in order, I care about:

  • Minimum feature set: 24-bit color, reasonable default fonts with emoji support, italics are nice.
  • Input latency.
  • Throughput at line rate, for example, when I cat a large file.
  • Support for multiple tabs in one window would be nice, but tmux suffices for me.

Which terminals should I test?

I considered the following.

  • Legacy conhost.exe (also known as Windows Console), Windows 10 19045
  • MinTTY (3.7.0)
  • Alacritty (0.13.1)
  • WezTerm (20240203-110809-5046fc22)
  • Windows Terminal (1.18.10301.0)

Testing Features

Testing color and italics support is easy with my colortest.rs script. To test basic emoji, you can cat the Unicode emoji 1.0 emoji-data.txt. To test more advanced support, try the zero-width joiner list in the latest/ directory.

Terminal Emoji Font Attributes
conhost.exe No No italics
MinTTY Black and white All major attributes
Alacritty Black and white Everything but double underline
WezTerm Color All major attributes
Windows Terminal Color All major attributes

Everything but conhost.exe meets my bar.

It’s also worth noting that conhost.exe has a terrible default palette. The default yellow is a pukey green and dark blue is barely visible. You can change palettes, but defaults matter.

Conhost.exe Default Palette
Conhost.exe Default Palette
MinTTY Default Palette
MinTTY Default Palette

Latency

I set up two latency tests. One with an 80x50 blank window in the upper left corner of the screen. The other fullscreen, editing an Emacs command at the bottom of the screen.

Since latencies are additive, system configuration doesn’t matter as much as the absolute milliseconds of latency each terminal adds, but I’ll describe my entire setup and include total keypress-to-pixels latency.

Measurement Methodology

With Is It Snappy?, I measured the number of frames between pressing a key and pixels changing on the screen.

To minimize ambiguity about when the key was pressed, I slammed a pencil’s eraser into the key, and always measured the key press as the second frame after contact. (The first frame was usually when the eraser barely touched the key. It would usually clear the activation depth by the second frame.)

I considered the latency to end when pixels just started to change on the screen. In practice, pixels take several 240 Hz frames to transition from black to white, but I consistently marked the beginning of that transition.

I took five measurements for each configuration and picked the median. Each measurement was relatively consistent, so average would have been a fine metric too. It doesn’t change the results below.

80x50

80x50 window, upper left of screen, cleared terminal, single keypress.

Confirmed window size with:

$ echo $(tput cols)x$(tput lines)
80x50
Terminal Median Latency (ms) 240 Hz Camera Frames
conhost.exe WSL1 33.3 8
MinTTY WSL1 33.3 8
conhost.exe Cygwin 41.3 10
MinTTY Cygwin 57.9 14
WezTerm cmd.exe 62.5 15
Alacritty WSL1 62.5 15
WezTerm WSL1 66.7 16
Windows Terminal WSL1 66.7 16

Fullscreen

Maximized emacs, editing a command in the bottom row of the terminal. I only tested WSL1 this time.

Terminal Median Latency (ms) 240 Hz Camera Frames
conhost.exe 45.8 11
MinTTY 52.42 12
WezTerm 75 18
Windows Terminal 75 18
Alacritty 87.5 21

Throughput

I generated a 100,000-line file with:

$ yes "This sentence has forty-five (45) characters." | head -n 100000 > /tmp/lines.txt

Then I measured the wall-clock duration of:

$ time cat /tmp/lines.txt

This benchmark captures the case that I accidentally dump a ton of output and I’m sitting there just waiting for the terminal to become responsive again. I have a gigabit internet connection, and it’s embarrassing to be CPU-bound instead of IO-bound.

I did include Cygwin in this test, just to have two different MinTTY datapoints.

Terminal Elapsed Time (s)
MinTTY WSL1 0.57
MinTTY Cygwin 2.2
Windows Terminal 5.25
Alacritty 5.75
WezTerm 6.2
conhost.exe 21.8

I assume this means MinTTY throttles display updates in some way. Of course this is totally fine, because you couldn’t read the output either way.

To test the hypothesis that MinTTY was caching cell rendering by their contents, I also tried generating a file that rotated through different lines, with no effect.

with open("/tmp/lines2.txt", "w") as f:
  for i in range(100000):
    sentence="This sentence has forty-five (45) characters."
    print(sentence[i%len(sentence):]+sentence[:i%len(sentence)], file=f)

CPU Usage During Repeated Keypresses

While making these measurements, I noticed some strange behaviors. My monitor runs at 120 Hz and animation and window dragging are generally smooth. But right after you start Alacritty, dragging the window animates at something like 30-60 frames per second. It’s noticeably chunkier. WezTerm does the same, but slightly worse. Maybe 20 frames per second.

I don’t know if I can blame the terminals themselves, because I sometimes experience this even with Notepad.exe too. But the choppiness stands out much more. Maybe something is CPU-bound in responding to window events?

This made me think of a new test: if I open a terminal and hold down the “a” button on autorepeat, how much CPU does the terminal consume?

To measure this, I set the terminal process’s affinity to my third physical core, and watched the CPU usage graph in Task Manager. Not a great methodology, but it gave a rough sense. Again, 80x50.

Terminal Percent of Core Private Bytes After Startup (KiB)
conhost 0% 6,500
Alacritty 5% 74,000
MinTTY WSL1 10% 10,200
MinTTY Cygwin 10% 10,500
Windows Terminal 20% 73,700
WezTerm 85% 134,000

The WezTerm CPU usage has to be a bug. I’ll report it.

CPU Usage (Idle)

I often have a pile of idle terminals sitting around. I don’t want them to chew battery life. So let’s take a look at CPU Cycles Delta (courtesy of Process Explorer) with a fresh, idle WSL session.

Terminal Idle Cycles/s (Focused) Idle Cycles/s (Background)
conhost ~900,000 0
Alacritty ~2,400,000 no difference
WezTerm ~2,600,000 ~1,600,000
Windows Terminal ~55,000,000 ~6,100,000
MinTTY WSL1 ~120,000,000 no difference
MinTTY Cygwin ~120,000,000 no difference

These numbers aren’t great at all! For perspective, I have a pile of Firefox tabs open, some of them actively running JavaScript, and they’re “only” using a few hundred million cycles per second.

Raymond Chen once wrote a blog post about the importance of properly idling in the Windows Terminal Server days. You might have a dozen users logged into a host, and if a program is actively polling, it’s eating performance that others could use.

Today, we often run on batteries, so idling correctly still matters, but it seems to be something of a lost art. The only terminal that idles completely is the old conhost.exe.

The other lesson we can draw is that Microsoft’s own replacement for conhost.exe, Windows Terminal, uses over 10x the RAM, 60x the CPU when focused, and infinitely more CPU when idle.

Conclusions

conhost.exe consistently has the best latency, with MinTTY not much behind. MinTTY handily dominates the throughput test, supports all major ANSI character attributes, and has a better default palette.

As in 2009, I’d say MinTTY is still pretty great. (I should try to track down that idle CPU consumption. It feels more like a bug than a requirement.)

If you want to use MinTTY as the default terminal for WSL, install WSLtty.

The others all have slightly worse latencies, but they’re in a similar class. I’m particularly sensitive to latency, so I’d had a suspicion even before measuring. Maybe it’s some consequence of being GPU-accelerated? Out of curiousity, I put Windows Terminal in software-rendered mode, and it shaved perhaps 4 ms off (median of 62.5 ms, 15 frames). Perhaps just measurement noise.

While I’m going to stick with MinTTY, one thing is clear: there is room to improve all of the above.

联系我们 contact @ memedata.com