一次分析vim启动慢原因的经历
三个月之前,参加了牛客网和华为云的活动,实际仅花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
打开。
参考资料: