WriteCharsLegacy performance issues caused by NotifyConsoleUpdateSimpleEvent #14356

Open
opened 2026-01-31 04:08:06 +00:00 by claunia · 19 comments
Owner

Originally created by @skyline75489 on GitHub (Jun 29, 2021).

Description of the new feature/enhancement

I know this is a issue a long time ago, but haven't got the chance to talk about it.

This is typical WPR trace of OpenConsole with output-heavy programs.

image

Proposed technical implementation details (optional)

Perhaps throttling the event?

Originally created by @skyline75489 on GitHub (Jun 29, 2021). # Description of the new feature/enhancement I know this is a issue a long time ago, but haven't got the chance to talk about it. This is typical WPR trace of `OpenConsole` with output-heavy programs. ![image](https://user-images.githubusercontent.com/4710575/123777797-21323580-d903-11eb-93d3-3b46acc43db4.png) <!-- A clear and concise description of what the problem is that the new feature would solve. Describe why and how a user would use this new functionality (if applicable). --> # Proposed technical implementation details (optional) <!-- A clear and concise description of what you want to happen. --> Perhaps throttling the event?
claunia added the Help WantedProduct-ConhostIssue-TaskArea-Performance labels 2026-01-31 04:08:06 +00:00
Author
Owner

@skyline75489 commented on GitHub (Jun 29, 2021):

Just by commenting out the NotifyConsoleUpdateSimpleEvent, you'll get actual 3x performance boost running termbench in OpenConsole (80kcg -> 260kcg).

@skyline75489 commented on GitHub (Jun 29, 2021): Just by commenting out the `NotifyConsoleUpdateSimpleEvent`, you'll get actual 3x performance boost running termbench in `OpenConsole` (80kcg -> 260kcg).
Author
Owner

@lhecker commented on GitHub (Jun 29, 2021):

Returning early from SCREEN_INFORMATION::NotifyAccessibilityEventing improves my performance only by ~10%.
image

I highly suspect that both you and @DHowett got WT's a11y features enabled, despite not wanting nor needing it. The question is, which tool could cause WT to believe that a11y is wanted in the first place? Any idea @carlos-zamora?

@lhecker commented on GitHub (Jun 29, 2021): Returning early from `SCREEN_INFORMATION::NotifyAccessibilityEventing` improves my performance only by ~10%. ![image](https://user-images.githubusercontent.com/2256941/123815179-8d5a6c80-d8f6-11eb-9137-bf5d93a958b3.png) I highly suspect that both you and @DHowett got WT's a11y features enabled, despite not wanting nor needing it. The question is, which tool could cause WT to believe that a11y is wanted in the first place? Any idea @carlos-zamora?
Author
Owner

@lhecker commented on GitHub (Jun 29, 2021):

Hmm, running accevent.exe (and thus enabling UIA) doesn't change the performance for me much either... So why does @skyline75489's trace show such a high CPU time in NotifyConsoleUpdateSimpleEvent?

@lhecker commented on GitHub (Jun 29, 2021): Hmm, running `accevent.exe` (and thus enabling UIA) doesn't change the performance for me much either... So why does @skyline75489's trace show such a high CPU time in `NotifyConsoleUpdateSimpleEvent`?
Author
Owner

@DHowett commented on GitHub (Jun 29, 2021):

This reminds me a bit of https://github.com/microsoft/terminal/issues/410#issuecomment-485012574, but it's a simple event and not a sizing event... hm.

@DHowett commented on GitHub (Jun 29, 2021): This reminds me a bit of https://github.com/microsoft/terminal/issues/410#issuecomment-485012574, but it's a simple event and not a sizing event... hm.
Author
Owner

@DHowett commented on GitHub (Jun 29, 2021):

To be fair, however: enabling any event causes us to send all events, due to the architecture of the legacy accessibility eventing system.

@DHowett commented on GitHub (Jun 29, 2021): To be fair, however: enabling _any_ event causes us to send _all_ events, due to the architecture of the legacy accessibility eventing system.
Author
Owner

@DHowett commented on GitHub (Jun 29, 2021):

Interesting. We do not disable accessibility notification in ConPTY. Are we wasting cycles doing this when we're sitting behind Terminal (or Code, or something else) too?

@DHowett commented on GitHub (Jun 29, 2021): Interesting. We do not disable accessibility notification in ConPTY. Are we wasting cycles doing this when we're sitting behind Terminal (or Code, or something else) too?
Author
Owner

@lhecker commented on GitHub (Jun 29, 2021):

@DHowett I was already wondering why we're posting MSAA events, when WT already has it's own UIA integration.
So basically, if I understand you correctly, we can disable MSAA entirely for ConPTY and in our OpenConsole build (which unlike conhost is only used by WT), right?

@lhecker commented on GitHub (Jun 29, 2021): @DHowett I was already wondering why we're posting MSAA events, when WT already has it's own UIA integration. So basically, if I understand you correctly, we can disable MSAA entirely for ConPTY and in our OpenConsole build (which unlike conhost is only used by WT), right?
Author
Owner

@DHowett commented on GitHub (Jun 29, 2021):

I'd rather disable it specifically when we're hosting a PTY -- we don't want to be sending those events when we're doing ConPTY using the Windows inbox infrastructure either :)

@DHowett commented on GitHub (Jun 29, 2021): I'd rather disable it specifically when we're hosting a PTY -- we don't want to be sending those events when we're doing ConPTY using the Windows inbox infrastructure either :)
Author
Owner

@DHowett commented on GitHub (Jun 29, 2021):

Chester may also just be testing openconsole directly. It's a good testbed for the raw performance of one round of VT parsing with no VT string formatting.

@DHowett commented on GitHub (Jun 29, 2021): Chester may also just be testing openconsole directly. It's a good testbed for the raw performance of one round of VT parsing with no VT string formatting.
Author
Owner

@skyline75489 commented on GitHub (Jun 29, 2021):

@DHowett is right. I was testing only OpenConsole. The screenshot shot and the 3x boost come from running OpenConsole directly.

@skyline75489 commented on GitHub (Jun 29, 2021): @DHowett is right. I was testing only OpenConsole. The screenshot shot and the 3x boost come from running OpenConsole directly.
Author
Owner

@skyline75489 commented on GitHub (Jun 30, 2021):

This is how it looks like with WT:

image

Basically the same thing as @lhecker posted.

@skyline75489 commented on GitHub (Jun 30, 2021): This is how it looks like with WT: ![image](https://user-images.githubusercontent.com/4710575/123886428-0226b880-d982-11eb-846e-89a560755b4a.png) Basically the same thing as @lhecker posted.
Author
Owner

@skyline75489 commented on GitHub (Jul 2, 2021):

So the ConPTY part is obviously fixable and profitable as shown in #10537. Are we do something about the OpenConsole part of this issue? That's a painfully obvious performance bottleneck that I think I first noticed in the year of 2020.

@skyline75489 commented on GitHub (Jul 2, 2021): So the ConPTY part is obviously fixable and profitable as shown in #10537. Are we do something about the OpenConsole part of this issue? That's a painfully obvious performance bottleneck that I think I first noticed in the year of 2020.
Author
Owner

@DHowett commented on GitHub (Jul 2, 2021):

We can only make it faster; we cannot remove it, as there are applications with a dependency on our legacy accessibility events.

@DHowett commented on GitHub (Jul 2, 2021): We can only make it faster; we cannot remove it, as there are applications with a dependency on our legacy accessibility events.
Author
Owner

@skyline75489 commented on GitHub (Jul 2, 2021):

We can only make it faster; we cannot remove it, as there are applications with a dependency on our legacy accessibility events.

😢

I don't have enough knowledge to make it faster without breaking other applications. Maybe someone can shine some light on this particular subject, when they have the time.

@skyline75489 commented on GitHub (Jul 2, 2021): > We can only make it faster; we cannot remove it, as there are applications with a dependency on our legacy accessibility events. 😢 I don't have enough knowledge to make it faster without breaking other applications. Maybe someone can shine some light on this particular subject, when they have the time.
Author
Owner

@miniksa commented on GitHub (Jul 6, 2021):

If we think of accessibility like a renderer to a screen reader... then it may be acceptable to coalesce the events coming out of it and skip frames or only report some of the information over the MSAA channel since no one could reasonably be expected to "read" all of that information anyway.

However, node.js and presumably other things globally hook MSAA events in some versions as a way of getting notifications that the buffer data has changed and scraping all of its context out of it... because it took us a really long time to provide something like ConPTY and that was their only option. They DO want to "read" ALL of the information, so skipping frames doesn't work for them.

I think the only way out of this box is through ConPTY and you're not going to fix it for conhost. You could choose to fix it for your own personal OpenConsole where you don't need the MSAA events... or we could add some sort of MSAA-opt-out flag on startup of conhost that turns them off if you know you don't need them... but not by default in the OS. The strategy there is to just migrate away from conhost as the headed environment.

@miniksa commented on GitHub (Jul 6, 2021): If we think of accessibility like a renderer to a screen reader... then it may be acceptable to coalesce the events coming out of it and skip frames or only report some of the information over the MSAA channel since no one could reasonably be expected to "read" all of that information anyway. However, node.js and presumably other things globally hook MSAA events in some versions as a way of getting notifications that the buffer data has changed and scraping all of its context out of it... because it took us a really long time to provide something like ConPTY and that was their only option. They DO want to "read" ALL of the information, so skipping frames doesn't work for them. I think the only way out of this box is through ConPTY and you're not going to fix it for conhost. You could choose to fix it for your own personal OpenConsole where you don't need the MSAA events... or we could add some sort of MSAA-opt-out flag on startup of conhost that turns them off if you know you don't need them... but not by default in the OS. The strategy there is to just migrate away from conhost as the headed environment.
Author
Owner

@DHowett commented on GitHub (Jul 6, 2021):

Node we know about -- it uses it solely for resize, which we really should address by having a better resize channel.

It's the nebulous "other things" that we can't know. :)

@DHowett commented on GitHub (Jul 6, 2021): Node we know about -- it uses it solely for resize, which we really should address by having a better resize channel. It's the nebulous "other things" that we can't know. :)
Author
Owner

@miniksa commented on GitHub (Jul 6, 2021):

Node we know about -- it uses it solely for resize, which we really should address by having a better resize channel.

Ah yes. Thank you for reminding me. Unfortunately it has to subscribe to all of them, I believe? Or by subscribing to the one event, it does it for all processes and that's slow? Something something global table in user32k.

It's the nebulous "other things" that we can't know. :)

Yes. I'm thinking that the class of alternative Windows terminal environments pre-ConPTY might be using some or all of this mechanism for eventing.

Further, though. I think it MIGHT be okay to batch up NotifyConsoleUpdateSimpleEvents into a big NotifyConsoleUpdateRegionEvent for massive/bulk text output. But someone would have to go find tools that use it and prove my theory.

@miniksa commented on GitHub (Jul 6, 2021): > Node we know about -- it uses it solely for resize, which we really should address by having a better resize channel. Ah yes. Thank you for reminding me. Unfortunately it has to subscribe to all of them, I believe? Or by subscribing to the one event, it does it for all processes and that's slow? Something something global table in user32k. > It's the nebulous "other things" that we can't know. :) Yes. I'm thinking that the class of alternative Windows terminal environments pre-ConPTY might be using some or all of this mechanism for eventing. Further, though. I think it **MIGHT** be okay to batch up `NotifyConsoleUpdateSimpleEvent`s into a big `NotifyConsoleUpdateRegionEvent` for massive/bulk text output. But someone would have to go find tools that use it and prove my theory.
Author
Owner

@j4james commented on GitHub (Jul 6, 2021):

Is there not perhaps some way we can determine whether any applications have registered for accessibility events, and thus skip sending them if we know that nobody is listening? For example, the docs for NotifyWinEvent say that "Servers may receive a WM_GETOBJECT message immediately after calling this function". So if there was an event we could generate at startup which was guaranteed to receive a WM_GETOBJECT callback, could we then be certain that nobody was listening if we didn't receive one?

@j4james commented on GitHub (Jul 6, 2021): Is there not perhaps some way we can determine whether any applications have registered for accessibility events, and thus skip sending them if we know that nobody is listening? For example, the docs for `NotifyWinEvent` say that "Servers may receive a `WM_GETOBJECT` message immediately after calling this function". So if there was an event we could generate at startup which was guaranteed to receive a `WM_GETOBJECT` callback, could we then be certain that nobody was listening if we *didn't* receive one?
Author
Owner

@miniksa commented on GitHub (Jul 9, 2021):

Looking behind NotifyWinEvent's code... it checks for an installed event hook locally in the user side within a structure quickly before making the kernel transition. So it should only be a tiny overhead (ETW-like) as long as no one is listening.

My interpretation of that particular line though, James, is that you only get WM_GETOBJECT callbacks for MSAA if the other side is specifically requesting information about a certain UI object positioning. But we don't have distinct UI objects... really. The console events just sort of declare things that listeners generally turn into Console API calls to get more information instead of querying them through the MSAA object framework.

I think it would just take someone playing around with all of these things to figure it out. Find a screen reader that uses our MSAA events... mess around with some changes... etc.

@miniksa commented on GitHub (Jul 9, 2021): Looking behind `NotifyWinEvent`'s code... it checks for an installed event hook locally in the user side within a structure quickly before making the kernel transition. So it should only be a tiny overhead (ETW-like) as long as no one is listening. My interpretation of that particular line though, James, is that you only get `WM_GETOBJECT` callbacks for MSAA if the other side is specifically requesting information about a certain UI object positioning. But we don't have distinct UI objects... really. The console events just sort of declare things that listeners generally turn into Console API calls to get more information instead of querying them through the MSAA object framework. I think it would just take someone playing around with all of these things to figure it out. Find a screen reader that uses our MSAA events... mess around with some changes... etc.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#14356