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


16

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

我做了以下工作~/.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的原始终端上也同样慢)。


那不应该发生。我是否正确使用MacPort的bash完成功能?
slhck

您加载的文件是什么样的?
丹尼尔·贝克

@slhck:是的,我的确在使用Macport的bash补全功能
消失了

@Daniel:除此之外,一切都很好。我剖析了几乎每一行。
消失了

5
我遇到同样的缓慢情况,并且正在使用Homebrew。
布莱斯2012年

Answers:


10

简短版:从中删除一行,/usr/local/etc/bash_completion可以将打开新标签页的时间从十秒减少到四分之一秒。继续阅读以获取详细信息。

我正在使用自制软件的bash-completion,并遇到了相同的问题。每次打开终端时,加载bash完成脚本都花费了十秒钟以上。

在大多数时间里,have()函数似乎只占用一行:type用于确定是否安装了命令行程序的调用。

使用默认have()功能并提供所有提供的bash完成脚本后,加载脚本将花费10.561s(通过在文件中添加前缀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.258s。可以通过从/usr/local/etc/bash_completion.d目录中删除不必要的完成脚本(符号链接)来进一步减少此时间。

我不知道为什么打给我type这么长时间。我接下来要调查。

这种方法的一个潜在缺点是,即使您没有使用bash完成函数,它也会将其加载到内存中。该have()功能检查是否已安装命令或应用程序。如果不是这样,则完成脚本通常会决定不打扰自己加载,因为这将毫无用处。

目前,我对折衷感到满意,但type随着时间的推移,我将继续探讨该问题。如果找到更好的解决方案,我将更新答案。


对我来说,注释此行可以将50ms时间从230ms减少到180ms。当然,我从来没有遇到过这么糟糕的地方。👍–
爱德华·安德森

这仅节省了大约60ms,因此我没有保留解决方法。我没有十秒钟的等待时间,但是大约是2秒,这有点令人讨厌。
danemacmillan

7

对于任何人来的结论是,启动时间为新壳在MacOS是对他们来说太缓慢,这是解决方案

我只是发现实际上可以通过安装两个软件包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启动时间从605ms减少到244ms。这是一个巨大的速度改进。

我怀疑我们中的许多人都在犯同样的错误,因为brew info统计数据表明前者的安装量很多,而后者却很少:

在此处输入图片说明

应当注意,当前选择的答案提到注释了一些行,这仅对启动时间进行了少许改进(如果使用旧bash-completion软件包,很多人可能会这样做),但对新bash-completion@2软件包没有任何影响:此新软件包无论如何都很快。这意味着不需要黑客。

TL; DR:

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

切记将您的.bashrc.bash_profile文件中的完成文件的源路径更新为。

资料来源:


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


编辑:

对于任何想要解释此问题的技术细节的人,我已经在Homebrew论坛上进行了详尽的介绍。总而言之,之所以bash-completion@2如此之快,是因为编写它的原因是它不再急切地加载所有完成文件。取而代之的是按需加载完成文件,或者如作者所描述的那样以不急于加载的方式加载它们。


我认为macOS上的默认Bash版本仍然是v3.2-我不认为它与Bash v4.2一起提供。您是否在其中提到macOS随Bash v4.2 +一起提供了参考?
nwinkler

1
@nwinkler你是正确的。我不知道为什么要提到它,因为MacOS仍随附version 3.2.57(1)-release (x86_64-apple-darwin18)。感谢您指出了这一点; 我已从我的帖子中删除了该行。
danemacmillan

1
莫名其妙,我知道...感谢您更新答案!
nwinkler

3

有了Godbyk答案的提示,我发现我的PATH变量有几个目录,这些目录没有任何二进制文件或不存在,将其删除大大加快了速度。换句话说,这是我在bashrc中拥有的路径:

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

然后我将其更改为:

PATH="$GOPATH/bin:$PATH"

这是因为have该bash补全中的函数会查找每个命令,并且对于这些二进制文件中的每个二进制文件,我都有太多无用的目录要访问,因此删除它们会使它们加速。


通过从PATH环境变量中删除不存在的路径,我还设法将加载时间从大约5秒更改为不到1秒。
juriejan

0

我遇到过同样的问题。一些简单的调试技巧使我找到了根本原因。

首先,启用,DEBUG mode以便您可以看到正在发生的事情:

export BASH_COMPLETION_DEBUG=true

这样可以在控制台上进行详细打印,因此您可以看到最后一个命令。现在,您可以在后台执行脚本,然后您会看到发生了什么

. /opt/local/etc/bash_completion &

不要使用PID,您可以使用ps或进行跟踪pstree

pstree -p <the PID>

| |     \-+= 82095 mfellows -bash
| |       \-+- 82103 mfellows -bash
| |         |-+- 82104 mfellows cargo --list
| |         | \--- 82106 mfellows rustc -vV --cap-lints allow

如您所见,它启动了一些与锈相关的命令,这些命令已经花费了很长时间。

暂时移除/opt/boxen/homebrew/etc/bash_completion.d/cargo可解决我的症状。


-1

如果您正在运行MacPorts> = 2.1.2和Mountain Lion,则看来您bash_profile错了。按照有关如何使git-completion.bash在Mac OS X上运行的说明进行操作?。我认为这可以加快自动完成速度。

另一个解决方案是尝试通过Fink或Homebrew 安装自动完成功能。如果那不起作用,则可以尝试另一个外壳。我发现,对于自动完成(开箱即用),Fish shell非常出色。尽管版本2仍处于测试版中,但我还是强烈推荐它。


-1

我猜你的拳头太旧了。我正在运行Mountain Lion附带的股票重击,这是我看到的内容:

$ port info bash-completion
bash-completion @2.0, Revision 1 (sysutils)

Description:          Programmable completion library for bash. This port
                      **requires bash >=4.1** and is meant to be used together with
                      the bash port.
Homepage:             http://bash-completion.alioth.debian.org/

Runtime Dependencies: bash
Conflicts with:       bash-completion-devel
Platforms:            darwin
License:              GPL-2+
Maintainers:          raimue@macports.org

$ bash --version
GNU bash, version **3.2.48(1)-release (x86_64-apple-darwin12)**
Copyright (C) 2007 Free Software Foundation, Inc.

我看不到有此端口命令。:(我如何找出混帐标签完成软件是我的Mac上运行的。
迪恩希勒

@DeanHiller这个答案是指Macports软件包管理器,它提供了port命令。MacPorts的的bash补全的应用程序将会比提供OS X.的一个新的
马特小号
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.