三个月之前,参加了牛客网和华为云的活动,实际仅花9.9元就获得了一年云服务器的使用权,此处点赞牛客网。买来肯定是要干点事情的吧,虽然花的钱不多,这其中,肯定免不了跟各种文件编辑打交道。而我作为一个vim党,配置服务器时首先要做的事情当中,自然包括安装、配置vim了。

然而,遇到一个很困惑的问题:这个服务器上的vim,启动速度太慢了。和在其他服务器、虚拟机里使用的体验完全不一样,可以明显感受到速度慢。趁着今天放假,忍无可忍,把它给解决了。

如何测量vim的启动时间?

这是摆在眼前的第一个问题,需要有数据,才好去分析。幸好,vim提供了一个参数——--startuptime,用于记录某次打开过程,各个参数、插件加载所花费的时间。以一个例子阐述下:

vim --startuptime tmp.txt ~/.vimrc

上面这条命令,会将vim打开~/.vimrc文件的启动时间(从在bash中按下回车键,到vim启动界面出现)所耗费的时间过程保存在tmp.txt文件中。


times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.003  000.003: --- VIM STARTING ---
000.095  000.092: Allocated generic buffers
000.160  000.065: locale set
000.169  000.009: GUI prepared
000.173  000.004: clipboard setup
000.175  000.002: window checked
000.598  000.423: inits 1
000.656  000.058: parsing arguments
000.657  000.001: expanding arguments
000.663  000.006: shell init
000.935  000.272: Termcap init
000.964  000.029: inits 2
001.096  000.132: init highlight
002.137  000.791  000.791: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
002.238  000.940  000.149: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/synload.vim
008.792  006.523  006.523: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
008.842  007.603  000.140: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syntax.vim
009.200  000.165  000.165: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
009.546  000.155  000.155: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
009.926  000.171  000.171: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
010.171  000.153  000.153: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
010.639  001.405  000.926: sourcing /home/ljh/.vim/colors/molokai.vim
012.270  001.607  001.607: sourcing /home/ljh/.vim/autoload/plug.vim
013.153  000.469  000.469: sourcing /home/ljh/.user/local/share/vim/vim81/ftoff.vim
019.308  005.606  005.606: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
019.390  000.038  000.038: sourcing /home/ljh/.user/local/share/vim/vim81/ftplugin.vim
019.456  000.030  000.030: sourcing /home/ljh/.user/local/share/vim/vim81/indent.vim
027.356  026.149  009.226: sourcing $HOME/.vimrc
027.362  000.117: sourcing vimrc file(s)
028.105  000.179  000.179: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree.vim
030.324  000.599  000.599: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/path.vim
030.526  000.169  000.169: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim
030.627  000.075  000.075: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim
030.751  000.099  000.099: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim
030.997  000.222  000.222: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim
031.227  000.201  000.201: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim
031.680  000.426  000.426: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_dir_node.vim
031.901  000.195  000.195: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/opener.vim
032.155  000.228  000.228: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/creator.vim
032.221  000.040  000.040: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim
032.377  000.130  000.130: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim
033.510  001.108  001.108: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/ui.vim
033.567  000.020  000.020: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/event.vim
033.628  000.034  000.034: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim
034.109  000.450  000.450: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim
038.206  001.715  001.715: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim
038.876  000.649  000.649: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim
038.928  000.038  000.038: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim
038.995  011.492  004.915: sourcing /home/ljh/.vim/plugged/nerdtree/plugin/NERD_tree.vim
039.287  000.069  000.069: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/getscriptPlugin.vim
039.645  000.347  000.347: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/gzip.vim
039.905  000.250  000.250: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/logiPat.vim
039.945  000.029  000.029: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/manpager.vim
040.164  000.187  000.187: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/matchparen.vim
041.772  001.595  001.595: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/netrwPlugin.vim
041.858  000.042  000.042: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/rrhelper.vim
041.904  000.029  000.029: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/spellfile.vim
042.155  000.237  000.237: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tarPlugin.vim
042.282  000.107  000.107: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tohtml.vim
042.482  000.185  000.185: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/vimballPlugin.vim
042.675  000.166  000.166: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/zipPlugin.vim
042.679  000.582: loading plugins
042.743  000.064: loading packages
042.766  000.023: loading after plugins
042.800  000.034: inits 3
043.013  000.213: reading viminfo
3410.082  3367.069: setup clipboard
3410.095  000.013: setting raw mode
3755.185  345.090: waiting for return
3755.191  000.006: start termcap
3755.214  000.023: clearing screen
3757.400  000.617  000.617: sourcing /home/ljh/.user/local/share/vim/vim81/scripts.vim
3764.045  001.058  001.058: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/lua.vim
3764.693  000.413  000.413: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/pod.vim
3767.382  003.187  002.774: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/perl.vim
3770.574  003.042  003.042: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/ruby.vim
3771.459  000.725  000.725: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/python.vim
3772.588  014.926  006.914: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/vim.vim
3773.056  000.267  000.267: sourcing /home/ljh/.user/local/share/vim/vim81/ftplugin/vim.vim
3773.501  000.104  000.104: sourcing /home/ljh/.user/local/share/vim/vim81/indent/vim.vim
3773.599  002.471: opening buffers
3773.645  000.046: BufEnter autocommands
3773.647  000.002: editing files in windows
3774.170  000.523: VimEnter autocommands
3774.173  000.003: before starting main loop
3783.250  009.077: first screen update
3783.252  000.002: --- VIM STARTED ---

其中,数字第一列表示从每一项的时间戳,第二列表示该项花的具体时间,它们的单位都是毫秒(ms)。因而我们关注第二项,使用sort命令对第二列按数值,从小到大进行排序:

sort -nrk 2 tmp.txt

发现前两项太“瞩目”了:

3410.082  3367.069: setup clipboard
3755.185  345.090: waiting for return

两项加起来快4秒了,难怪会觉得那么卡!

接下来该怎么办?自然是问问神奇的咕歌同学了。
stackoverflow上,找到了答案。
首先,通过下列命令看是否是这个原因:

vim -X --startuptime tmp-1.txt ~/.vimrc

如果加了启动参数-X后,没有了上面两项或者上面两项耗费的时间少,那就说明是下面的这个原因了。
原来,vim在启动时会去连接X Server以便它能使用剪切板(clipboard)和窗口标题。这种情况的发生需要满足三个条件:

  • 通过终端模拟器使用vim
  • vim编译时加了+X11选项,开启了该特性
  • vim与X Server之间的连接慢

前面两个好理解,我是在Windows 10上,使用MobaXterm登录服务器的,并且由于一些需要,vim是编译安装并开启了这个特性。那第三个是为什么?我是通过ssh直接连接,并没有使用X Server呀?好叭,原来是因为MobaXterm启用了X11 Forward功能。

该怎么解决?
只需要在配置文件~/.vimrc中加入下面一行:

set clipboard=exclude:.*

即可在保留X11 Forward功能的同时,加快vim启动速度。

再看下打开~/.vimrc的时间,这些就快多了:


times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.007  000.007: --- VIM STARTING ---
000.126  000.119: Allocated generic buffers
000.237  000.111: locale set
000.249  000.012: GUI prepared
000.254  000.005: clipboard setup
000.258  000.004: window checked
000.816  000.558: inits 1
000.844  000.028: parsing arguments
000.846  000.002: expanding arguments
000.857  000.011: shell init
001.216  000.359: Termcap init
001.263  000.047: inits 2
001.468  000.205: init highlight
003.296  001.453  001.453: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
003.466  001.694  000.241: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/synload.vim
013.426  009.907  009.907: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
013.476  011.791  000.190: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syntax.vim
014.026  000.273  000.273: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
014.598  000.263  000.263: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
015.205  000.265  000.265: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
015.609  000.262  000.262: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
016.401  002.319  001.529: sourcing /home/ljh/.vim/colors/molokai.vim
019.033  002.588  002.588: sourcing /home/ljh/.vim/autoload/plug.vim
020.297  000.782  000.782: sourcing /home/ljh/.user/local/share/vim/vim81/ftoff.vim
030.537  009.447  009.447: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
030.657  000.060  000.060: sourcing /home/ljh/.user/local/share/vim/vim81/ftplugin.vim
030.758  000.052  000.052: sourcing /home/ljh/.user/local/share/vim/vim81/indent.vim
030.899  029.255  001.943: sourcing $HOME/.vimrc
030.903  000.180: sourcing vimrc file(s)
032.031  000.301  000.301: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree.vim
034.186  000.962  000.962: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/path.vim
034.500  000.271  000.271: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim
034.665  000.127  000.127: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim
034.874  000.174  000.174: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim
035.265  000.356  000.356: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim
035.648  000.344  000.344: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim
036.427  000.738  000.738: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_dir_node.vim
036.778  000.312  000.312: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/opener.vim
037.205  000.384  000.384: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/creator.vim
037.319  000.075  000.075: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim
037.577  000.221  000.221: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim
038.112  000.499  000.499: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/ui.vim
038.181  000.029  000.029: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/event.vim
038.273  000.057  000.057: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim
039.042  000.725  000.725: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim
043.500  000.146  000.146: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim
044.638  001.116  001.116: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim
044.720  000.058  000.058: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim
044.813  013.732  006.837: sourcing /home/ljh/.vim/plugged/nerdtree/plugin/NERD_tree.vim
045.295  000.116  000.116: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/getscriptPlugin.vim
045.733  000.419  000.419: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/gzip.vim
046.166  000.411  000.411: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/logiPat.vim
046.236  000.047  000.047: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/manpager.vim
046.587  000.308  000.308: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/matchparen.vim
047.552  000.944  000.944: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/netrwPlugin.vim
047.657  000.063  000.063: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/rrhelper.vim
047.729  000.042  000.042: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/spellfile.vim
048.061  000.308  000.308: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tarPlugin.vim
048.313  000.213  000.213: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tohtml.vim
048.674  000.332  000.332: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/vimballPlugin.vim
049.100  000.375  000.375: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/zipPlugin.vim
049.108  000.895: loading plugins
049.198  000.090: loading packages
049.234  000.036: loading after plugins
049.246  000.012: inits 3
049.674  000.428: reading viminfo
049.676  000.002: setup clipboard
049.684  000.008: setting raw mode
049.816  000.132: start termcap
049.920  000.104: clearing screen
050.442  000.522: opening buffers
050.514  000.072: BufEnter autocommands
050.516  000.002: editing files in windows
050.941  000.425: VimEnter autocommands
050.944  000.003: before starting main loop
051.854  000.910: first screen update
051.856  000.002: --- VIM STARTED ---


times in msec
 clock   self+sourced   self:  sourced script
 clock   elapsed:              other lines

000.003  000.003: --- VIM STARTING ---
000.098  000.095: Allocated generic buffers
000.160  000.062: locale set
000.167  000.007: GUI prepared
000.171  000.004: clipboard setup
000.174  000.003: window checked
000.559  000.385: inits 1
000.583  000.024: parsing arguments
000.584  000.001: expanding arguments
000.593  000.009: shell init
000.885  000.292: Termcap init
000.915  000.030: inits 2
001.059  000.144: init highlight
002.225  000.908  000.908: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
002.338  001.069  000.161: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/synload.vim
009.835  007.462  007.462: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
009.910  008.703  000.172: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syntax.vim
010.333  000.214  000.214: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
010.688  000.157  000.157: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
011.054  000.165  000.165: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
011.306  000.166  000.166: sourcing /home/ljh/.user/local/share/vim/vim81/syntax/syncolor.vim
011.769  001.398  000.910: sourcing /home/ljh/.vim/colors/molokai.vim
013.446  001.652  001.652: sourcing /home/ljh/.vim/autoload/plug.vim
014.340  000.596  000.596: sourcing /home/ljh/.user/local/share/vim/vim81/ftoff.vim
020.692  005.846  005.846: sourcing /home/ljh/.user/local/share/vim/vim81/filetype.vim
020.772  000.038  000.038: sourcing /home/ljh/.user/local/share/vim/vim81/ftplugin.vim
020.834  000.031  000.031: sourcing /home/ljh/.user/local/share/vim/vim81/indent.vim
020.917  019.745  001.267: sourcing $HOME/.vimrc
020.920  000.116: sourcing vimrc file(s)
021.734  000.188  000.188: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree.vim
023.135  000.605  000.605: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/path.vim
023.337  000.174  000.174: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_controller.vim
023.437  000.076  000.076: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/menu_item.vim
023.554  000.097  000.097: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/key_map.vim
023.787  000.212  000.212: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/bookmark.vim
024.024  000.213  000.213: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_file_node.vim
024.483  000.434  000.434: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/tree_dir_node.vim
024.693  000.186  000.186: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/opener.vim
024.938  000.222  000.222: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/creator.vim
025.012  000.051  000.051: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/flag_set.vim
025.168  000.134  000.134: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/nerdtree.vim
025.503  000.303  000.303: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/ui.vim
025.543  000.016  000.016: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/event.vim
025.597  000.033  000.033: sourcing /home/ljh/.vim/plugged/nerdtree/lib/nerdtree/notifier.vim
026.086  000.461  000.461: sourcing /home/ljh/.vim/plugged/nerdtree/autoload/nerdtree/ui_glue.vim
028.669  000.090  000.090: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/exec_menuitem.vim
029.367  000.684  000.684: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/fs_menu.vim
029.421  000.038  000.038: sourcing /home/ljh/.vim/plugged/nerdtree/nerdtree_plugin/vcs.vim
029.487  008.436  004.219: sourcing /home/ljh/.vim/plugged/nerdtree/plugin/NERD_tree.vim
029.776  000.070  000.070: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/getscriptPlugin.vim
030.159  000.372  000.372: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/gzip.vim
030.502  000.324  000.324: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/logiPat.vim
030.576  000.049  000.049: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/manpager.vim
030.804  000.195  000.195: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/matchparen.vim
031.460  000.643  000.643: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/netrwPlugin.vim
031.530  000.040  000.040: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/rrhelper.vim
031.573  000.026  000.026: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/spellfile.vim
031.758  000.171  000.171: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tarPlugin.vim
031.887  000.104  000.104: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/tohtml.vim
032.099  000.197  000.197: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/vimballPlugin.vim
032.312  000.183  000.183: sourcing /home/ljh/.user/local/share/vim/vim81/plugin/zipPlugin.vim
032.317  000.587: loading plugins
032.379  000.062: loading packages
032.402  000.023: loading after plugins
032.410  000.008: inits 3
032.669  000.259: reading viminfo
032.670  000.001: setup clipboard
032.676  000.006: setting raw mode
032.782  000.106: start termcap
032.847  000.065: clearing screen
033.262  000.415: opening buffers
033.317  000.055: BufEnter autocommands
033.321  000.004: editing files in windows
033.657  000.336: VimEnter autocommands
033.659  000.002: before starting main loop
034.352  000.693: first screen update
034.355  000.003: --- VIM STARTED ---

不到40毫秒就打开了文件。

抛开今天这个问题,还可能有那些原因?

  • 插件加载慢————可以考虑延迟加载
  • .viminfo————这个也会影响?
  • .vimrc————可能配置文件里还有一些项没有配置好

如果想跟进一步优化vim的启动速度,可以阅读vim内置的一份文档,可以通过命令:

:help slow-start

打开。

参考资料:

  1. vim-takes-a-very-long-time-to-start-up