From 9e44df0c9f201d5c3bb0df62f1519931f43a4fe0 Mon Sep 17 00:00:00 2001 From: Michael Niksa Date: Thu, 9 Jul 2020 04:18:25 -0700 Subject: [PATCH] Cache the size viewport structure inside TextBuffer (#6841) Looking up the size of the viewport from the underlying dimensions of the structures seemed like a good idea at the time (so it would only be in one place), but it turns out to be more of a perf cost than we expected. Not necessarily on any one hot path, but if we sort by functions in WPR, it was the top consumer on the Terminal side. This instead saves the size as a member of the `TextBuffer` and serves that out. It only changes when it is constructed or resized traditionally, so it's easy to update/keep track of. It impacted conhost/conpty to a lesser degree but was still noticeable. ## Validation Steps Performed - Run `time cat big.txt` under WPR. Checked before and after perf metrics. ## PR Checklist * [x] Closes perf itch * [x] I work here * [x] Manual test * [x] Documentation irrelevant. * [x] Schema irrelevant. * [x] Am core contributor. --- src/buffer/out/search.cpp | 4 ++-- src/buffer/out/search.h | 4 ++-- src/buffer/out/textBuffer.cpp | 20 ++++++++++++++++---- src/buffer/out/textBuffer.hpp | 6 ++++-- src/types/ScreenInfoUiaProviderBase.cpp | 2 +- src/types/ScreenInfoUiaProviderBase.h | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/buffer/out/search.cpp b/src/buffer/out/search.cpp index 5897bde1197..40a57c3cbc2 100644 --- a/src/buffer/out/search.cpp +++ b/src/buffer/out/search.cpp @@ -261,7 +261,7 @@ wchar_t Search::_ApplySensitivity(const wchar_t wch) const noexcept // - Helper to increment a coordinate in respect to the associated screen buffer // Arguments // - coord - Updated by function to increment one position (will wrap X and Y direction) -void Search::_IncrementCoord(COORD& coord) const +void Search::_IncrementCoord(COORD& coord) const noexcept { _uiaData.GetTextBuffer().GetSize().IncrementInBoundsCircular(coord); } @@ -270,7 +270,7 @@ void Search::_IncrementCoord(COORD& coord) const // - Helper to decrement a coordinate in respect to the associated screen buffer // Arguments // - coord - Updated by function to decrement one position (will wrap X and Y direction) -void Search::_DecrementCoord(COORD& coord) const +void Search::_DecrementCoord(COORD& coord) const noexcept { _uiaData.GetTextBuffer().GetSize().DecrementInBoundsCircular(coord); } diff --git a/src/buffer/out/search.h b/src/buffer/out/search.h index 3822e3ff45f..39efc139f40 100644 --- a/src/buffer/out/search.h +++ b/src/buffer/out/search.h @@ -63,8 +63,8 @@ class Search final bool _CompareChars(const std::wstring_view one, const std::wstring_view two) const noexcept; void _UpdateNextPosition(); - void _IncrementCoord(COORD& coord) const; - void _DecrementCoord(COORD& coord) const; + void _IncrementCoord(COORD& coord) const noexcept; + void _DecrementCoord(COORD& coord) const noexcept; static COORD s_GetInitialAnchor(Microsoft::Console::Types::IUiaData& uiaData, const Direction dir); diff --git a/src/buffer/out/textBuffer.cpp b/src/buffer/out/textBuffer.cpp index 1f645aa14ff..5462ffceea5 100644 --- a/src/buffer/out/textBuffer.cpp +++ b/src/buffer/out/textBuffer.cpp @@ -33,13 +33,16 @@ TextBuffer::TextBuffer(const COORD screenBufferSize, _cursor{ cursorSize, *this }, _storage{}, _unicodeStorage{}, - _renderTarget{ renderTarget } + _renderTarget{ renderTarget }, + _size{} { // initialize ROWs for (size_t i = 0; i < static_cast(screenBufferSize.Y); ++i) { _storage.emplace_back(static_cast(i), screenBufferSize.X, _currentAttributes, this); } + + _UpdateSize(); } // Routine Description: @@ -623,7 +626,7 @@ COORD TextBuffer::GetLastNonSpaceCharacter(std::optional(_storage.at(0).size()), gsl::narrow(_storage.size()) }); + _size = Viewport::FromDimensions({ 0, 0 }, { gsl::narrow(_storage.at(0).size()), gsl::narrow(_storage.size()) }); } void TextBuffer::_SetFirstRowIndex(const SHORT FirstRowIndex) noexcept @@ -845,6 +854,9 @@ void TextBuffer::Reset() // Also take advantage of the row ID refresh loop to resize the rows in the X dimension // and cleanup the UnicodeStorage characters that might fall outside the resized buffer. _RefreshRowIDs(newSize.X); + + // Update the cached size value + _UpdateSize(); } CATCH_RETURN(); diff --git a/src/buffer/out/textBuffer.hpp b/src/buffer/out/textBuffer.hpp index 4b409e7b95f..3f19e3a7592 100644 --- a/src/buffer/out/textBuffer.hpp +++ b/src/buffer/out/textBuffer.hpp @@ -110,7 +110,7 @@ class TextBuffer final const SHORT GetFirstRowIndex() const noexcept; - const Microsoft::Console::Types::Viewport GetSize() const; + const Microsoft::Console::Types::Viewport GetSize() const noexcept; void ScrollRows(const SHORT firstRow, const SHORT size, const SHORT delta); @@ -177,6 +177,8 @@ class TextBuffer final std::optional> positionInfo); private: + void _UpdateSize(); + Microsoft::Console::Types::Viewport _size; std::deque _storage; Cursor _cursor; @@ -193,7 +195,7 @@ class TextBuffer final void _SetFirstRowIndex(const SHORT FirstRowIndex) noexcept; - COORD _GetPreviousFromCursor() const; + COORD _GetPreviousFromCursor() const noexcept; void _SetWrapOnCurrentRow(); void _AdjustWrapOnCurrentRow(const bool fSet); diff --git a/src/types/ScreenInfoUiaProviderBase.cpp b/src/types/ScreenInfoUiaProviderBase.cpp index c5667b8e1af..d92bb4b458b 100644 --- a/src/types/ScreenInfoUiaProviderBase.cpp +++ b/src/types/ScreenInfoUiaProviderBase.cpp @@ -368,7 +368,7 @@ IFACEMETHODIMP ScreenInfoUiaProviderBase::get_SupportedTextSelection(_Out_ Suppo #pragma endregion -const COORD ScreenInfoUiaProviderBase::_getScreenBufferCoords() const +const COORD ScreenInfoUiaProviderBase::_getScreenBufferCoords() const noexcept { return _getTextBuffer().GetSize().Dimensions(); } diff --git a/src/types/ScreenInfoUiaProviderBase.h b/src/types/ScreenInfoUiaProviderBase.h index 53f7adabfba..eda5bf4d921 100644 --- a/src/types/ScreenInfoUiaProviderBase.h +++ b/src/types/ScreenInfoUiaProviderBase.h @@ -123,7 +123,7 @@ namespace Microsoft::Console::Types // mechanism for multi-threaded code. std::unordered_map _signalFiringMapping{}; - const COORD _getScreenBufferCoords() const; + const COORD _getScreenBufferCoords() const noexcept; const TextBuffer& _getTextBuffer() const noexcept; const Viewport _getViewport() const noexcept; void _LockConsole() noexcept;