Closed
Description
Description
As shown in #10563, ConPTY suffers from significant performance drop with too much scrolling request. A typical repro is:
time bash -c 'yes | head -n1000000'
This is a typical trace of OpenConsole.exe
under the above workload:
Discussion
The main issue that caused this, I think, is that VtRenderer suffers from using the same interface as other graphic renderer. To break it down:
- Carriage return & linefeed can trigger graphic renderer to circling the buffer & force repaint. But for VtRenderer, it dosen't really need to do too much, other than print the newly added line. It doesn't really need to flush the buffer (
EndPaint
as shown above), because the actual text added to the buffer is only a single line (120 chars in a typical display). - The
_PaintBufferOutputHelper
method insiderrenderer
is obviously graphic-oriented. After all these years of development, I don't think it suits the need for VtRenderer anymore. An example is Reduce string operation cost in VtEngine::PaintBufferLine #10567, in which I try to reduce the cost of reassemble the line buffer. The reason why we need to reassemble the clusters, is because they are produced by splitting up the original buffer in_PaintBufferOutputHelper
, which is heavily required by graphic renderers. If we have a dedicated interface, unnecessary operations like these can be eliminated. - In
VtEngine
&XtermEngine
, the actual number of methods that're both overridden and practically useful is rather small, comparing to the large amount of base methods inIRenderEngine
. This indicates that the fundamental goal ofVtEngine
isn't really the same as the graphic renderers.
Proposed solution
I'm proposing a three-phase refactoring process for VtEngine to move away from IRenderEngine
:
- Separate the methods in
VtEngine
that are heavily burdened by the current design, such as_PaintBufferOutputHelper
. We add them as base methods toIRenderEngine
.VtEngine
is still a child class ofIRenderEngine
, but we add dedicated IO methods in it and test the performance gain. - Separate the rest the methods in
VtEngine
same way as above. - When we finished the first two steps, we should have a clear path towards adding a dedicated interface just for
VtEngine
, probably name itIVtEngine
. Then we can createIVtEngine
fromIRenderEngine
, and letIRenderEngine
be what's left in it.
CC @DHowett @miniksa @zadjii-msft @lhecker @j4james for discussion.
(How can I just At everyone who's collaborator of this project. That would be helpful.)