reedline icon indicating copy to clipboard operation
reedline copied to clipboard

POLL_WAIT hurts user experience

Open comex opened this issue 2 years ago • 2 comments

Platform macOS Terminal software Apple Terminal.app

To quote src/engine.rs:

// The POLL_WAIT is used to specify for how long the POLL should wait for
// events, to accelerate the handling of paste or compound resize events. Having
// a POLL_WAIT of zero means that every single event is treated as soon as it
// arrives. This doesn't allow for the possibility of more than 1 event
// happening at the same time.
const POLL_WAIT: u64 = 10;

In effect this adds 10ms of latency to every keystroke, by design. But this hurts the user experience for two reasons.

  • First, 10ms is a human-perceivable amount of lag by itself. On my 120Hz display, 10ms will delay the output by 1-2 frames depending on how far into the frame the keystroke was received. On a 60Hz display it would delay the output by 0-1 frames. 10ms is really not the end of the world, but when you add that to other sources of latency such as display latency and SSH connection latency, it starts to add up.

  • Second, there is a bug in Apple's Terminal.app where if a terminal program takes more than 1ms to respond to keystrokes, the output is delayed by an additional ~33ms. This is not reedline's fault, and I have filed a bug report with Apple about it, but removing the artificial latency significantly mitigates the bug. I tried setting POLL_WAIT to 0 and running Nushell, and it often is capable of responding within the 1ms deadline.

Still, the justification given for POLL_WAIT makes sense: it should improve performance when there's a very fast stream of events such as with pasted text. I suggest making the wait time dynamic. When receiving the first few events after a period of inactivity, handle them instantly. Then, if events continue to pile up quickly (more quickly than a human can type), start adding a delay. (If needed, resize events could also be treated specially and always given the delay.) That should preserve most of the benefit of the POLL_WAIT scheme, while eliminating the latency for normal typing.

Alternately, POLL_WAIT could be made runtime configurable.

comex avatar Oct 08 '23 00:10 comex

Thanks so much for the in depth research here and into the Terminal.app behavior.

True that 10ms is probably pessimistic for the general events. For pure text events we would probably be fine with a shorter waiting period on modern systems in general.

For the resize things are both more costly, as redrawing the whole output or polling the terminal state (we requested the cursor position after the resize for a while to update our assumptions) takes some noticeable time. Furthermore we don't have the logic for resizes quite nailed down (e.g. #477 https://github.com/nushell/reedline/issues/408 and a whole litany of similar ones on the nushell repo). And when manually dragging the size of the terminal window around, we observed that the artifacts may appear worse for terminals that seem to send the resizes events more immmediate (e.g. alacritty appeared more affected than kitty).

I think in the past we wanted to avoid the complexity of managing a separate timer but maybe we need to keep things separate so we strike a balance and work around Terminal.app's back-off.

There have been reports about artificially high CPU usage while spinning around the epoll_wait #521 so that might be a thing to watch out for when tweaking the timers.

sholderbach avatar Oct 11 '23 11:10 sholderbach

this latency is the number one thing that makes me not want to use nushell

mars-monkey avatar Mar 31 '24 11:03 mars-monkey