You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have searched the issues (including closed ones) and believe that this is not a duplicate.
If related to a plugin, I prefixed the issue title with the name of the plugin.
OS version and name: Ubuntu 22.04
Fish shell version: 3.7.1
VirtualFish version: 2.5.6
Issue
I've been profiling my Fish shell startup time and have found the VirtualFish loading script to consume a significant chunk of time.
# Without "virtualfish-loader.fish" installed
$ time fish -c exit
________________________________________________________
Executed in 38.06 millis fish external
usr time 30.62 millis 0.00 micros 30.62 millis
sys time 8.52 millis 734.00 micros 7.79 millis
# With "virtualfish-loader.fish" installed
$ time fish -c exit
________________________________________________________
Executed in 188.56 millis fish external
usr time 152.15 millis 727.00 micros 151.42 millis
sys time 92.58 millis 313.00 micros 92.27 millis
After doing some investigation, I've found it to be directly caused by the __vfsupport_setup_autocomplete function, specifically the part that extracts the help text from all the VF functions.
Here's timing information with an without that specific function:
$ time source virtualfish-loader.fish
time source virtualfish-loader.fish
________________________________________________________
Executed in 150.11 millis fish external
usr time 112.20 millis 16.33 millis 95.86 millis
sys time 91.53 millis 15.33 millis 76.20 millis
# Removed "emit virtualfish_did_setup_plugins" so the function is not called in virtual.fish
$ time source virtualfish-loader.fish
________________________________________________________
Executed in 10.14 millis fish external
usr time 8.00 millis 3.86 millis 4.14 millis
sys time 2.25 millis 0.00 millis 2.25 millis
To further investigate, I've extracted that specific function to its own script and profiled it as follows (repeated parts reduced for clarity):
fish --profile=/tmp/vf-completion vfsupport_setup_autocomplete.fish
Time Sum Command
7 7 > function __vfsupport_setup_autocomplete ...
26 111802 > __vfsupport_setup_autocomplete
2 2 -> function __vfcompletion_needs_command...
1 1 -> function __vfcompletion_using_command...
263 111685 -> for sc in (functions -a | sed -n '/__vf_/{s///g;p;}')...
3396 3396 --> functions -a | sed -n '/__vf_/{s///g;p;}'
246 10358 --> set -l helptext (functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|")
1192 10112 ---> functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|"
739 4739 ----> command /usr/bin/grep --color=auto $argv
69 69 --> complete -x -c vf -n '__vfcompletion_needs_command' -a $sc -d $helptext
365 5952 --> set -l helptext (functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|")
978 5587 ---> functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|"
4609 4609 ----> command /usr/bin/grep --color=auto $argv
65 65 --> complete -x -c vf -n '__vfcompletion_needs_command' -a $sc -d $helptext
120 5830 --> set -l helptext (functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|")
879 5710 ---> functions "__vf_$sc" | grep -m1 "^function" | sed -E "s|.*'(.*)'.*|\1|"
4831 4831 ----> command /usr/bin/grep --color=auto $argv
(...repeated 10+ times...)
8 48 --> complete -x -c vf -n '__vfcompletion_needs_command' -a $sc -d $helptext
32 32 -> complete -x -c vf -n '__vfcompletion_using_command activate' -a "(vf ls)"
21 21 -> complete -x -c vf -n '__vfcompletion_using_command connect' -a "(vf ls)"
17 17 -> complete -x -c vf -n '__vfcompletion_using_command rm' -a "(vf ls)"
18 18 -> complete -x -c vf -n '__vfcompletion_using_command upgrade' -a "(vf ls)"
23 70 > __vfsupport_remove_env_on_deactivate_or_exit PROCESS_EXIT 436514 0
3 47 -> if begin; set -q _VF_TEMPORARY_ENV; and [ $_VF_TEMPORARY_ENV = (basename $VIRTUAL_ENV) ]; end...
32 44 --> begin...
12 12 ---> set -q _VF_TEMPORARY_ENV
As you can see, the for sc in (functions ...) loop is taking the majority of the time (>100ms), and this is almost entirely attributed to every invokation of grep taking ~5ms.
Possible Solutions
Since the completions don't often change, it might be better to generate them once and cache them. Here's a working example that can replace the __vfsupport_setup_autocomplete function in virtual.fish:
function __vfsupport_initialize_autocomplete
# Source the completion file if it exists. set-q XDG_CACHE_HOME; orset XDG_CACHE_HOME $HOME/.cache
iftest-f$XDG_CACHE_HOME/fish/virtualfish_complete.fish
source $XDG_CACHE_HOME/fish/virtualfish_complete.fish
else# If not, create it and source it.mkdir-p$XDG_CACHE_HOME/fish
# add completion for subcommandsfor sc in (functions-a|sed-n'/__vf_/{s///g;p;}')
set-l helptext (functions"__vf_$sc"|grep-m1"^function"|sed-E"s|.*'(.*)'.*|\1|")
echocomplete-x-c vf -n'__vfcompletion_needs_command'-a\'$sc\' -d \'$helptext\' >> $XDG_CACHE_HOME/fish/virtualfish_complete.fish end echo 'complete-x-c vf -n\'__vfcompletion_using_command activate\' -a "(vf ls)"'>>$XDG_CACHE_HOME/fish/virtualfish_complete.fish
echo'complete -x -c vf -n \'__vfcompletion_using_command connect\' -a "(vf ls)"'>>$XDG_CACHE_HOME/fish/virtualfish_complete.fish
echo'complete -x -c vf -n \'__vfcompletion_using_command rm\' -a "(vf ls)"'>>$XDG_CACHE_HOME/fish/virtualfish_complete.fish
echo'complete -x -c vf -n \'__vfcompletion_using_command upgrade\' -a "(vf ls)"'>>$XDG_CACHE_HOME/fish/virtualfish_complete.fish
source $XDG_CACHE_HOME/fish/virtualfish_complete.fish
endendfunction __vfsupport_setup_autocomplete
function __vfcompletion_needs_command
set cmd (commandline-opc)
iftest (count$cmd) -eq 1 -a$cmd[1] = 'vf'return 0
endreturn 1
endfunction __vfcompletion_using_command
set cmd (commandline-opc)
iftest (count$cmd) -gt 1
iftest$argv[1] = $cmd[2]
return 0
endendreturn 1
end
__vfsupport_initialize_autocomplete
end
This function takes ~120ms upon the first run, but subsequent runs take <2ms, representing a significant speedup!
The text was updated successfully, but these errors were encountered:
Many thanks for the detailed report, Anthony. It is rare and refreshing to see not only a detailed report, but also some concrete ideas and code regarding how the issue might be resolved. Bravo!
As you accurately point out, VirtualFish completions rarely change, which makes me wonder whether we need to generate the completions (even in cached form) on every shell startup. Perhaps we could install the completions as part of the vf install process? Maybe with a separate vf install --completions flag that only generates the completions, to be used to update completions in case they have changed?
After reviewing where to put completions, perhaps they should go in ~/.local/share/fish/vendor_completions.d?
Looking forward to your thoughts. Once again, much appreciated!
Issue
I've been profiling my Fish shell startup time and have found the VirtualFish loading script to consume a significant chunk of time.
After doing some investigation, I've found it to be directly caused by the
__vfsupport_setup_autocomplete
function, specifically the part that extracts the help text from all the VF functions.Here's timing information with an without that specific function:
To further investigate, I've extracted that specific function to its own script and profiled it as follows (repeated parts reduced for clarity):
As you can see, the
for sc in (functions ...)
loop is taking the majority of the time (>100ms), and this is almost entirely attributed to every invokation of grep taking ~5ms.Possible Solutions
Since the completions don't often change, it might be better to generate them once and cache them. Here's a working example that can replace the
__vfsupport_setup_autocomplete
function in virtual.fish:This function takes ~120ms upon the first run, but subsequent runs take <2ms, representing a significant speedup!
The text was updated successfully, but these errors were encountered: