refterm
refterm copied to clipboard
Figure out what really happens in conhost
Now that I've started looking at performance of refterm, I've noticed that if you don't use stdio and instead use Windows' native WriteFIle, conhost no longer seems to take a significant amount of time.
splat.cpp is the stdio version of splat, and splat2.cpp is the Windows-native version. If you run both, you can see a dramatic difference between the two. While both are fast with fastpipe, splat2 is barely slower with fastpipe off, whereas splat is much slower with fastpipe off.
I am hoping that I just messed up the timings here, because I only looked at this briefly. But if I didn't, and there's something else going on here, it would be nice to know what it is!
- Casey
It looks like this is about the write pattern. Apparently, changing from text to binary mode largely fixes the problem, because stdio no longer goes through CR/LF buffering. This would seem to imply that conhost suffers from handoff overhead of some kind, such that writing one n-byte buffer is much faster than writing 10 (n/10)-byte buffers. This should be more rigorously verified, of course, but it is interesting.
- Casey
Does changing stuff with _set_fmode(_O_BINARY); fix the issue even with stdio slowness? Apparently, _O_BINARY needs to be explictly passed to get binary file descriptors on Windows when calling _open(); I am assuming they default to using text mode unless someone changes the setting?
It fixes slowness for how splat code is using large writes. If you do small writes, does not matter with fwrite+binary-mode or WriteFile, then there will be slowness regardless. That was the reason why enabling binary mode on stdout seems to "fix it" for splat, because then stdio stopped doing small writes and used code to call WriteFile on whole buffer that is passed it.
Apparently, changing from text to binary mode largely fixes the problem, because stdio no longer goes through CR/LF buffering.
I am not a programmer, but does changing the buffering mode with setvbuf to full buffering make a difference?
setvbuf(stdout, NULL, _IOFBF, BufSize);
I've had good results using full buffering and a large buffer for a logging terminal even though the documentation says "stream must refer to an open file that has not undergone an I/O operation since it was opened" and you have to use _fflush(stdout); for partial buffers