-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize rendering runs of spaces when there is no visual change #4877
Conversation
I haven't had a chance to try your patch, but I suspect the reverse video attribute might cause problems with this optimisation. Consider the difference between this sequence...
and this...
In both case it's just a run of spaces with a foreground change, but the second sequence would actually require a cluster split wouldn't it? And if that is the case, I assume the |
YES, thank you. That's very helpful. |
It won't change the mergeability of this PR, but would you [request changes] because of that? |
So, an attribute knows whether it's been reversed. This is fine for reverse video, but not for global DECSCNM. I'd hate to round trip through the thing that knows the colors just to make this determination... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed, this needs to take into account the reverse video attribute, and potentially the DECSCNM
mode.
Regarding the Edit: If you want to go the latter route, it looks like it should be an easy change to add something like a Lines 1308 to 1313 in a13ccfd
|
cmatrix is somewhat of a pathological case for our infrastructure: it prints out a bunch of green and white characters and then updates them a million times a second. It also maintains a column of space between every green character. When it prints this column, it prints it in "default" or "white". This ends up making runs of text that look like this: (def: G=green B=bright white W=white *=matrix char =space) G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W G W As characters trickle in: G*W G*W G*W G*W G*W G*W G*W B*W G*W G*W G*W G*W G*W G*W G*W G W G*W G*W G*W B*W G*W G*W G*W G W G*W B*W G*W G W G*W G*W G*W G*W G*W G W G*W G W G*W B*W G*W G*W B*W G W G*W G W G*W G W B*W G*W G W G W G*W G W G*W G W G W B*W G W G W B*W G W G*W G W G W G W Every one of those color transitions causes us to break up the run of text and start rendering it again. This impacts GDI, Direct2D *and* ConPTY. The problem is, printing a space doesn't **use** the foreground color! This commit introduces an optimization. When we're about to break a text cluster becuase its attributes changed, we make sure that it's not just filled with spaces and differs only in the foreground parameter. This lets us optimize both the rendering _and_ the PTY output to look like this: G* * * * * * * B* G* * * * * * * G* * * B* * * * G* B* * * * * * G* * * B* * * B* * * B* * G * * B* G B* * Text will be printed at best line-by-line and at worst only when the visible properties of the screen actually change. This speeds up cmatrix remarkably.
d7b39c8
to
a857291
Compare
This works for both normal and invert video with both yes and no DECSCNM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're going to hate me, but I think there's another case you need to deal with. What happens when one of the underline attributes is set? For example:
printf "\e[4;31m \e[32m \e[m"
You've got a run of spaces with only the foreground changing, but that still requires two clusters to handle the change in underline color doesn't it?
I'm clearing my approval in response to @j4james's comment that happened while I was reviewing |
oh heck no 😄 i love it |
|
||
constexpr bool IsAnyGridLineEnabled() const noexcept | ||
{ | ||
return WI_IsAnyFlagSet(_wAttrLegacy, COMMON_LVB_GRID_HORIZONTAL | COMMON_LVB_GRID_LVERTICAL | COMMON_LVB_GRID_RVERTICAL | COMMON_LVB_UNDERSCORE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to future proof this by checking the ExtendedAttributes
too (CrossedOut, Underlined, etc)? It's a bit open ended, because there are all sorts of these attributes that we may want to implement one day, so I don't know. I just thought it worth mentioning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're not wrong, I just keep acting like i've never written code before. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this thread you guys
Okay, this is as comprehensive as I think I can make it -- i've renamed the function to compensate. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay.
My most recent test case:
I then toggled DECSCNM on and off with that in the buffer. |
I'm not sure how you could write a test for that, which is why I'm okay with this not being tested. We don't really have a |
@msftbot make sure @miniksa signs off on this |
Hello @zadjii-msft! Because you've given me some instructions on how to help merge this pull request, I'll be modifying my merge approach. Here's how I understand your requirements for merging this pull request:
If this doesn't seem right to you, you can tell me to cancel these instructions and use the auto-merge policy that has been configured for this repository. Try telling me "forget everything I just told you". |
Ugh, I explicitly code-formatted this. |
Oh, I see. Unformatted code merged into master. Ugh. |
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, good enough.
cmatrix is somewhat of a pathological case for our infrastructure: it
prints out a bunch of green and white characters and then updates them a
million times a second.
It also maintains a column of space between every green character. When
it prints this column, it prints it in "default" or "white". This ends
up making runs of text that look like this:
(def: G=green B=bright white W=white *=matrix char =space)
As characters trickle in:
Every one of those color transitions causes us to break up the run of
text and start rendering it again. This impacts GDI, Direct2D and
ConPTY. In the example above, there are 120 runs.
The problem is, printing a space doesn't use the foreground color!
This commit introduces an optimization. When we're about to break a text
cluster because its attributes changed, we make sure that it's not just
filled with spaces and doesn't differ in any visually-meaningful way
(like underline or strikethrough, considering global invert state).
This lets us optimize both the rendering and the PTY output to look
like this:
Text will be printed at best line-by-line and at worst only when the
visible properties of the screen actually change. In the example
above, there are only 21 runs.
This speeds up cmatrix remarkably.
PR Checklist