使用 vim-plug 执行 PlugClean 的时候,CPU 都会飙升,而且执行需要 >10s,尝试解决。
TL;DR:vim 自带的列举文件函数 globpath
效率远低于命令 find
又低于 fd
,替换即可。
https://github.com/oldkingOK/vim-plug/commit/dcd710d99c53b75bd9b0f01eaa9ce71ed3117d8e
找了半天,才发现 vim 自带了一个 profile 的命令,用于测量脚本执行的时间。
:profile start vim_profile.log
:profile func *
" profile 所有的 func
然后开始执行需要 profile 的命令,这里是 :PlugClean
:profile stop
查看 ~/.vim/autoload/plug.vim
,PlugClean
会执行 s:clean
函数。在结果中搜索即可
可以看到,两个耗时最长的函数均为 s:glob_dir
。在最下面也有耗时排名:
猜测 self
就是本身消耗的时间,total
就是包括调用其他函数的时间。这里耗时最长的 4_glob
:
FUNCTION <SNR>4_glob()
Defined: ~/.vim/autoload/plug.vim:265
Called 16 times
Total time: 11.927213987
Self time: 11.458387360
count total (s) self (s)
16 11.927171176 11.458344549 return s:lines(globpath(a:from, a:pattern))
查阅之后,globpath 就是遍历文件,例如 globpath('.', '*')
就是遍历当前文件夹下的所有文件,如果是 **
,那就是递归遍历。所以这里的问题是,层数太多了,在查找 YouCompleteMe
的时候,因为 YCM 会把所有的依赖都放进自己的插件文件夹,比如 Go Binaries,clangd 所需要的头文件等等,就会爆炸。
这里尝试使用 find 来限制层数。即 system('find '.a:from.' -maxdepth 10 -name "'.a:pattern.'"')
,不出所料,时间大幅降低!
偶然发现,就算是不限制层数,find
也比 globpath
快。这里追求更快,使用 Rust 写的 fd
,即最终的方案。