Fasd: Slow

Created on 10 Mar 2013  ·  11Comments  ·  Source: clvv/fasd

Been profiling my Terminal today and noticed that fasd is considerably slower than z.

z was added to my .zshrc with: .brew --prefix/etc/profile.d/z.sh

fasd with: eval "$(fasd --init posix-alias zsh-hook zsh-ccomp zsh-ccomp-install zsh-wcomp zsh-wcomp-install)"

The results when using zprof with them exclusively enabled was:

fasd

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    3        1527.75   509.25   83.55%   1527.75   509.25   83.55%  _fasd_preexec
 2)    2         107.40    53.70    5.87%    107.40    53.70    5.87%  compaudit
 3)    3          47.98    15.99    2.62%     47.98    15.99    2.62%  precmd
 4)    1         153.86   153.86    8.41%     46.46    46.46    2.54%  compinit
 5)    6          39.73     6.62    2.17%     39.73     6.62    2.17%  _setup
 6)    3          27.72     9.24    1.52%     27.72     9.24    1.52%  preexec

z

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    2          44.18    22.09   48.69%     44.18    22.09   48.69%  compaudit
 2)    1          67.12    67.12   73.98%     22.95    22.95   25.29%  compinit
 3)    1          15.62    15.62   17.22%     15.62    15.62   17.22%  precmd
 4)    1           7.73     7.73    8.52%      7.73     7.73    8.52%  preexec
 5)    1           0.14     0.14    0.15%      0.14     0.14    0.15%  _z
 6)    1           0.26     0.26    0.29%      0.12     0.12    0.13%  _z_precmd

It helps a lot to just use the simple setup: eval "$(fasd --init posix-alias zsh-hook)"

But still slow compared to z.

fasd (simple)

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    3         316.83   105.61   47.56%    316.83   105.61   47.56%  _fasd_preexec
 2)    2         146.31    73.15   21.96%    146.31    73.15   21.96%  compaudit
 3)    1         228.45   228.45   34.29%     82.14    82.14   12.33%  compinit
 4)    3          36.87    12.29    5.53%     36.87    12.29    5.53%  precmd
 5)    3          35.78    11.93    5.37%     35.78    11.93    5.37%  _setup
 6)    3          24.23     8.08    3.64%     24.23     8.08    3.64%  preexec

Since fasd is run on every folder change it's a fairly noticeable slowdown.

Most helpful comment

I don't know if this is still relevant, but using this snippet of code fixes the problem for me:

eval "$(fasd --init posix-alias)" # Anything you want enabled BUT zsh-hook

_fasd_preexec() {
    { eval "fasd --proc \$(fasd --sanitize \$2)"; } &|
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec _fasd_preexec

All 11 comments

I suspect the main reason is that fasd is called twice as an executable in preexec. This overhead can be minimized if fasd is sourced by zsh (source =fasd should work in zsh).

Also, to make the comparison more fair, you can tell fasd and z to use the same database, since the fasd just use z's data format.

I looked at the code and it seems possible to condense two executable call into one. I'll play around with the code when I have time.

Any updates on this? I would love to use fasd, but right now it's just too slow.

inlining the --sanitize sed regex's into the function also helps somewhat, but it's still very slow.

im having slowdowns too using simply: eval "$(fasd --init auto)" in .bash_profile.

@sindresorhus profiling sounds interesting. mind sharing how you do that?

@wamatt It's in the issue text.

I am also observing that fasd slows down my shell significantly.
I have eval "$(fasd --init auto)" in my .zshrc.

zsh 5.0.8 (x86_64-apple-darwin14.3.0) on OSX.

$ zprof

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    6         194,36    32,39   92,69%    194,36    32,39   92,69%  _fasd_preexec
 2)    6           5,96     0,99    2,84%      5,96     0,99    2,84%  _powerline_get_main_keymap_name
 3)    6           5,29     0,88    2,52%      5,29     0,88    2,52%  _powerline_set_true_keymap_name
 4)   24           2,40     0,10    1,15%      2,40     0,10    1,15%  url-quote-magic
 5)    6          11,82     1,97    5,64%      0,57     0,09    0,27%  _powerline_set_main_keymap_name
 6)    6           0,30     0,05    0,14%      0,30     0,05    0,14%  zle-line-finish
 7)    6           0,27     0,05    0,13%      0,27     0,05    0,13%  zle-line-init
 8)    6           0,19     0,03    0,09%      0,19     0,03    0,09%  omz_termsupport_precmd
 9)    6           0,18     0,03    0,09%      0,18     0,03    0,09%  omz_termsupport_preexec
10)    6           0,09     0,02    0,04%      0,09     0,02    0,04%  _powerline_set_jobnum
11)    6           0,06     0,01    0,03%      0,06     0,01    0,03%  omz_termsupport_cwd

-----------------------------------------------------------------------------------

 1)    6         194,36    32,39   92,69%    194,36    32,39   92,69%  _fasd_preexec

Still slow in 2017 :)

The slowdown was the first thing I noticed after installing fasd, so I did some profiling too.

With my default ~/.zshrc

$ time (for i in {1..20}; do zsh -ic 'exit'; done)

================
CPU 87%
user    1.913
system  0.880
total   3.207

With z: source /usr/share/z/z.sh

$ time (for i in {1..20}; do zsh -ic 'exit'; done)

================
CPU 87%
user    1.837
system  0.970
total   3.213

With fasd: eval "$(fasd --init posix-alias zsh-hook zsh-ccomp zsh-ccomp-install zsh-wcomp zsh-wcomp-install)"

$ time (for i in {1..20}; do zsh -ic 'exit'; done)

================
CPU 83%
user    2.207
system  1.123
total   3.993

So z adds < 1 ms, while fasd adds 39.3 ms.

I don't know if this is still relevant, but using this snippet of code fixes the problem for me:

eval "$(fasd --init posix-alias)" # Anything you want enabled BUT zsh-hook

_fasd_preexec() {
    { eval "fasd --proc \$(fasd --sanitize \$2)"; } &|
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec _fasd_preexec

from here
I suspect the main reason is that fasd is called twice as an executable in preexec. This overhead can be minimized if fasd is sourced by zsh (source =fasd should work in zsh).

Is that = in the source statement meaningful?

I don't know if this is still relevant, but using this snippet of code fixes the problem for me:

eval "$(fasd --init posix-alias)" # Anything you want enabled BUT zsh-hook

_fasd_preexec() {
    { eval "fasd --proc \$(fasd --sanitize \$2)"; } &|
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec _fasd_preexec

I don't see any performance difference if I go with the output of zsh --init zsh-hook which is below.
Not sure if it's relevant but I save the below snipped in a cache file and then source that instead of doing an eval over the output.

# add zsh hook
_fasd_preexec() {
  { eval "fasd --proc $(fasd --sanitize $1)"; } >> "/dev/null" 2>&1
}
autoload -Uz add-zsh-hook
add-zsh-hook preexec _fasd_preexec
Was this page helpful?
0 / 5 - 0 ratings

Related issues

simendsjo picture simendsjo  ·  6Comments

rendybjunior picture rendybjunior  ·  14Comments

ixil picture ixil  ·  5Comments

josephholsten picture josephholsten  ·  15Comments

mhlinder picture mhlinder  ·  3Comments