ultisnips icon indicating copy to clipboard operation
ultisnips copied to clipboard

Insert mode lags

Open habamax opened this issue 4 years ago • 15 comments

In insert mode I can see quite a lag especially when I do enter Russian letters.

Expected behavior: Should be no lag

Actual behavior: Lag

ultisnips-issue1

Steps to reproduce

Well, not sure. I just had it installed for quite a long time

Settings that I had regarding ultisnips

	let g:UltiSnipsExpandTrigger = '<tab>'
	let g:UltiSnipsJumpForwardTrigger = '<tab>'
	let g:UltiSnipsJumpBackwardTrigger = '<s-tab>'
	let g:UltiSnipsListSnippets = '<c-tab>'

My snippets were:

https://github.com/habamax/.vim/tree/03dce7b57131e993b5ccdc88775196c2f5fe7ef6/UltiSnips

If I remove Ultisnips (use vsnips instead): ultisnips-issue3

PS

If I remove au! Ultisnips_AutoTrigger it becomes way faster. But only for english. Russian lags the same.

ultisnips-issue2


  • Operating System: Win10
  • Vim Version: 8.2.114
  • UltiSnips Version: current master
  • Python inside Vim: 3.8.1

habamax avatar Jan 13 '20 16:01 habamax

Steps to reproduce

Well, not sure.

Without a MWE there's no way to know what causes your issue. Bisect your config until you find one, then post it here.

Here's what a MWE could look like:

" in `/tmp/vimrc`
let g:UltiSnipsSnippetDirectories = ['/tmp/snippets']
let g:UltiSnipsExpandTrigger = '<tab>'
set rtp-=$HOME/.vim
set rtp^=$HOME/.vim/plugged/ultisnips
set rtp+=$HOME/.vim/plugged/ultisnips/after
set rtp^=$HOME/.vim
filetype plugin on

# in `/tmp/snippets/vim.snippets`
snippet trigger
my snippet has been expanded
endsnippet

" start Vim like this:
$ vim -Nu /tmp/vimrc /tmp/vim.vim

" type those keys: ....

See also reproducing-bugs.


Just a guess, but in your gifs, the text contains fold markers; folding can introduce lag. Check whether you can reproduce after temporarily setting 'foldmethod' to manual (:setl fdm=manual), or try vim-fastfold.

lacygoill avatar Jan 13 '20 20:01 lacygoill

Also, try to get a profile:

:prof start /tmp/profile.log
:prof! file /path/to/ultisnips/**/*.vim
:ru! /path/to/ultisnips/**/*.vim
" reproduce the issue, then quit Vim; the profile should be written in `/tmp/profile.log`

See :h profile.

lacygoill avatar Jan 13 '20 20:01 lacygoill

Just a guess, but in your gifs, the text contains fold markers; folding can introduce lag. Check whether you can reproduce after temporarily setting 'foldmethod' to manual (:setl fdm=manual), or try vim-fastfold.

That is not the case:

  1. without ultisnips it doesn't lag with the same file, same folding settings
  2. it lags the same on a new file without folding at all (set fdm=manual)

habamax avatar Jan 14 '20 06:01 habamax

Ok, then you'll have to bisect your config to find a minimal reproducible example.

lacygoill avatar Jan 14 '20 12:01 lacygoill

Ok, then you'll have to bisect your config to find a minimal reproducible example.

Busy at work, will try to do it when I have time. Thx.

habamax avatar Jan 14 '20 13:01 habamax

Well, I've spent last 1.5 hour bisecting my config, removing/reinstalling plugins and couldn't find the exact thing that makes ultisnips slow.

without any plugins installed next lines in my vimrc makes ultisnips slower (not THAT slow as in my previous gifs but I can see it):

func! SetDefaultFiletype()
	if @% == "" && &filetype == ""
		setfiletype txt
	endif
endfunc
augroup default_filetype
	autocmd!
	autocmd BufEnter * call SetDefaultFiletype()
augroup END

When I start adding other plugins one by one, ultisnips become slightly more laggy with each plugin I install until the result u see in gifs. I couldn't find single plugin that adds all the laggines fo far.

I think you can close the issue and reopen it when there will be other reports on it (I will continue using vsnip for now as I don't have time at the moment to investigate root cause)

Thank you!

habamax avatar Jan 14 '20 18:01 habamax

This is very unfortunate behavior and I am deeply sorry that it bothered your editing experience. Windows support is traditionally the poorest in UltiSnips. The reason is that I do not have access to a Windows machine and have in fact not worked on any Windows machine for ten years or so.

traditionally, the Python <-> Vim bridge in Windows was not very performant. My hunch (without any data) is that string conversions (Vim uses UTF8, while Windows traditionally uses Unicode 16 or so, which I think python on Windows also uses internally) are expensive and that could be the reason you see slow downs. However, I do not have the means to investigate this.

I'll leave this open for a while to see if somebody else jumps on it and can add additional data.

@habamax Thanks for investing so much time and energy into this bug report!

SirVer avatar Jan 18 '20 20:01 SirVer

Just wanted to say I have experienced this on both Linux and Windows.

jperrett256 avatar Feb 12 '22 00:02 jperrett256

Just wanted to say I have experienced this on both Linux and Windows.

Indeed, i'm using ubuntu and I do have similar issue.

ws051682 avatar Aug 10 '22 12:08 ws051682

I can confirm that I have the same issue on GVIM on Windows (but not on GVIM on KDE Linux, though). The lag is specially noticeable when editing text files (perhaps because I type prose much faster than code?) and creating a new snippet file for texts with :UltiSnipsEdit seems to alleviate the lag a little (any snippet will do, just need to create the file).

mnemster avatar May 25 '23 17:05 mnemster

Same issue for GVim+win10

skywind3000 avatar Aug 13 '23 19:08 skywind3000

I thought I found something, and figure out how to reproduce this on Linux.

I am experiencing serious insert mode lag too:

One thing I noticed is that: when I was using a minimal vimrc (with only one plugin, ultisnips installed), the lag was small, but still noticable. Then I started to add other plugins and found: the more plugin I had, the more input lag I got .

Is it related to the number of runtimepath ? What if I only add some empty runtimepaths without adding any other actual plugin? To prove this, I made a minimal vimrc to add 300 empty runtimepaths:

set nocompatible

set ttimeout
set ttimeoutlen=50
set display=lastline
set encoding=utf-8
set fileencoding=utf-8
set fileencodings=ucs-bom,utf-8,gbk,gb18030,big5,euc-jp,latin1
set showcmd

syntax enable
syntax on

filetype plugin indent on

set rtp+=c:/users/Linwei/.vim/bundles/ultisnips

let BASE = 'd:/temp/ultisnips'

for i in range(300)
	let tmpname = printf("%s/rtp-%d", BASE, i)
	exec 'set rtp+=' . fnameescape(tmpname)
	call mkdir(tmpname, 'p')
endfor

setlocal ft=cpp

The lag became intolerable with this minimal vimrc:

And I've recorded a profile log for this:

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
  106  26.851451             UltiSnips#TrackChange()
   91   0.015417   0.014351  <SNR>23_Highlight_Matching_Pair()
   91   0.000902             <SNR>23_Remove_Matches()

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
  106             26.851451  UltiSnips#TrackChange()
   91   0.015417   0.014351  <SNR>23_Highlight_Matching_Pair()
   91              0.000902  <SNR>23_Remove_Matches()

see the most expensive function is UltiSnips#TrackChange(), it costs 253ms millisecs each call:

https://github.com/SirVer/ultisnips/blob/24a3ebb36687b6d59a19d63173713575b486d739/autoload/UltiSnips.vim#L176-L178

This function is listening on InsertCharPre, TextChangedI, and TextChangedP:

https://github.com/SirVer/ultisnips/blob/24a3ebb36687b6d59a19d63173713575b486d739/plugin/UltiSnips.vim#L37-L44

This function will be called several times when I press a single letter, what does it do ?

Will it scan all the runtimepaths ? Can it be removed ? or only add to InsertLeave ?

I have 95+ plugins installed, which is normal nowadays, Windows I/O is slower than Linux, so this function made me unable to edit.

@SirVer , I believe you can reproduce it too on Linux by just adding 300, or more, empty runtimepaths.

skywind3000 avatar Sep 05 '23 08:09 skywind3000

@skywind3000 Thanks for investing time into this issue, I highly appreciate it.

TrackChanges is doing a diff between the buffer as it was before the last cursor move and after the current cursor move. This is needed to understand how the buffer change to update tabstops, mirrors and therelike. It is a potentially very expensive function if the buffer has changed tremendously (e.g. if you paste a lot of text while a snippet is active), however it is surprising to me that it would depend on the runtime path.

It also calls try_expand which will try to expand autotrigger snippets on cursor move. This function will once load the snippets for the current file type - this will indeed traverse all runtimepaths - but then only ever reload them when a .snippets file is saved in the current vim session. I just verified this with some quick debug printf that this indeed works as intended (on my system).

I think a bit more digging is required on your end - I cannot reproduce lag in simple buffers even with 300 entries in my runtimepath. Edit: to clarify: If I add 1000 directories to my rtp, i notice a clear lack upon expanding the first time the cursor moves, but not thereafter.

SirVer avatar Sep 05 '23 18:09 SirVer

I doubt this depends on the amount of paths in the rtp. But rather on the latency of the underlying filesystem. When using neovim inside a linux VM to edit files on a virtiofs mount, the delay while typing makes it barely usable. (With my snippets and plugins are also on this virtiofs mount). The only current workaround is to delete the augroup UltiSnips_AutoTrigger as described here back in 2018. But even outside a VM, the difference is perceivable without this augroup when you pay attention.

AlxHnr avatar Sep 27 '23 22:09 AlxHnr

I do not get where this would come from though - UltiSnips does not access the filesystem unless reloading snippets, which only happens on the first expand or after a .snippet file was edited inside Vim.

SirVer avatar Oct 14 '23 11:10 SirVer

appreciated

skywind3000 avatar Mar 16 '24 20:03 skywind3000