为什么 bash 完成在 OS X 上加载如此之慢?

为什么 bash 完成在 OS X 上加载如此之慢?

我不明白为什么 bash 完成在我的 MacBook Pro 上加载速度这么慢。

我在我的中做了以下事情~/.bash_profile

echo "Loading BashCompletion..."
if [ -f /opt/local/etc/bash_completion ]; then
    . /opt/local/etc/bash_completion
fi
echo "BashCompletion loaded."

bash_completion 的执行时间通常为 > 2 秒。

当我在终端上工作时,我发现这真的很烦人,因为需要我不断打开新标签。

有什么方法可以缓存这个或类似的东西吗?

(请注意,我正在使用 iTerm2,它在 Mac 上的原始终端上也同样慢)。

答案1

如果有人认为 MacOS 上新 shell 的启动时间太慢,这是解决方案

我刚刚发现事实上可以通过 安装的软件包brew。我已经安装该bash-completion软件包多年了,从来没有想过要质疑它,尽管在这段时间里我已经从 Bash 3 升级到 4,再到现在的 5。不过,时不时地,我会重新审视这个问题,经常偶然发现这个 StackOverflow 讨论。

还有另外一个包裹bash-completion@2

有什么区别?bash-completion适用于 Bash 版本 3.2。bash-completion@2适用于 Bash 版本 4.1+ 和 5。

在删除旧bash-completion包并安装后bash-completion@2,我的 shell 启动时间从 605 毫秒缩短到了 244 毫秒。速度有了很大的提升。

我怀疑我们中的许多人都犯了同样的错误,因为brew info统计数据显示,前者拥有大量安装,而后者安装量却很少:

在此处输入图片描述

需要注意的是当前选定的答案提到注释掉一些行,这只会稍微改善启动时间(如果使用旧bash-completion包,很多人可能都是这样),但对新包没有任何影响bash-completion@2:这个新包无论如何都很快。这意味着不需要任何黑客攻击。

总结:

brew uninstall bash-completion && brew install bash-completion@2

.bashrc请记住将或文件中的完成文件的源路径更新为.bash_profile

资料来源:


作为一个有点相关的话题,我rclone经常使用该实用程序,因此安装了它。它也恰好有我见过的最大的完成文件。删除它将我的 shell 启动时间减少到 ~120ms,这非常快。


编辑:

对于那些想要了解该问题技术细节的人,我已经在 Homebrew 论坛上对此进行了详细的介绍bash-completion@2总结一下,速度快得多的原因是因为它的编写方式使得它不再热切地加载所有完成文件;相反,它会按需加载完成文件,或者如作者所述,它会以不热切方式。

答案2

简短版本:从中删除一行可/usr/local/etc/bash_completion将打开新标签的时间从十秒缩短至四分之一秒。请继续阅读以了解详情。

我正在使用 homebrew 的 bash-completion,遇到了同样的问题。每次打开终端时,加载 bash 完成脚本都要花十多秒的时间。

大部分时间似乎都被函数中的一行占用have():调用来type确定是否安装了命令行程序。

使用默认have()函数和所有提供的 bash 完成脚本,需要 10.561 秒来加载脚本(通过在我的文件中的行time前面添加前缀来报告)。. /opt/local/etc/bash_completion.bash_profile

注释掉PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin type $1 &>/dev/null &&我的/usr/local/etc/bash_completion脚本行后(保留该have=yes行,打开一个新终端只需要 0.258 秒。通过从目录中删除不必要的完成脚本(符号链接),可以进一步减少这个时间/usr/local/etc/bash_completion.d

我不知道为什么调用type耗时这么长。我接下来会调查此事。

这种方法的一个潜在缺点是,它会导致 bash 完成函数被加载到内存中,即使您不需要它们。该have()函数会检查命令或应用程序是否已安装。如果没有,完成脚本通常会决定不费心加载自身,因为它没有用处。

目前,我对这种权衡感到满意,但我会type随着时间继续探索这个问题。如果我找到更好的解决方案,我会更新我的答案。

答案3

根据 godbyk 的回答,我发现我的 PATH 变量中有一些目录没有任何二进制文件或不存在,删除它们可以大大加快速度。换句话说,这是我在 bashrc 中的 PATH:

PATH="$GOPATH/bin:/some/directory/not/existing:/some/empty/directory:/some/directory/without/binaries:$PATH"

然后我将其改为:

PATH="$GOPATH/bin:$PATH"

这是因为havebash 补全中的函数会查找每个命令,而我有太多无用的目录需要为每个二进制文件进行访问,因此删除它们可以加快速度。

答案4

如果你运行的是 MacPorts >= 2.1.2 和 Mountain Lion,那么你的操作似乎bash_profile不正确。请按照如何让 git-completion.bash 在 Mac OS X 上运行?。我认为这可以加快自动完成速度。

另一个解决方案是尝试通过以下方式安装自动完成功能芬克或者 Homebrew。如果这不起作用,你可以尝试另一个 shell。我发现鱼壳在自动完成方面非常出色(开箱即用)。虽然版本 2 仍处于测试阶段,但我强烈推荐它。

相关内容