Skip to content

Commit

Permalink
Optimize hashrocket alignment for speed
Browse files Browse the repository at this point in the history
The way the function is currently written, it is processing the same
lines over and over again, which can make things very slow if we're
processing an entire file that is big.

In order to optimize what the function is doing, I made
puppet#align#AlignHashrockets report back what line indexes it has
worked on and then we accumulate the line indexes already seen so that
we can skip over them when we encounter those lines again in our loop.

As an example of a slow-to-process file, I've found that in
https://github.com/puppetlabs/puppetlabs-apache the file
manifests/vhosts.pp, which is 2967 lines long was particularly slow to
process with the current code.

If I open that file with nvim/vim, then go to the first line and
reformat the whole file (gggqG), it takes the plugin:

nvim 0.9.5: elapsed time:   48.235387
vim 9.1: elapsed time:   76.116376

With the optimization in place, the plugin takes:

nvim 0.9.5: elapsed time:    0.101734
vim 9.1: elapsed time:    0.12892

so about two orders of magnitude faster.

The above timings were taken with a CPU 12th Gen Intel(R) Core(TM)
i5-1240P and 32 Gb of RAM, so your measurements may vary a bit.
  • Loading branch information
lelutin committed Sep 14, 2024
1 parent 78375fb commit c59aa99
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
6 changes: 4 additions & 2 deletions autoload/puppet/align.vim
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ function! puppet#align#LinesInBlock(lnum) abort
let marker = a:lnum - 1
while marker >= 1
let line_text = getline(marker)
let line_indent = puppet#align#IndentLevel(marker)

if line_text =~? '\v\S'
let line_indent = puppet#align#IndentLevel(marker)
if line_indent < indent_level
break
elseif line_indent == indent_level
Expand All @@ -25,9 +25,9 @@ function! puppet#align#LinesInBlock(lnum) abort
let marker = a:lnum
while marker <= line('$')
let line_text = getline(marker)
let line_indent = puppet#align#IndentLevel(marker)

if line_text =~? '\v\S'
let line_indent = puppet#align#IndentLevel(marker)
if line_indent < indent_level
break
elseif line_indent == indent_level
Expand Down Expand Up @@ -77,4 +77,6 @@ function! puppet#align#AlignHashrockets(...) abort
call setline(line_num, new_line)
endif
endfor

return lines_in_block
endfunction
14 changes: 11 additions & 3 deletions autoload/puppet/format.vim
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,20 @@ endfunction
" Format hashrockets expressions in every line in range start_lnum and
" end_lnum, both ends included
"
" TODO way of using AlignHashrockets function is ineffective, because it
" formats same lines again and again, find better way to do it
function! puppet#format#Hashrocket(start_lnum, end_lnum) abort
let l:lnum = a:start_lnum
let processed_lines = []
while l:lnum <= a:end_lnum
call puppet#align#AlignHashrockets(l:lnum)
if index(processed_lines, l:lnum) ==# -1
let line_text = getline(l:lnum)
if line_text =~? '\v\S'
let processed_lines += puppet#align#AlignHashrockets(l:lnum)
else
" empty lines make puppet#align#AlignHashrockets reprocess blocks with
" indentation that were already processed so we just skip them
call add(processed_lines, l:lnum)
endif
endif
let l:lnum += 1
endwhile
endfunction
Expand Down

0 comments on commit c59aa99

Please sign in to comment.