语法高亮在Vim中引起了可怕的延迟

68

我喜欢 Vim。但现在它让我感到很困难。

我使用了很多插件,在过去的6个月里,我发现了很多很棒的插件。但是我的Vim也变得非常缓慢。我经常进行清理,但效果不大。

现在我的Vim已经完全无法使用了。感觉渲染速度每秒只有2-5帧,切换标签/缓冲区需要约1秒钟,使用 hjkl 滚动非常可怕,延迟太严重了,即使在插入模式下输入一句话也会因为延迟而感到混乱。

编辑:实际上,当我打开一个新的Vim实例时,它还可以,但15分钟后就变得无法使用了。

我刚刚花了4个小时试图找出哪个插件或配置引起了问题。但我没有成功。

然而,我发现删除以下设置会消除所有的延迟:

syntax on

这三行与语法结构一起使用会使一切变得更糟。

set t_Co=256
set background=dark
colorscheme candyman

有趣。所以,语法高亮会使Vim从超级敏捷变得非常缓慢?

我尝试在"clean"模式下启用语法: vim -u NONE

那里就没有问题了。

看起来问题是语法高亮与我的一个或多个插件组合使用的结果。我尝试禁用了一堆插件,但没有成功。

是否有任何方法进行分析?我已经非常疲惫了,因为要手动测试。

是否有人有类似的经历?也许可以快速查看一下我的 .vimrc文件,看看是否能找出问题。 https://bitbucket.org/furion/dotfiles

解决方案: 导致混乱的插件是:

Bundle "gorodinskiy/vim-coloresque.git"

我建议阅读答案,它们提供了很好的见解。

编辑(1个月后): coloresque插件已经得到了一些改进。


根据您最新的编辑,我猜测某些东西正在泄漏。您是否看到vim的内存占用(即使是轻微但持续地)增长?这可能是插件或甚至vim保留了一些不断增长的映射表,可能是因为插件有缺陷,或者您已将Vim中的某些设置设置为非常大的值(猜测,例如撤消历史记录)。 - Shahbaz
我真的不知道。这么做似乎会导致泄漏,是吗?最好还是等这个人来回答你! - Shahbaz
抱歉给您带来不便。最新版本已经修复了延迟问题(我自己也在使用我的插件)。请尝试使用最新版本。再次道歉。 - Konstantin
它确实看起来更快... - if __name__ is None
@KonstantinGorodinskiy 看起来好了很多,但是在颜色处理的行上,滞后仍然非常严重,在其他行上则不太明显。 - if __name__ is None
显示剩余6条评论
12个回答

101

编辑:关于如何使用这些方法的博客,包括截图和详细说明。

https://eduncan911.com/software/fix-slow-scrolling-in-vim-and-neovim.html

以下是原始答案...


:syntime on

在你的 Ruby 文件中移动,然后

:syntime report 

以下是我遇到的最慢匹配情况,您可以看到甚至没有1个匹配。

我在ruby.vim文件中禁用了rubyPredefinedConstant,问题得到解决。Vim正则表达式引擎不喜欢ruby语法高亮正则表达式中的某些内容。您需要在足够的语法高亮和良好性能之间寻找平衡。

这里是我在Mac OS 10.8.5上报告的ruby语法高亮正则表达式前3个最慢的匹配,homebrew Vim 7.4(控制台vim)。

  TOTAL      COUNT  MATCH   SLOWEST     AVERAGE   NAME               PATTERN
  3.498505   12494  0       0.008359    0.000280  rubyPredefinedConstant \%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(STDERR\|STDIN\|STDOUT\|TOPLEVEL_BINDING\|TRUE\)\>\%(\s*(\)\@!
  2.948513   12494  0       0.006798    0.000236  rubyPredefinedConstant \%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(MatchingData\|ARGF\|ARGV\|ENV\)\>\%(\s*(\)\@!
  2.438253   12494  0       0.005346    0.000195  rubyPredefinedConstant \%(\%(\.\@<!\.\)\@<!\|::\)\_s*\zs\%(DATA\|FALSE\|NIL\)\>\%(\s*(\)\@!

或者你可以尝试Dojosto提到的vim-ruby


2
+1。救命的答案。好吧,不是_救命的。但我有一个100行的.rb文件,它的加载速度就像100百万行一样慢,禁用rubyPrefinedConstant解决了问题。谢谢@AskandLearn! - Joe Kennedy
7
你如何禁用 Vim 中类似 rubyPredefinedConstant 这样的功能? - rudolph9
2
这确实有所改善,而且 syntime 命令在未来的性能问题中肯定会派上用场。但对我来说真正的解决方案是安装 vim-ruby - Doug Johnston
1
那是一个很棒的工具,非常不错! - Josh Bodah
1
同样的问题也出现在ruby预定义常量中... vim-ruby解决了它! - pragmatic_programmer
显示剩余3条评论

31

您的autocmd命令存在垃圾邮件。您应该将所有的autocmd语句放在清除组中,然后再重新添加它们。看起来,您的.vimrc文件中大多数autocmd语句都被注释掉了,所以可能是某个插件引起了问题。请检查以下命令的输出:

:au CursorMoved

如果有许多重复的处理程序,那就是你的问题。

这是我在我的 .vimrc中自动命令的一个示例:

augroup vimrc_autocmd
  autocmd!
  "toggle quickfix window
  autocmd BufReadPost quickfix map <buffer> <leader>qq :cclose<cr>|map <buffer> <c-p> <up>|map <buffer> <c-n> <down>

  autocmd FileType unite call s:unite_settings()
  " obliterate unite buffers (marks especially).
  autocmd BufLeave \[unite\]* if "nofile" ==# &buftype | setlocal bufhidden=wipe | endif

  " Jump to the last position when reopening a file
  autocmd BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif

  " ...etc...

augroup END

augroup 块的开头,autocmd! 清除当前组(在本例中为 vimrc_autocmd),然后重新添加 autocmd。


:au CursorMoved中有3个自动命令,全部来自插件。我会重新调整我的.vimrc以遵循您的规范。 - if __name__ is None
2
... 或者不要重新加载你的 .vimrc 文件,只需执行 :q 并重新启动即可。 - Ingo Karkat
@JanNetherdrake,3个自动命令还好,但其中可能有一个表现不佳。您至少可以通过此命令清除“CursorMoved”自动命令::au!CursorMoved,以查看是否解决了问题。这样可以帮助您缩小问题范围。 - Justin M. Keyes
实际上,:au!CursorMoved 只会删除非分组 autocmds,似乎。所以你还必须单独删除每个组,例如 :au!matchparen - Justin M. Keyes
好的,那么现在我应该做的就是扫描我的 vimrc 文件,并将自动命令分组到以 au! 开头的 augroups 中,对吗?我还会删除那些我不需要的自动命令。 - if __name__ is None
当然,这是一个好的做法。但是为了发现您最初问题的根源,您应该逐个删除“CursorMoved”组,以查看哪个插件(如果有)是问题的原因。 - Justin M. Keyes

29

另一个stack overflow的问题中,我了解到通过在.vimrc文件中添加以下行:
set re=1
可以使vim更快,它会强制vim使用旧版本的正则表达式引擎,并且对于Ruby实际上更快。


这对我也真的起作用了!调试这个很困难(我不知道是语法高亮,注释掉vimrc的部分才到达这一点)。这一行解决了它!我重新添加了相对行号。学到了很多,谢谢! - Daryll Santos
顺便说一句:我刚刚发现我的vimrc中的“set re=1”是语法高亮缓慢的原因!所以这可能不是现代vim的好建议。 - llimllib

15
我发现 "set foldmethod=syntax" 会使得 7.4 版本在处理js和ruby文件时变得非常慢(使用Ubuntu 13.10), 然而 "set foldmethod=indent" 却可以良好地工作。

2
FastFold插件使得折叠只在保存时重新计算。请参见https://dev59.com/h07Sa4cB1Zd3GeqP0Azn#26812154。 - idbrii
我有一个相当大的 .vimrc 文件,很高兴发现这个解决方案立即适用于我。感谢! - Chris Walsh
这应该是被接受的答案。在.vimrc文件中,我有一个stray set foldmethod=syntax,距离set foldmethod=indent几行之远。 - Kaz
这个问题会让那些没有使用奇怪插件的用户遇到麻烦,他们只是用语法高亮编辑一个大的C文件。它不会影响导航,但插入文本非常缓慢。现在我知道原因了:Vim正在重新计算文件的所有11,000行可折叠级别! - Kaz

15

我注意到如果你使用任何动态更改背景颜色的功能,vim可能会变得非常缓慢。尝试关闭:set cursorline:set cursorcolumn(如果你已经设置了它们)。


8
我想感谢所有帮助我解决这个问题的人。好消息是,我的Vim又变得非常流畅了。
我从头开始重新安装了Vim,并逐个添加插件,直到找到了罪魁祸首。
Bundle "gorodinskiy/vim-coloresque.git"

这是一个插件带来的问题。由于我使用了它一段时间,所以没有怀疑到它,这也是我发现它很晚的原因。

这个插件的功能是,每当它发现一个颜色单词(例如red, green)或十六进制值(例如#FFFFFF),它会将文本的背景颜色设置为描述颜色的颜色。这是个好主意,但实现似乎不太好。

删除此插件解决了延迟的问题。

但我并没有停止在这里。我还对我的 .vimrc 文件进行了大量清理。删除了一些未使用的插件,分组我的 autocmd 并删除不必要的内容。

现在我的 Vim 反应非常迅速。我又开心了。


1
我之前从未听说过那个插件,但我一直在寻找类似的东西。最终我找到了 https://github.com/chrisbra/color_highlight,这可能是更好的实现方式(Christian Brabandt已经提交了补丁到Vim本身,所以我认为他知道如何编写一个行为良好的插件)。 - Justin M. Keyes
1
我情不自禁地查看了源代码(https://github.com/gorodinskiy/vim-coloresque/blob/master/after/syntax/css/vim-coloresque.vim),插件确实添加了一个昂贵的“CursorMoved”自动命令,并且它没有防止重复注册。 - Justin M. Keyes
谢谢你的一切! - if __name__ is None
@JustinM.Keyes 另一个让我困扰的 CursorMoved au 是 https://github.com/bling/vim-airline/blob/master/autoload/airline/extensions.vim 你对这个有什么看法? - if __name__ is None
航空公司的设计非常精良。我没有遇到任何问题。你还在遇到速度慢的问题吗? - Justin M. Keyes

5

语法高亮可能会变慢,但这应该仅限于某些(有些病态的)文件和特定的语法。最新的Vim 7.4有一个新命令:syntime来解决语法高亮速度慢的问题。

除此之外,通常情况下,进行二分查找可以帮助您快速找到有问题的脚本。您可以先禁用一半的插件,然后只保留其中的一半(当问题仍然存在时),或者另一半(当问题消失时)。


4
我有这个问题已经很长时间了,让我感到疯狂。我尝试安装vim-ruby。不确定是否有帮助,但至少现在我有最新版本的ruby语法高亮(与上一个Vim版本相比有任何性能改进)。
但是我继续查看,发现vim-ruby有一个跳过所有昂贵高亮的模式。尝试将此行添加到您的vimrc中,看看是否有所帮助(对我有用,终于!): let ruby_no_expensive=1

4
我很确定
set t_Co=256
set background=dark
colorscheme candyman

与延迟无关。前两行无用(可用颜色数量根据您的$TERM定义,您的配色方案已经执行了set background=dark),但并不真正有害。

常见的“Vim运行缓慢”原因包括编写不良的autocmd、太多的autocmd、过于频繁地重新加载~/.vimrc、编写不良的插件等。

请发布您的设置,以便我们帮助您找出为什么会出现这种延迟。


我已经发布了我的设置,如果你错过了它,它在帖子的底部。 - if __name__ is None
抱歉。我认为您有太多的自动命令。尝试将它们注释掉,看看问题是否仍然存在。 - romainl

1
对我来说,导致速度变慢的原因是set relativenumber功能。尝试使用set norelativenumber禁用它并进行测试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接