V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Kobayashi
V2EX  ›  分享发现

autojump, z, z.lua, fasd 的区别

  •  
  •   Kobayashi · 2019-01-20 18:42:41 +08:00 · 3427 次点击
    这是一个创建于 2169 天前的主题,其中的信息可能已经有所发展或是发生改变。

    转载自 reddit r/linux。原本是有人用 Lua 写了一个 z,下面有回复者根据 4 者挂载的钩子不同做出了分析。

    预先解释一下几种钩子:

    • chpwd,每次cd切换目录后执行函数。BASH 没有对应的这个钩子,这也是为什么nvm下给出的自动切换方案,BASH 是要重写cd函数,更多参考nvm issue #110
    • precmd,终端输入命令前执行,shell 主题就是用的这个钩子
    • preexec,命令执行前,此时已经有了键入的命令,可以获取键入的内容。

    I have a question about the hooks. I use zsh. As far I know, z.lua and z use precmd hook, fasd uses preexec hook, autojump uses chpwd hook. So, who is doing the job right?

    Update: I got an answer by myself.

    autojump is hooked on chpwd in zsh. Because the frecent is based on the times you accessed the directory.

    z take the time you spent in the directory into consideration. So z hooks on precmd. The same thing happens with z.lua.

    fasd takes a further step, not only because fasd combines z and v together. Besides taking the time you spent in the directory into consideration, it also extracts path or file info from your command line. This explains why fasd uses the preexec hook.

    Unlike v, who get files you used from ~/.viminfo, fasd gives you four backends to get the list of files you opened. You may guess it, there's one backend called current, that gets the list based on the files extracted from your command line.

    Let's talk about the speed of adding path into history data file.

    The 1st thing I want to mention is, fasd is not that slow. Though fasd is slower that z, but it's much faster than autojump.

    I benchmarked the four on my machine, the result differs from the one made by the author of z.lua.

    time cost: autojump > fasd > _z > _zlua

    Tested on my mbp (15-inch, 2016):

    ❯ time (autojump --add /tmp)
    ( autojump --add /tmp; )  0.12s user 0.05s system 68% cpu 0.249 total
    
    ❯ time (fasd -A /tmp)
    ( fasd -A /tmp; )  0.02s user 0.01s system 69% cpu 0.042 total
    
    ❯ time (_z --add /tmp)
    ( _z --add /tmp; )  0.01s user 0.01s system 56% cpu 0.019 total
    
    ❯ time (_zlua --add /tmp)
    ( _zlua --add /tmp; )  0.00s user 0.00s system 75% cpu 0.008 total
    

    (因为据 z.lua 作者所说,最耗时的部分就是添加路径到历史数据文件这一过程,所以针对此过程测试。但z.lua 作者的测试应该有问题,autojump 由于 Python 解释器启动耗时问题,按理说肯定是最慢的,但 z.lua 作者的结果中却是 fasd 最慢。我自己的测试情况也是 fasd 比 z 略慢,但远快于 autojump。)

    autojump is written in Python. One of the main cause for its slowness is, starting up the Python interpreter takes time.

    Both z and fasd are written in shell scripts. Because fasd extracts info from your command line using sed and regex, it's slower than z.

    z.lua is the fastest one among the four. It seems z.lua takes the advantage of Lua the language.

    You may have your own choice now. Before I finish this, I'd like to give you another advice about how to speed up the startup time of the four.

    You should avoid generating the init code time by time. Generate the init codes once and cache them, source the cache next time you spawn a new shell.

    prezto/modules/fasd/init.zsh

    cache_file="${TMPDIR:-/tmp}/prezto-fasd-cache.$UID.zsh"
    if [[ "${commands[fasd]}" -nt "$cache_file" \
        || "${ZDOTDIR:-$HOME}/.zpreztorc" -nt "$cache_file" \
        || ! -s "$cache_file"  ]]; then
        # Set the base init arguments.
        init_args=(zsh-hook)
    
        # Set fasd completion init arguments, if applicable.
        if zstyle -t ':prezto:module:completion' loaded; then
            init_args+=(zsh-ccomp zsh-ccomp-install zsh-wcomp zsh-wcomp-install)
        fi
    
        # Cache init code.
        fasd --init "$init_args[@]" >! "$cache_file" 2> /dev/null
    fi
    

    Anyway, z.lua is a promising project. If you only need directory jumping, it may be the best choice.

    总结一下,此评论给出的结论基本是

    • autojump 最差,不仅是算法上没有考虑用户在一个路径内耗时(命令数目),Python 启动解释器耗时用在这种场景显然比其他几位劣势
    • fasd 功能最强,结合和 z 与 v。不仅计算了某路径下执行命令的数量,还考虑了用户的输入中出现的路径、文件。其 v 功能也比原来的 v 好。
    • z.lua 速度最佳。不过这里没有对其算法做深究,好像在 z 的算法上有些改进?

    原文链接,z.lua - A better method to change directory.

    另附各工具项目主页:

    当然,现在的主流做法是搭配 fuzzy finder 使用,详见fzf wiki Examples#z

    另外这个回复中最有意思的是 Prezto 模块的优化。翻看了一下,Prezto 中 command-not-found 模块也作了类似处理,缓存了命令的位置。python 模块中的 pyenv 初始化使用--no-rehash,减小耗时,node 模块中 nodenv、ruby 模块中的 rbenv 都做了这样的处理。相比之下,Oh-My-ZSH 的插件则缺少对应这种优化。

    各位还知不知道其他类似的比较,可以分享一下。

    1 条回复    2019-01-21 01:20:05 +08:00
    hanxiV2EX
        1
    hanxiV2EX  
       2019-01-21 01:20:05 +08:00 via Android
    z.lua 的作者在这里 @skywind3000
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1165 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 18:21 · PVG 02:21 · LAX 10:21 · JFK 13:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.