-
-
Save itchyny/39a827e060c0c51100d40295a72e2df8 to your computer and use it in GitHub Desktop.
Performance comparison of the standard matchparen plugin and vim-parenmatch (https://github.com/itchyny/vim-parenmatch)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FUNCTION <SNR>10_Highlight_Matching_Pair() | |
Called 10001 times | |
Total time: 5.638959 | |
Self time: 5.638959 | |
count total (s) self (s) | |
" Remove any previous match. | |
10001 0.104816 if exists('w:paren_hl_on') && w:paren_hl_on | |
535 0.004517 silent! call matchdelete(3) | |
535 0.002974 let w:paren_hl_on = 0 | |
535 0.001179 endif | |
" Avoid that we remove the popup menu. | |
" Return when there are no colors (looks like the cursor jumps). | |
10001 0.086326 if pumvisible() || (&t_Co < 8 && !has("gui_running")) | |
return | |
endif | |
" Get the character under the cursor and check if it's in 'matchpairs'. | |
10001 0.071594 let c_lnum = line('.') | |
10001 0.064923 let c_col = col('.') | |
10001 0.038000 let before = 0 | |
10001 0.069035 let text = getline(c_lnum) | |
10001 0.484219 let matches = matchlist(text, '\(.\)\=\%'.c_col.'c\(.\=\)') | |
10001 0.073237 if empty(matches) | |
let [c_before, c] = ['', ''] | |
else | |
10001 0.130081 let [c_before, c] = matches[1:2] | |
10001 0.024639 endif | |
10001 0.391124 let plist = split(&matchpairs, '.\zs[:,]') | |
10001 0.096964 let i = index(plist, c) | |
10001 0.041568 if i < 0 | |
" not found, in Insert mode try character before the cursor | |
9466 0.087415 if c_col > 1 && (mode() == 'i' || mode() == 'R') | |
let before = strlen(c_before) | |
let c = c_before | |
let i = index(plist, c) | |
endif | |
9466 0.030627 if i < 0 | |
" not found, nothing to do | |
9466 0.021123 return | |
endif | |
endif | |
" Figure out the arguments for searchpairpos(). | |
535 0.001734 if i % 2 == 0 | |
360 0.001613 let s_flags = 'nW' | |
360 0.003057 let c2 = plist[i + 1] | |
360 0.000865 else | |
175 0.000747 let s_flags = 'nbW' | |
175 0.000708 let c2 = c | |
175 0.001407 let c = plist[i - 1] | |
175 0.000409 endif | |
535 0.002118 if c == '[' | |
80 0.000271 let c = '\[' | |
80 0.000248 let c2 = '\]' | |
80 0.000135 endif | |
" Find the match. When it was just before the cursor move it there for a | |
" moment. | |
535 0.001602 if before > 0 | |
let has_getcurpos = exists("*getcurpos") | |
if has_getcurpos | |
" getcurpos() is more efficient but doesn't exist before 7.4.313. | |
let save_cursor = getcurpos() | |
else | |
let save_cursor = winsaveview() | |
endif | |
call cursor(c_lnum, c_col - before) | |
endif | |
" Build an expression that detects whether the current cursor position is in | |
" certain syntax types (string, comment, etc.), for use as searchpairpos()'s | |
" skip argument. | |
" We match "escape" for special items, such as lispEscapeSpecial. | |
535 0.006009 let s_skip = '!empty(filter(map(synstack(line("."), col(".")), ''synIDattr(v:val, "name")''), ' . '''v:val =~? "string\\|character\\|singlequote\\|escape\\|comment"''))' | |
" If executing the expression determines that the cursor is currently in | |
" one of the syntax types, then we want searchpairpos() to find the pair | |
" within those syntax types (i.e., not skip). Otherwise, the cursor is | |
" outside of the syntax types and s_skip should keep its value so we skip any | |
" matching pair inside the syntax types. | |
535 1.424980 execute 'if' s_skip '| let s_skip = 0 | endif' | |
" Limit the search to lines visible in the window. | |
535 0.005013 let stoplinebottom = line('w$') | |
535 0.004197 let stoplinetop = line('w0') | |
535 0.002231 if i % 2 == 0 | |
360 0.002224 let stopline = stoplinebottom | |
360 0.000744 else | |
175 0.000985 let stopline = stoplinetop | |
175 0.000332 endif | |
" Limit the search time to 300 msec to avoid a hang on very long lines. | |
" This fails when a timeout is not supported. | |
535 0.004249 if mode() == 'i' || mode() == 'R' | |
let timeout = exists("b:matchparen_insert_timeout") ? b:matchparen_insert_timeout : g:matchparen_insert_timeout | |
else | |
535 0.006122 let timeout = exists("b:matchparen_timeout") ? b:matchparen_timeout : g:matchparen_timeout | |
535 0.001175 endif | |
535 0.001233 try | |
535 1.590589 let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, timeout) | |
535 0.002791 catch /E118/ | |
" Can't use the timeout, restrict the stopline a bit more to avoid taking | |
" a long time on closed folds and long lines. | |
" The "viewable" variables give a range in which we can scroll while | |
" keeping the cursor at the same position. | |
" adjustedScrolloff accounts for very large numbers of scrolloff. | |
let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2]) | |
let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2]) | |
let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2]) | |
" one of these stoplines will be adjusted below, but the current values are | |
" minimal boundaries within the current window | |
if i % 2 == 0 | |
if has("byte_offset") && has("syntax_items") && &smc > 0 | |
let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2]) | |
let stopline = min([bottom_viewable, byte2line(stopbyte)]) | |
else | |
let stopline = min([bottom_viewable, c_lnum + 100]) | |
endif | |
let stoplinebottom = stopline | |
else | |
if has("byte_offset") && has("syntax_items") && &smc > 0 | |
let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2]) | |
let stopline = max([top_viewable, byte2line(stopbyte)]) | |
else | |
let stopline = max([top_viewable, c_lnum - 100]) | |
endif | |
let stoplinetop = stopline | |
endif | |
let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline) | |
endtry | |
535 0.001782 if before > 0 | |
if has_getcurpos | |
call setpos('.', save_cursor) | |
else | |
call winrestview(save_cursor) | |
endif | |
endif | |
" If a match is found setup match highlighting. | |
535 0.003712 if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom | |
535 0.004241 if exists('*matchaddpos') | |
535 0.025851 call matchaddpos('MatchParen', [[c_lnum, c_col - before], [m_lnum, m_col]], 10, 3) | |
535 0.001512 else | |
exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) . 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/' | |
endif | |
535 0.002639 let w:paren_hl_on = 1 | |
535 0.001001 endif | |
FUNCTION parenmatch#update() | |
Called 10000 times | |
Total time: 0.660151 | |
Self time: 0.660151 | |
count total (s) self (s) | |
10000 0.110140 let i = mode() ==# 'i' || mode() ==# 'R' | |
10000 0.149091 let c = getline('.')[col('.') - i - 1] | |
10000 0.151401 silent! call matchdelete(w:parenmatch) | |
10000 0.106627 if !has_key(s:paren, c) | return | endif | |
535 0.005828 let [open, closed, flags, stop] = s:paren[c] | |
535 0.006679 let q = [line('.'), col('.') - i] | |
535 0.006086 if i | let p = getcurpos() | call cursor(q) | endif | |
535 0.046504 let r = searchpairpos(open, '', closed, flags, '', line(stop), 10) | |
535 0.005393 if i | call setpos('.', p) | endif | |
535 0.037070 if r[0] > 0 | let w:parenmatch = matchaddpos('ParenMatch', [q, r]) | endif | |
FUNCTIONS SORTED ON TOTAL TIME | |
count total (s) self (s) function | |
10001 5.638959 <SNR>10_Highlight_Matching_Pair() | |
10000 0.660151 parenmatch#update() | |
FUNCTIONS SORTED ON SELF TIME | |
count total (s) self (s) function | |
10001 5.638959 <SNR>10_Highlight_Matching_Pair() | |
10000 0.660151 parenmatch#update() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment