-
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
The terminal is buffering in continuous printing #12336
Comments
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
That's odd, using cmd.mp4And in the terminal this: terminal.mp4 |
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as off-topic.
Alright, I don't know how this thread got so off the rails. Gonna minimize half the comments here. Alas, this didn't get better with #11890. The key here is that OP is just constantly throwing new lines into the buffer, so conpty needs to flush the new line to the terminal side each newline. IIRC I had tried avoiding that in the initial conpty implementation, but it had some bug that forced the immediate flushing. Something about #1173 & #10001 might be a potential solution here. Get ConPTY out of the equation. OP could probably remove a lot of pain by doing a cpp version of OPs code, for my reference#include <stdio.h>
#include <windows.h>
// This wmain exists for help in writing scratch programs while debugging.
int __cdecl wmain(int /*argc*/, WCHAR* /*argv[]*/)
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
int width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
char* f = new char [height * width];
memset(f, ' ', height * width);
f[(height / 2) * width + (width / 2)] = '*';
f[height * width - 1] = 0;
while(1) {
puts(f);
}
}
|
The code posted here has a bug where the null terminator for fwrite(f, sizeof(char), height * width, stdout); The immediate flushing of ConPTY is a significant performance issue. vtebench is a really nice tool and it shows that Windows Terminal is pretty alright in almost all areas... except for newline performance, which is 500-900x slower than other popular Terminals. See #10563. I suspect that fixing the scrolling performance will simultaneously fix this issue more or less.
|
Using any type of Unicode special sequence is problematic when running the code from CMD because then it's actually printed... |
@donno2048 Maybe I'm misunderstanding you, but if you're referring to my (and other's) suggestion to use Modern terminals will parse such escape sequences and not show them on the screen to the user. That way you can for instance tell your terminal to jump anywhere on the screen, or change the text color, with just a bit of hidden text. In order to use such sequences in CMD you can simply enable the |
Yeah, I know what an escape sequence I just didn't remember the term 😅 (yeah it isn't Unicode but you know what I mean), in my original issue (microsoft/vscode#142001) I mentioned the possibility to use them to resolve this issue partially, the problem as I said is that when not running in a compatible terminal but rather a "plain" CMD those characters will actually be printed which is problematic |
@donno2048 I probably continue to misunderstand you. I'm sorry in advance. 😅 If I'm right, does it work if you try to add this at the very start of your application? SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
You just blew my mind |
I tried that, but I'm getting weird results. What code are you referring to, can you show the whole thing, and with the compiler options? |
The code is the code from the first comment here. |
Try this: #include <stdio.h>
#include <windows.h>
int main(void) {
int height, width;
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
handle_t h = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(h, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
GetConsoleScreenBufferInfo(h, &csbi);
width = csbi.srWindow.Right - csbi.srWindow.Left + 1;
height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
}
char f[height][width];
memset(f, ' ', height * width);
f[height / 2][width / 2] = '*';
while (TRUE) {
printf("\x1b[H");
fwrite(f, sizeof(char), height * width, stdout);
}
} |
A thought I had: Perhaps I could reuse the "buffer but don't flush" from #14677. Flushing is expensive, buffering... less so. |
|
showerthought - does that just queue the frame to get flushed on the render thread, but ultimately, the render thread still ends up blocking on WriteFile. Like, I'm worried that we end up in a place where the flush is still just blocking on I/O instead of properly flushing async. 7418101 had an attempt at just moving the WriteFile into |
The problem with "buffering" linefeeds is that they destroy the conhost buffer, since that's only the size of the visible viewport. Every linefeed you execute without flushing is going to erase one line of content from the top of the viewport. By the time you eventually flush the buffer, there's potentially nothing left to send to the conpty client. What should have been pushed into their scrollback would now be lost. |
Oh sorry - to clarify: in the aforementioned branch, when we circle, I'd render the text buffer out to the conpty buffer but not immediately flush the conpty buffer to the end terminal. I'd wait until the normal frame happens to do that. That would get the conpty That would still preserve the text, because the "frame" still happens before we lose the text. It just gets written to the pipe at a later time. Now, the real issue is: can we speed writing to the pipe up? Is that slow because pipes are slow? Is it slow because Terminal drains the pipe too slow? Something something xproc calls, etc. |
terminal/src/renderer/vt/invalidate.cpp Lines 107 to 121 in 7010626
hmm. Do we need to
Probably not? That might be a place to speed this up a little. Not sure that'd end up actually optimizing that much out. I'd reckon we're probably outputting to the textbuffer a whole viewport worth of lines faster than a frame anyways |
OK. That makes perfect sense. I'd forgotten there was a conpty buffer. |
Windows Terminal version
1.11.3471.0
Windows build number
10.0.19043.1466
Other Software
No response
Steps to reproduce
Expected Behavior
One "*" character is supposed to appear in the middle of the terminal
Actual Behavior
The terminal is buffering just like I previously mentioned here
The text was updated successfully, but these errors were encountered: