terminal/src/renderer/vt/tracing.hpp
Michael Niksa 525be22bd8
Eliminate more transient allocations: Titles and invalid rectangles and bitmap runs and utf8 conversions (#8621)
## References
* See also #8617 

## PR Checklist
* [x] Supports #3075
* [x] I work here.
* [x] Manual test.

## 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:
1. It's assembling the prefix to the full title doing a concatenation.
   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.
2. A copy must be made because it was returning `std::wstring` instead
   of `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.
1. For some renderers, it's always a constant 1 element. They update
   that 1 element when dirty is queried and return it in the span with a
   span size of 1.
2. For other renderers with more complex behavior, they're already
   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 a `std::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 the
optional 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` and
`std::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 PTY
renderer, 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 returning
it 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 out
parameter so the caller can just hold onto it.

## Validation Steps Performed
- [x] `big.txt` in conhost.exe (GDI renderer)
- [x] `big.txt` in Terminal (DX, PTY renderer)
- [x] Ensure WDDM and BGFX build under Razzle with this change.
2021-02-16 20:52:33 +00:00

50 lines
1.8 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- tracing.hpp
Abstract:
- This module is used for recording tracing/debugging information to the telemetry ETW channel
--*/
#pragma once
#include <string>
#include <windows.h>
#include <winmeta.h>
#include <TraceLoggingProvider.h>
#include <telemetry/ProjectTelemetry.h>
#include "../../types/inc/Viewport.hpp"
TRACELOGGING_DECLARE_PROVIDER(g_hConsoleVtRendererTraceProvider);
namespace Microsoft::Console::VirtualTerminal
{
class RenderTracing final
{
public:
RenderTracing();
~RenderTracing();
void TraceString(const std::string_view& str) const;
void TraceInvalidate(const til::rectangle view) const;
void TraceLastText(const til::point lastText) const;
void TraceScrollFrame(const til::point scrollDelta) const;
void TraceMoveCursor(const til::point lastText, const til::point cursor) const;
void TraceSetWrapped(const short wrappedRow) const;
void TraceClearWrapped() const;
void TraceWrapped() const;
void TracePaintCursor(const til::point coordCursor) const;
void TraceInvalidateAll(const til::rectangle view) const;
void TraceTriggerCircling(const bool newFrame) const;
void TraceInvalidateScroll(const til::point scroll) const;
void TraceStartPaint(const bool quickReturn,
const til::pmr::bitmap& invalidMap,
const til::rectangle lastViewport,
const til::point scrollDelta,
const bool cursorMoved,
const std::optional<short>& wrappedRow) const;
void TraceEndPaint() const;
};
}