mirror of
https://github.com/nmasur/dotfiles
synced 2026-09-08 22:56:07 +00:00
post-TUI lag: autosuggestion culprit confirmed; add self-heal hook
A/B in a live lagging shell: disabling fish_autosuggestion_enabled cures the lag instantly, and re-enabling does NOT bring it back — the toggle resets the wedged reader state. __autosuggestion_unwedge (fish_postexec) now applies that reset after every command, at the moment TUIs exit. Builtins only, invisible, respects a deliberate manual disable. Flight recorder stays armed until the hook is proven in real use. Also from this investigation: wedged-thread evidence (sampler attach cures), lag-sample tool, flight recorder in the zellij fish wrapper.
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
# Self-heal for the post-TUI typing lag (fish 4.8.1, see docs/CHANGELOG.md
|
||||
# 2026-08-29..31): exiting a TUI can wedge fish's autosuggestion pipeline,
|
||||
# after which every keystroke at the commandline lags until the process is
|
||||
# replaced. Empirically validated cure: turn autosuggestions off and back on
|
||||
# in the affected shell. This hook applies that reset after every command —
|
||||
# i.e. at the exact moment a TUI has just exited — using only builtins, so it
|
||||
# is effectively free and invisible.
|
||||
#
|
||||
# Caveats, recorded for honesty: the manual cure had keystrokes between the
|
||||
# off and the on; whether an immediate off/on inside an event handler resets
|
||||
# the same reader state is unproven (the flight recorder stays armed to catch
|
||||
# any recurrence). If lag ever appears despite this hook, cure manually with
|
||||
# set -g fish_autosuggestion_enabled 0 (type a few chars)
|
||||
# set -g fish_autosuggestion_enabled 1
|
||||
# and save ~/.local/state/lag-triage/flight/ logs for that shell's pid.
|
||||
|
||||
# Respect a deliberate user choice to keep autosuggestions off.
|
||||
if test "$fish_autosuggestion_enabled" != 0
|
||||
set -g fish_autosuggestion_enabled 0
|
||||
set -g fish_autosuggestion_enabled 1
|
||||
end
|
||||
@@ -32,6 +32,15 @@ in
|
||||
description = "Reset terminal state left behind by a TUI";
|
||||
body = builtins.readFile ./unlag.fish;
|
||||
};
|
||||
lag-sample = {
|
||||
description = "Stack-sample fish and zellij while typing lag is happening";
|
||||
body = builtins.readFile ./lag-sample.fish;
|
||||
};
|
||||
__autosuggestion_unwedge = {
|
||||
description = "Reset autosuggestion state after each command to prevent post-TUI typing lag";
|
||||
onEvent = "fish_postexec";
|
||||
body = builtins.readFile ./autosuggestion-unwedge.fish;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# Capture stack samples of this fish process, the zellij server, and the
|
||||
# zellij client WHILE the typing lag is happening. This names the guilty
|
||||
# component directly: if fish's main thread is busy/blocked per keystroke the
|
||||
# stacks show exactly where; if fish is idle while typing feels laggy, the
|
||||
# delay is in zellij's render path instead.
|
||||
#
|
||||
# CAUTION (learned 2026-08-30): attaching the sampler to a lagging fish CURES
|
||||
# the lag (thread suspend/resume unwedges it), so run this from a DIFFERENT
|
||||
# pane with the lagging shell's pid: `lag-sample <pid>` (get it in the lagging
|
||||
# shell with the builtin-only `echo $fish_pid`). Have someone type in the
|
||||
# lagging pane while sampling runs — the first samples may catch the wedge.
|
||||
# With no argument it samples the current shell.
|
||||
|
||||
set -l target $fish_pid
|
||||
if test (count $argv) -ge 1; and test -n "$argv[1]"
|
||||
set target $argv[1]
|
||||
end
|
||||
|
||||
set -l outdir ~/.local/state/lag-triage
|
||||
mkdir -p $outdir
|
||||
set -l ts (date +%Y%m%d-%H%M%S)
|
||||
set -l dur 8
|
||||
|
||||
set -l fishfile $outdir/sample-$ts-fish-$target.txt
|
||||
/usr/bin/sample $target $dur 1 -file $fishfile &>/dev/null &
|
||||
disown
|
||||
|
||||
# this session's zellij server (socket path ends in the session name)
|
||||
set -l serverpid (pgrep -f "zellij --server.*/$ZELLIJ_SESSION_NAME\$")
|
||||
test -z "$serverpid"; and set serverpid (pgrep -f "zellij --server" | head -3)
|
||||
for pid in $serverpid
|
||||
/usr/bin/sample $pid $dur 1 -file $outdir/sample-$ts-zellij-server-$pid.txt &>/dev/null &
|
||||
disown
|
||||
end
|
||||
|
||||
# zellij clients (attached to ghostty): named zellij but without --server args
|
||||
set -l allserver (pgrep -f "zellij --server")
|
||||
set -l clientpid
|
||||
for pid in (pgrep -x zellij)
|
||||
contains $pid $allserver; or set -a clientpid $pid
|
||||
end
|
||||
for pid in $clientpid[1..3]
|
||||
/usr/bin/sample $pid $dur 1 -file $outdir/sample-$ts-zellij-client-$pid.txt &>/dev/null &
|
||||
disown
|
||||
end
|
||||
|
||||
# notify when done, without occupying the commandline
|
||||
fish -c "sleep (math $dur + 2); echo; echo '== lag-sample done: '$outdir'/sample-$ts-*.txt =='" &
|
||||
disown
|
||||
|
||||
echo "Sampling fish (pid $target), zellij server(s) [$serverpid], client(s) [$clientpid] for $dur s."
|
||||
echo ">>> TYPE CONTINUOUSLY IN THE LAGGING PANE NOW (junk text is fine) <<<"
|
||||
echo "Files: $outdir/sample-$ts-*.txt"
|
||||
@@ -20,8 +20,21 @@ let
|
||||
# harness on fish 4.8.1 (see docs/CHANGELOG.md 2026-08-29 and
|
||||
# presets/programs/lag-triage/upstream_repro.py). Spawning fish with the
|
||||
# variable already exported makes every pane shell immune.
|
||||
# Flight recorder for the still-unsolved post-TUI typing lag: sampling the
|
||||
# process CURES the lag (a wedged thread gets kicked loose), so the only way
|
||||
# to observe it is a recorder that is already running before the lag starts.
|
||||
# Armed by `touch ~/.local/state/lag-triage/RECORD`; new panes then log
|
||||
# fish's reader/thread internals to ~/.local/state/lag-triage/flight/.
|
||||
# Remove the RECORD file to disable (zero overhead when off).
|
||||
fish-no-query-term = pkgs.writeShellScriptBin "fish-no-query-term" ''
|
||||
export fish_features=no-query-term
|
||||
dir="$HOME/.local/state/lag-triage"
|
||||
if [ -e "$dir/RECORD" ]; then
|
||||
mkdir -p "$dir/flight"
|
||||
find "$dir/flight" -type f -mtime +3 -delete 2>/dev/null
|
||||
export FISH_DEBUG='reader,term-support,proc-termowner,iothread,fd-monitor,topic-monitor'
|
||||
export FISH_DEBUG_OUTPUT="$dir/flight/fish-$(date +%Y%m%d-%H%M%S)-$$.log"
|
||||
fi
|
||||
exec ${lib.getExe pkgs.fish} "$@"
|
||||
'';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user