microsoft / terminal

The new Windows Terminal and the original Windows console host, all in the same place!
MIT License
95.63k stars 8.32k forks source link

Large drop in performance when using font features #17927

Open ChrHorn opened 1 month ago

ChrHorn commented 1 month ago

Windows Terminal version

1.22.2362.0

Windows build number

10.0.19045.4894

Other Software

Iosevka Term 31.6.1

Steps to reproduce

  1. Download and install Iosevka Term 31.6.1.
  2. Set font face to Iosevka Term
  3. Set any of the available font features to an arbitrary value.

Expected Behavior

Smooth scrolling/selection.

Actual Behavior

Selection via mouse and scrolling becomes very sluggish. It is less noticeable on a blank cmd, but it gets worse and worse with more colors, characters and a bigger window. Especially noticeable when using a command line editor like Vim/Helix via WSL.

Removing the font features immediately makes everything smooth again. I can't reproduce this behavior with Cascadia Code, only noticed it with Iosevka Term so far.

lhecker commented 1 month ago

Can you provide more detailed reproduction steps? Basically, what exact steps can I follow to make it as sluggish and slow as possible? I can make it run at roughly 30 FPS if I follow your steps, which is really bad, but it'd be nice if there was something to make it even worse, so I can fix the issue more easily.

Generally speaking, this is because Iosevka has a lot of "complex" glyphs. This causes IDWriteTextAnalyzer1::GetTextComplexity to return FALSE all the time. This forces us to do expensive glyph shaping with IDWriteTextAnalyzer::GetGlyphs. The problem with that is that DirectWrite is the only font stack we can use, and its implementation is just not all that great from a performance perspective. While GetTextComplexity is rather slow, the alternative GetGlyphs is multiple magnitudes worse. While the rest of our text renderer runs at >4000 FPS on average desktop hardware, it drops down to <10FPS when you have a screen full of Hebrew text for instance while we spend 99% of the CPU time in DirectWrite.

I'll check if there's anything I can do about that.

ChrHorn commented 1 month ago

Can you provide more detailed reproduction steps? Basically, what exact steps can I follow to make it as sluggish and slow as possible? I can make it run at roughly 30 FPS if I follow your steps, which is really bad, but it'd be nice if there was something to make it even worse, so I can fix the issue more easily.

I'm currently using an aging Skylake laptop, that's probably why the issue is more noticeable on my end. To reproduce my worst-case:

  1. Install Helix (winget install helix.helix, or use WSL)
  2. Enable any Iosevka font feature
  3. Maximize the terminal window
  4. Open a file with source code (e.g. clone Helix repo, hx helix/helix-view/src/editor.rs)
  5. Hold down left mouse button and select text while moving the mouse up and down

Short demonstration how it looks on my end:

https://github.com/user-attachments/assets/a77ed039-a205-4e89-a859-8a69f592496d

Without font features everything is smooth.

When using WeZterm I didn't notice any difference with font features enabled (although WezTerm seems to be less smooth on average compared to Windows Terminal). Thankfully it's very easy to create customized Iosevka fonts that have features already baked in.

Irfan29580 commented 1 month ago

Can you provide more detailed reproduction steps? Basically, what exact steps can I follow to make it as sluggish and slow as possible? I can make it run at roughly 30 FPS if I follow your steps, which is really bad, but it'd be nice if there was something to make it even worse, so I can fix the issue more easily.

Generally speaking, this is because Iosevka has a lot of "complex" glyphs. This causes IDWriteTextAnalyzer1::GetTextComplexity to return FALSE all the time. This forces us to do expensive glyph shaping with IDWriteTextAnalyzer::GetGlyphs. The problem with that is that DirectWrite is the only font stack we can use, and its implementation is just not all that great from a performance perspective. While GetTextComplexity is rather slow, the alternative GetGlyphs is multiple magnitudes worse. While the rest of our text renderer runs at >4000 FPS on average desktop hardware, it drops down to <10FPS when you have a screen full of Hebrew text for instance while we spend 99% of the CPU time in DirectWrite.

I'll check if there's anything I can do about that.