Skip to content

Improve throughput a little#521

Merged
davidrg merged 21 commits into
masterfrom
performance
Jul 6, 2026
Merged

Improve throughput a little#521
davidrg merged 21 commits into
masterfrom
performance

Conversation

@davidrg

@davidrg davidrg commented Mar 28, 2026

Copy link
Copy Markdown
Owner

This PR builds on previous work done late last year to improve throughput a little by:

  • Not using semaphores to track vscreen dirtyness in GUI builds - the GUI renderer never waits on the semaphore so there is no benefit to its overhead. The old console mode renderer does wait on them, so it still uses them.
  • Use CRITICAL_SECTION instead of mutexes for the TCP/IP socket, Local Echo Buffer and SSH ring buffer improving throughput for SSH connections a little and non-SSH connections quite drastically.
  • Replace the NetCmd input thread (also used for PTY connections) with a new implementation that works the same way as the SSH subsystem and reuses its ringbuffer implementation.

This cuts the time it takes to handle a 10MB text file being dumped to the terminal from 5.94 to 1.7 seconds for SSH, and 15.59 to 1.9 seconds for telnet. PTY/pipe throughput is now about the same as SSH.

For comparison:

  • K95 3.0 beta 7: 56.48 seconds for SSH, 15.59 seconds for telnet, 2 minutes 50 seconds for a pty/pipe
  • TeraTerm: 26.29 seconds
  • Putty: 1.51 seconds
  • Windows Terminal: 1.39 seconds

~1.7 seconds is probably fine - no one can read that fast, so its really about making sure accidentally catting a huge log file doesn't cause problems (which it absolutely does in the current K95 release).

I don't see any other obvious low hanging fruit at this point. Any further gains in throughput will probably come down to minor tweaks that individually only make a very small difference. Based on some further experimentation with the profiler, probably things like:

  • Reducing unnecessary function calls. Eg
    • Function that just wraps another with slight parameter tweaks - just call the wrapped function directly
    • Function that checks a boolean and does nothing it its not set - check the boolean before calling rather than wasting time on a function call
  • Improve the way VscrnScrollPage erases lines by keeping a cached blank line that can just memcpy'd, rather than iterating through all the cells erasing them every time.

TODO:

  • Investigate some of the above things and commit anything that does make a measurable improvement
  • Look into dropping the compiled-in default render interval from 100ms to 20ms so that anyone not using the default config file shipped with recent K95 releases (which sets it to 20ms) doesn't have to suffer the abysmal latency of K95 2.x.

davidrg added 17 commits March 27, 2026 12:04
A number of functions called by VscrnScrollPage acquire and release the vscrn mutex even though VscrnScrollPage already does this, making it a bit of a waste of time. So don't do that anymore.
KUI builds never wait on the vscreen dirty semaphore - they just check each time the render timer fires if the vscreen is dirty and needs to be painted.

And it turns out semaphores are a kind of expensive way to store a boolean value - when processing large amounts of input, K95 spends about half of its time just setting the vscreen dirty semaphore.

So instead for KUI builds we'll try just using an integer. Whenever the vscreen is made dirty, the integer is incremented. And whenever the KUI render timer fires, it checks if this integers value is the same as the last time it looked. If the integer value has changed, the vscreen contents will have as well so its time to paint.

This seems to work fine, and it doubles throughput. K95G can now sink 10MB of text in around 2.8 seconds over SSH (telnet is slower due to locking around the local echo buffer)
in some places for thread synchronisation around TCPIP sockets and the Local Echo buffer. These are implemented in userspace so have much lower overhead than mutexes provided by the kernel if there is low contention.

This improves throughput for telnet and probably other non-SSH TCP/IP connections by around 5x bringing to around the same speed as SSH which doesn't currently use K95s TCP/IP connection management stuff.
# Conflicts:
#	kermit/k95/feature_flags.mak
#	kermit/k95/kui/makefile
…bled.

While the functions themselves check before acting, it's a waste of time calling them for every single character received if we know they're not going to do anything.
As VscrnGetLineFromTop just wraps VscrnGetPageLineFromTop.
…(50fps)

K95 has shipped with a k95custom.ini file that changes the setting to 20ms/50fps four years now, and I've not heard of any trouble or observed any myself.
davidrg added 2 commits July 6, 2026 16:47
The design of the new implementation is based on the way the SSH subsystem shuffles data between threads, and it reuses its ringbuffer implementation. This provides for a speedup of over 80x for terminal throughput.

I've run a few file transfers through it and used a terminal session through it both (PTY and PIPE), and it all seems to work fine. The design is the same as the SSH subsystem, so if there are any major issues with the design I expect they'd have already surfaced over there by now.
@davidrg davidrg marked this pull request as ready for review July 6, 2026 09:39
@davidrg davidrg force-pushed the performance branch 2 times, most recently from d48b72c to 9de463d Compare July 6, 2026 10:23
@davidrg davidrg merged commit 3b4530b into master Jul 6, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant