vim-ocaml icon indicating copy to clipboard operation
vim-ocaml copied to clipboard

lag in vim on saving .ml file

Open nilsbecker opened this issue 3 years ago • 4 comments

hi, recently i have noticed laggy behavior when editing a small to medium sized dune project in vim. i tried to debug it by using :profile start profile.log , profile func *. i then performed :w then i broke the last line in this function:

    let add_products config =
      let open Config in
      function
      | Empty  -> ()
      | Single m' -> add config m'
      | Pair (m',m'') -> (* inserted line break *)
        add config m'; add config m''

when i then :w again, i get a lag of a few seconds. my final profile.log has the following suspicious section:

FUNCTION  OMLetFoldLevel()
    Defined: ~/.vim/plugins/vim-ocaml/ftplugin/ocaml.vim:176
Called 23281 times
Total time:  17.862757
 Self time:   2.871963

count  total (s)   self (s)
                            
                              " This is for not merging blank lines around folds to them
23281              0.096067   if getline(a:l) !~ '\S'
  805              0.000996     return -1
22476              0.010256   endif
                            
                              " We start folds for modules, classes, and every toplevel definition
22476              0.242120   if getline(a:l) =~ '^\s*\%(\<val\>\|\<module\>\|\<class\>\|\<type\>\|\<method\>\|\<initializer\>\|\<inherit\>\|\<exception\>\|\<external\>\)'
  224              0.001100     exe 'return ">' (indent(a:l)/s:i)+1 '"'
22252              0.011305   endif
                            
                              " Toplevel let are detected thanks to the indentation
22252  15.161066   0.170272   if getline(a:l) =~ '^\s*let\>' && indent(a:l) == s:i+s:topindent(a:l)
 1238              0.007322     exe 'return ">' (indent(a:l)/s:i)+1 '"'
21014              0.010320   endif
                            
                              " We close fold on end which are associated to struct, sig or object.
                              " We use syntax information to do that.
21014              0.145205   if getline(a:l) =~ '^\s*end\>' && synIDattr(synID(a:l, indent(a:l)+1, 0), "name") != "ocamlKeyword"
   39              0.000091     return (indent(a:l)/s:i)+1
20975              0.009617   endif
                            
                              " Folds end on ;;
20975              0.078737   if getline(a:l) =~ '^\s*;;'
   16              0.000060     exe 'return "<' (indent(a:l)/s:i)+1 '"'
20959              0.009870   endif
                            
                              " Comments around folds aren't merged to them.
20959              1.727391   if synIDattr(synID(a:l, indent(a:l)+1, 0), "name") == "ocamlComment"
 4184              0.004404     return -1
16775              0.007958   endif
                            
16775              0.013879   return '='

i don't understand why function should be called that often? this is the function with the biggest time budget in the profile.

i am using ocp-indent and the ALE plugin, where i set

" use ale to fix trailing spaces in ocaml
let g:ale_fixers = {
			\ 'ocaml': ['trim_whitespace', 'remove_trailing_lines' ]
			\}

to trim whitespace.

nilsbecker avatar Mar 01 '21 14:03 nilsbecker

actually, the ALE fixer uses a lot of time:

FUNCTION  <SNR>151_RunFixer()
    Defined: ~/.vim/plugins/ale/autoload/ale/fix.vim:206
Called 9 times
Total time:  53.671523
 Self time:   0.000299

count  total (s)   self (s)
    9              0.000017     let l:buffer = a:options.buffer
    9              0.000012     let l:input = a:options.input
    9              0.000011     let l:index = a:options.callback_index
                            
    9              0.000019     if len(a:options.callback_list) <= l:index
    3  17.881809   0.000269         call ale#fix#ApplyFixes(l:buffer, l:input)
                            
    3              0.000003         return
    6              0.000003     endif
                            
    6              0.000021     let [l:fixer_name, l:Function] = a:options.callback_list[l:index]
                            
                                " Record new jobs started as fixer jobs.
    6              0.000024     call setbufvar(l:buffer, 'ale_job_type', 'fixer')
                            
                                " Regular fixer commands accept (buffer, [input])
    6   0.023597   0.001429     let l:result = ale#util#FunctionArgCount(l:Function) == 1   ? call(l:Function, [l:buffer])   : call(l:Function, [l:buffer, copy(l:input)])
                            
    6              0.000241     call s:RunJob(l:result, {   'buffer': l:buffer,   'input': l:input,   'callback_list': a:options.callback_list,   'callback_index': l:index,   'fixer_name': l:fixer_name,})

nilsbecker avatar Mar 01 '21 15:03 nilsbecker

and i have enabled the ALE fixer on save with au FileType ocaml let b:ale_fix_on_save=1 in the .vimrc. so it seems there is some interaction between the ocaml ftplugin, ALE removing trailing whitespace. possibly, also merlin or ocp-indent. does someone see a solution? is this an ALE problem?

nilsbecker avatar Mar 01 '21 15:03 nilsbecker

I don’t know ALE, but in my memories (in fact, in comments I left for myself in my .vimrc) the builtin folder for OCaml is “slow and totally broken” (obsolete maybe?). Maybe you’d better disable it altogether? Tell me if I’m wrong.

" disable the builtin OCaml folder (but by default it should already be disabled):
unlet g:ocaml_folding

Maelan avatar Mar 01 '21 18:03 Maelan

in my config, g:ocaml_folding was enabled, and i don't set it in .vimrc; it seems to be on by default. i'll try it out.

[edit]: no, that does not seem to have been the cause. i still get lag on saving after i either unlet g:ocaml_folding or let g:ocaml_folding=0.

nilsbecker avatar Mar 02 '21 10:03 nilsbecker