Syntax highlighting causes terrible lag in Vim

Solution 1:

EDIT: Blogged about how this all works, with screenshots and awesome-sauce.

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

Original answer below...


:syntime on

move around in your ruby file and then

:syntime report

It reported the following slowest matching for me, and you can see that there are not even 1 match.

I disabled rubyPredefinedConstant in ruby.vim file and problem solved. Vim regex engine does not like something in ruby syntax highlight regex. You will have to find the balance between enough syntax highligting and a good performance.

hope that helps, here is the top 3 slowest syntax highlighting regex for ruby reported on my Mac OS 10.8.5, homebrew Vim 7.4 (console 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*(\)\@!

Or you can try vim-ruby as pointed out by Dojosto

Solution 2:

You have autocmd spam. You should wrap all of your autocmd statements in groups which clear the group before re-adding the autocmds. It looks like your .vimrc has most autocmds commented-out, so maybe there is a plugin that is causing the issue. Check the output of this command:

:au CursorMoved

If there's a bunch of duplicate handlers there, that's your problem.

Here's an example of autocmd discipline from my .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

The autocmd! at the beginning of the augroup block clears out the current group (vimrc_autocmd, in this case) before re-adding the autocmds.

Solution 3:

From another stack overflow question, I get vim fast by adding the following line in .vimrc file:
set re=1
This will force vim to use a older version of regex engine and it is actually FASTER for ruby.

Solution 4:

I found that "set foldmethod=syntax" makes 7.4 almost unusable slow e.g. for js&ruby files (ubuntu 13.10) whereas "set foldmethod=indent" works fine.

Solution 5:

I've noticed that vim can slow down to a halt if you're using anything that dynamically changes the background color. Try turning off :set cursorline or :set cursorcolumn (if you have them set).