-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions #8621
Conversation
…so it's not assembled every time the renderer asks.
…es and returned as iterable spans to avoid more allocations, especially for renderers with complex dirty areas that are already storing the rectangles internally.
This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 7 days. It will be closed if no further activity occurs within 7 days of this comment. |
…f thousands of transient allocations as we convert things to emit them as a UTF-8 string.
…over and over when we know we're about to just rebuild a vector of more runs. optional will destroy the internal vector.
@miniksa You are such a wizard on performance! I'm seeing great result comparing this branch with 1.5 Preview. With setting UI and all, 1.6 is going to be awesome 🎉 |
I owe a lot of credit to @Austin-Lamb this time for setting me down the allocations path. Without that insight, we wouldn't be seeing these PRs! |
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.
cool
… in the end going for til instead.
src/inc/til/bitmap.h
Outdated
// or continue to use the optional with a PMR vector inside. | ||
// It's static because we only need one pool to manage memory | ||
// for all vectors of rectangles no matter which bitmap instance is making them. | ||
static std::pmr::unsynchronized_pool_resource& _getPool() noexcept |
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.
this will conflict with #8787; should we converge earlier rather than later?
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.
We decided over Teams to converge in this PR, because there's a conflict here anyway.
…arameter constructor in VT because the compiler matches the &_pool on the two-part one to a boolean!
@@ -32,7 +32,7 @@ VtEngine::VtEngine(_In_ wil::unique_hfile pipe, | |||
_lastTextAttributes(INVALID_COLOR, INVALID_COLOR), | |||
_lastViewport(initialViewport), | |||
_pool(til::pmr::get_default_resource()), | |||
_invalidMap(initialViewport.Dimensions(), &_pool), | |||
_invalidMap(initialViewport.Dimensions(), false, &_pool), |
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.
@DHowett, if I don't call it with three parameters, it is turning the &_pool
into bool true
. What.
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.
Ahh, automatic coercion of pointer types to booleans (for nullness checks). Ew.
@miniksa |
Yeah yeah yeah yeah. |
Hello @miniksa! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
🎉 Handy links: |
Dustin L. Howett (3) * Fix the Host Proxy DLL reference in ServerLib (GH-9129) * ci: fix spelling * Format the incoming inbox code Michael Niksa (1) * Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions (GH-8621) Related work items: MSFT-31755835
We have been seeing some crashes (#9410) originating from a use-after-free or a double-free in the renderer. The renderer is iterating over the dirty rects from the render engine¹ and the rect list is being freed out from under it. Things like this are usually the result of somebody manipulating the renderer's state outside of lock. Therefore, this pull request introduces some targeted locking fixes around manipulation of the pattern buffer (which, in turn, changes the renderer state.) ¹ This was not a problem until #8621, which made the renderer return a span instead of a copy for the list of dirty rects. ## Validation I ran Terminal under App Verifier, and introduced a manul delay (under lock) in the renderer such that the invalid map would definitely have been invalidated between the renderer taking the lock and the renderer handling the frame. AppVerif failed us without these locking changes, and did not do so once they were introduced. Closes #9410.
We have been seeing some crashes (#9410) originating from a use-after-free or a double-free in the renderer. The renderer is iterating over the dirty rects from the render engine¹ and the rect list is being freed out from under it. Things like this are usually the result of somebody manipulating the renderer's state outside of lock. Therefore, this pull request introduces some targeted locking fixes around manipulation of the pattern buffer (which, in turn, changes the renderer state.) ¹ This was not a problem until #8621, which made the renderer return a span instead of a copy for the list of dirty rects. ## Validation I ran Terminal under App Verifier, and introduced a manul delay (under lock) in the renderer such that the invalid map would definitely have been invalidated between the renderer taking the lock and the renderer handling the frame. AppVerif failed us without these locking changes, and did not do so once they were introduced. Closes #9410. (cherry picked from commit ea3e56d)
References
PR Checklist
Detailed Description of the Pull Request / Additional comments
Window Title Generation
Every time the renderer checks the title, it's doing two bad things that
I've fixed:
No one ever gets just the prefix ever after it is set besides the
concat. So instead of storing prefix and the title, I store the
assembled prefix + title and the bare title.
std::wstring
insteadof
std::wstring&
. Now it returns the ref.Dirty Area Return
Every time the renderer checks the dirty area, which is sometimes
multiple times per pass (regular text printing, again for selection,
etc.), a vector is created off the heap to return the rectangles. The
consumers only ever iterate this data. Now we return a span over a
rectangle or rectangles that the engine must store itself.
that 1 element when dirty is queried and return it in the span with a
span size of 1.
holding a cached vector of rectangles. Now it's effectively giving
out the ref to those in the span for iteration.
Bitmap Runs
The
til::bitmap
used astd::optional<std::vector<til::rectangle>>
inside itself to cache its runs and would clear the optional when the
runs became invalidated. Unfortunately doing
.reset()
to clear theoptional will destroy the underlying vector and have it release its
memory. We know it's about to get reallocated again, so we're just going
to make it a
std::pmr::vector
and give it a memory pool.The alternative solution here was to use a
bool
andstd::vector<til::rectangle>
and just flag when the vector was invalid,but that was honestly more code changes and I love excuses to try out
PMR now.
Also, instead of returning the ref to the vector... I'm just returning a
span now. Everyone just iterates it anyway, may as well not share the
implementation detail.
UTF-8 conversions
When testing with Terminal and looking at the
conhost.exe
's PTYrenderer, it spends a TON of allocation time on converting all the
UTF-16 stuff inside to UTF-8 before it sends it out the PTY. This was
because
ConvertToA
was allocating a string inside itself and returningit just to have it freed after printing and looping back around again...
as a PTY does.
The change here is to use
til::u16u8
that accepts a buffer outparameter so the caller can just hold onto it.
Validation Steps Performed
big.txt
in conhost.exe (GDI renderer)big.txt
in Terminal (DX, PTY renderer)