Reduce cost of resetting row attributes (#15497)

Performance of printing enwik8.txt at the following block sizes:
4KiB (printf): 54MB/s -> 54MB/s
128KiB (cat): 101MB/s -> 104MB/s

## Validation Steps Performed
This change is easily verifiable via review.
This commit is contained in:
Leonard Hecker 2023-06-15 17:34:29 +02:00 committed by GitHub
parent f3e2890084
commit b8f402f64b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 28 additions and 3 deletions

View File

@ -123,11 +123,13 @@ LineRendition ROW::GetLineRendition() const noexcept
// - Attr - The default attribute (color) to fill
// Return Value:
// - <none>
void ROW::Reset(const TextAttribute& attr)
void ROW::Reset(const TextAttribute& attr) noexcept
{
_charsHeap.reset();
_chars = { _charsBuffer, _columnCount };
_attr = { _columnCount, attr };
// Constructing and then moving objects into place isn't free.
// Modifying the existing object is _much_ faster.
*_attr.runs().unsafe_shrink_to_size(1) = til::rle_pair{ attr, _columnCount };
_lineRendition = LineRendition::SingleWidth;
_wrapForced = false;
_doubleBytePadded = false;

View File

@ -124,7 +124,7 @@ public:
void SetLineRendition(const LineRendition lineRendition) noexcept;
LineRendition GetLineRendition() const noexcept;
void Reset(const TextAttribute& attr);
void Reset(const TextAttribute& attr) noexcept;
void TransferAttributes(const til::small_rle<TextAttribute, uint16_t, 1>& attr, til::CoordType newWidth);
void CopyFrom(const ROW& source);

View File

@ -402,6 +402,11 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
return _runs;
}
container& runs() noexcept
{
return _runs;
}
// Get the value at the position
const_reference at(size_type position) const
{

View File

@ -606,6 +606,24 @@ namespace til
_capacity = capacity;
}
// This is a very unsafe shortcut to free the buffer and get a direct
// hold to the _buffer. The caller can then fill it with `size` items.
[[nodiscard]] T* unsafe_shrink_to_size(size_t size) noexcept
{
assert(size <= N);
if (_capacity != N)
{
_deallocate(_data);
}
_data = &_buffer[0];
_capacity = N;
_size = size;
return &_buffer[0];
}
void push_back(const T& value)
{
emplace_back(value);