在使用 zsh 在文件夹中执行自动完成操作时,我已经遇到性能问题相当长一段时间了。最后,我投入了一些时间来尝试了解导致问题的原因以及如何解决它。不幸的是,我不得不停在“什么”上,“如何解决”仍然是一个问号。
当在启用跟踪的情况下在调试中运行 zsh(并禁用我的.zshrc.local
)时,我设法清楚地看到它:
当按双 TAB 时,执行$ cd ~/Documents/<TAB>
,我得到:
....
+_cd:88> eval 'dir=( ~Documents/ )'
+(eval):1> dir=( '~Documents/' )
....
最新的响应时间约为 3 秒。
这种情况发生在文件夹自动完成的每个级别(cd a/<TAB>
、cd a/b/<TAB>
、... ),而不是cd <TAB>
.
我尝试过设置set -o magicequalsubst
.
答案1
_cd
当前版本中补全函数的第 88 行zsh
位于仅当cdablevars
启用该选项时才能到达的部分。
启用该选项后,cd username
或者cd var
将cd
进入用户的主目录username
或存储的路径(如果这些用户/var存在并且当前目录或中$var
没有username
/目录) 。换句话说,行为就像如果不作为目录存在(在或中)。var
$cdpath
cd foo
cd ~foo
foo
.
$cdpath
cd
现在,这只是为/所做的事情pushd
。当_cd
构建可能的完成列表并且您Documents/
到目前为止已经输入时,它需要为您提供文件夹的子目录列表Documents
,而且,由于您已经启用了 ,所以还需要提供用户主目录或用户主cdablevars
目录的子目录列表。变量Documents
中存储的目录$Documents
(如果有)。
这就是它这样做的原因eval 'dirs=( ~Documents )'
。
现在,我想象如果您所在的系统具有大型网络用户数据库而没有缓存(LDAP、NIS+...),那么扩展可能会很慢。zsh
会在其变量列表中查找,Documents
即使您有数百万个变量,因为 zsh 使用哈希表,该列表也应该很快,并调用getpwnam("Documents")
以检索用户的主目录Documents
,这在您的情况下可能是慢的部分。您可以通过尝试id Documents
哪个应该拨打相同的getpwnam()
电话来确认。
我个人会避开这个cdablevars
选项,因为它肯定有一天或另一天会给你带来不好的惊喜。如果没有它,您始终可以执行cd ~user
or cd ~var
,并且我发现当您确实想要cd
进入除作为参数给出的目录之外的其他内容时,明确请求它会更好。
cdablevars
1990 年的第一个版本中就已经出现了,zsh
受到tcsh
默认情况下这样做的启发。它早于~var
.cdablevars
在我看来,应该被视为历史文物。
至于如何解决缓慢的问题getpwnam()
,您可以考虑调整名称服务数据库。例如,如果使用sssd
,您可以增加设置来确定在再次查询后端之前entry_negative_timeout
缓存用户不存在的信息的时间。Documents
对于用户数据库查询来说,3 秒似乎过多,这表明您可能存在配置问题,或者提供程序服务器不可用,并且回退机制(如果有)未以最佳方式配置。