On 02/04/20 09:09AM, Christian Brabandt wrote:
> [I did not receive the original mail, so answering to Tonys mail, please 
> keep the list on CC]

Strange. I did keep the list in Cc ([email protected], but now I've also 
included [email protected]). I think my emails are being held up 
by something because I noticed that when I sent the first email it took 
a while (multiple hours) to show up in the Google groups archive. And 
now I see that my reply doesn't show up in the archive even though my 
mail client shows [email protected] in Cc.
 
> On Mi, 01 Apr 2020, Tony Mechelynck wrote:
> 
> > > Yes, the tags file is sorted and vim is built with +tag_binary and
> > > 'tagbsearch' is on. The tags file wasn't case-folded sorted, but I tried
> > > with that too and I see similar performance.
> > >
> > > Anyway, just to remove any potential confusion, jumping to tags via
> > > 'CTRL-]' is blazing fast. So is listing all alternatives with 'g]'. Does
> > > ccomplete use the same mechanism for searching tags file as those two?
> > > If so, then I wonder why it is so much slower.
> 
> Hm, I had a quick look at ccomplete.vim. It not only does a tag search, 
> but also searches the current file and more importantly, it might call 
> :vimgrep and :vimgrep is known to be slow if many files have to be 
> searched. Not sure if there is anything to improve, perhaps adding a 
> switch to only do tag completion would already help?
> 
> Anyhow, first please create a vimscript profile, so we can exactly see 
> when it is slow. See :h :profile and this stackoverflow answer: 
> https://stackoverflow.com/a/12216578/789222
> 
> Perhaps this can share some more light on the slowness.
 
The profile log is pretty big (~3500 lines) since I use multiple 
plugins. Trace of ccomplete#Complete and StructMembers() is pasted 
below. Let me know if you need any more info, like traces of other 
functions in the call chain.

The major time consumer looks like:

   21            130.867568       exe 'silent! keepj noautocmd ' . n . 'vimgrep 
/\t' . typename . '\(\t\|$\)/j ' . fnames

inside StructMembers().

FUNCTIONS SORTED ON TOTAL TIME
count  total (s)   self (s)  function
    2 130.920294   0.013774  ccomplete#Complete()
   21 130.873054             <SNR>77_StructMembers()
    2 124.341230   0.001711  <SNR>77_Nextitem()
  129   6.548978   0.004060  <SNR>77_Tagline2item()
  129   6.544918   0.002094  <SNR>77_GetAddition()
  128   6.542824   0.009213  <SNR>77_SearchMembers()
   14   0.024376   0.001583  airline#check_mode()
    2   0.022166   0.004144  airline#highlighter#highlight()
  128   0.016388   0.003802  <SNR>77_Tag2item()
   76   0.013935   0.003591  airline#highlighter#exec()
   14   0.011462   0.000464  airline#extensions#branch#get_head()
   14   0.010636   0.000383  airline#extensions#branch#head()
   14   0.010169   0.000242  airline#extensions#wordcount#get()
    6   0.009927   0.000111  <SNR>61_update_wordcount()
    6   0.009742             <SNR>61_get_wordcount()
  128   0.009439             <SNR>77_Dict2info()
  116   0.009389   0.004537  airline#highlighter#get_highlight()
   14   0.008767   0.000787  <SNR>57_update_branch()
   20   0.007623   0.000636  <SNR>55_exec_separator()
   14   0.007164   0.000748  <SNR>57_update_git_branch()

FUNCTIONS SORTED ON SELF TIME
count  total (s)   self (s)  function
   21            130.873054  <SNR>77_StructMembers()
    2 130.920294   0.013774  ccomplete#Complete()
    6              0.009742  <SNR>61_get_wordcount()
  128              0.009439  <SNR>77_Dict2info()
  128   6.542824   0.009213  <SNR>77_SearchMembers()
  116   0.009389   0.004537  airline#highlighter#get_highlight()
  232              0.004197  <SNR>55_get_syn()
    2   0.022166   0.004144  airline#highlighter#highlight()
  129   6.548978   0.004060  <SNR>77_Tagline2item()
  128   0.016388   0.003802  <SNR>77_Tag2item()
   76   0.013935   0.003591  airline#highlighter#exec()
  128              0.003147  <SNR>77_Tagcmd2extra()
   14   0.004693   0.003079  fugitive#Find()
   34              0.002095  <SNR>55_GetHiCmd()
  129   6.544918   0.002094  <SNR>77_GetAddition()
   14              0.001898  <SNR>75_generate_names()
    2 124.341230   0.001711  <SNR>77_Nextitem()
   76              0.001710  <SNR>55_CheckDefined()
   14   0.024376   0.001583  airline#check_mode()
   14   0.001486   0.001300  <SNR>57_update_untracked()

FUNCTION  ccomplete#Complete()
    Defined: /usr/share/vim/vim82/autoload/ccomplete.vim:10
Called 2 times
Total time: 130.920294
 Self time:   0.013774

count  total (s)   self (s)
    2              0.000004   if a:findstart
                                " Locate the start of the item, including ".", 
"->" and "[...]".
    1              0.000003     let line = getline('.')
    1              0.000003     let start = col('.') - 1
    1              0.000001     let lastword = -1
    4              0.000005     while start > 0
    4              0.000012       if line[start - 1] =~ '\w'
    3              0.000003     let start -= 1
    1              0.000002       elseif line[start - 1] =~ '\.'
                                if lastword == -1
                                  let lastword = start
                                endif
                                let start -= 1
    1              0.000002       elseif start > 1 && line[start - 2] == '-' && 
line[start - 1] == '>'
                                if lastword == -1
                                  let lastword = start
                                endif
                                let start -= 2
    1              0.000001       elseif line[start - 1] == ']'
                                " Skip over [...].
                                let n = 0
                                let start -= 1
                                while start > 0
                                  let start -= 1
                                  if line[start] == '['
                                    if n == 0
                                      break
                                    endif
                                    let n -= 1
                                  elseif line[start] == ']'  " nested []
                                    let n += 1
                                  endif
                                endwhile
    1              0.000000       else
    1              0.000001     break
    3              0.000001       endif
    4              0.000002     endwhile
                            
                                " Return the column of the last word, which is 
going to be changed.
                                " Remember the text that comes before it in 
s:prepended.
    1              0.000001     if lastword == -1
    1              0.000002       let s:prepended = ''
    1              0.000001       return start
                                endif
                                let s:prepended = strpart(line, start, lastword 
- start)
                                return lastword
    1              0.000001   endif
                            
                              " Return list of matches.
                            
    1              0.000002   let base = s:prepended . a:base
                            
                              " Don't do anything for an empty base, would 
result in all the tags in the
                              " tags file.
    1              0.000001   if base == ''
                                return []
    1              0.000000   endif
                            
                              " init cache for vimgrep to empty
    1              0.000001   let s:grepCache = {}
                            
                              " Split item in words, keep empty word after "." 
or "->".
                              " "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> 
['aa', 'bb'], etc.
                              " We can't use split, because we need to skip 
nested [...].
                              " "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> 
['aa', 'bb', '[...]'], etc.
    1              0.000001   let items = []
    1              0.000001   let s = 0
    1              0.000001   let arrays = 0
    1              0.000001   while 1
    1              0.000005     let e = match(base, '\.\|->\|\[', s)
    1              0.000001     if e < 0
    1              0.000002       if s == 0 || base[s - 1] != ']'
    1              0.000003     call add(items, strpart(base, s))
    1              0.000000       endif
    1              0.000001       break
                                endif
                                if s == 0 || base[s - 1] != ']'
                                  call add(items, strpart(base, s, e - s))
                                endif
                                if base[e] == '.'
                                  let s = e + 1 " skip over '.'
                                elseif base[e] == '-'
                                  let s = e + 2 " skip over '->'
                                else
                                  " Skip over [...].
                                  let n = 0
                                  let s = e
                                  let e += 1
                                  while e < len(base)
                                if base[e] == ']'
                                  if n == 0
                                    break
                                  endif
                                  let n -= 1
                                elseif base[e] == '['  " nested [...]
                                  let n += 1
                                endif
                                let e += 1
                                  endwhile
                                  let e += 1
                                  call add(items, strpart(base, s, e - s))
                                  let arrays += 1
                                  let s = e
                                endif
    1              0.000001   endwhile
                            
                              " Find the variable items[0].
                              " 1. in current function (like with "gd")
                              " 2. in tags file(s) (like with ":tag")
                              " 3. in current file (like with "gD")
    1              0.000001   let res = []
    1              0.000027   if searchdecl(items[0], 0, 1) == 0
                                " Found, now figure out the type.
                                " TODO: join previous line if it makes sense
    1              0.000002     let line = getline('.')
    1              0.000002     let col = col('.')
    1              0.000003     if stridx(strpart(line, 0, col), ';') != -1
                                  " Handle multiple declarations on the same 
line.
                                  let col2 = col - 1
                                  while line[col2] != ';'
                                let col2 -= 1
                                  endwhile
                                  let line = strpart(line, col2 + 1)
                                  let col -= col2
    1              0.000000     endif
    1              0.000003     if stridx(strpart(line, 0, col), ',') != -1
                                  " Handle multiple declarations on the same 
line in a function
                                  " declaration.
                                  let col2 = col - 1
                                  while line[col2] != ','
                                let col2 -= 1
                                  endwhile
                                  if strpart(line, col2 + 1, col - col2 - 1) =~ 
' *[^ ][^ ]*  *[^ ]'
                                let line = strpart(line, col2 + 1)
                                let col -= col2
                                  endif
    1              0.000001     endif
    1              0.000001     if len(items) == 1
                                  " Completing one word and it's a local 
variable: May add '[', '.' or
                                  " '->'.
    1              0.000001       let match = items[0]
    1              0.000001       let kind = 'v'
    1              0.000005       if match(line, '\<' . match . '\s*\[') > 0
                                let match .= '['
    1              0.000001       else
    1 124.341163   0.000009     let res = s:Nextitem(strpart(line, 0, col), 
[''], 0, 1)
    1              0.000001     if len(res) > 0
                                  " There are members, thus add "." or "->".
    1              0.001138       if match(line, '\*[ \t(]*' . match . '\>') > 0
    1              0.000003         let match .= '->'
                                  else
                                    let match .= '.'
    1              0.000000       endif
    1              0.000000     endif
    1              0.000001       endif
    1              0.000011       let res = [{'match': match, 'tagline' : '', 
'kind' : kind, 'info' : line}]
                                elseif len(items) == arrays + 1
                                  " Completing one word and it's a local array 
variable: build tagline
                                  " from declaration line
                                  let match = items[0]
                                  let kind = 'v'
                                  let tagline = "\t/^" . line . '$/'
                                  let res = [{'match': match, 'tagline' : 
tagline, 'kind' : kind, 'info' : line}]
                                else
                                  " Completing "var.", "var.something", etc.
                                  let res = s:Nextitem(strpart(line, 0, col), 
items[1:], 0, 1)
    1              0.000000     endif
    1              0.000001   endif
                            
    1              0.000002   if len(items) == 1 || len(items) == arrays + 1
                                " Only one part, no "." or "->": complete from 
tags file.
    1              0.000001     if len(items) == 1
    1              0.002090       let tags = taglist('^' . base)
                                else
                                  let tags = taglist('^' . items[0] . '$')
    1              0.000001     endif
                            
                                " Remove members, these can't appear without 
something in front.
    1              0.000605     call filter(tags, 'has_key(v:val, "kind") ? 
v:val["kind"] != "m" : 1')
                            
                                " Remove static matches in other files.
    1              0.008299     call filter(tags, '!has_key(v:val, "static") || 
!v:val["static"] || bufnr("%") == bufnr(v:val["filename"])')
                            
    1   0.017006   0.000618     call extend(res, map(tags, 's:Tag2item(v:val)'))
    1              0.000000   endif
                            
    1              0.000001   if len(res) == 0
                                " Find the variable in the tags file(s)
                                let diclist = taglist('^' . items[0] . '$')
                            
                                " Remove members, these can't appear without 
something in front.
                                call filter(diclist, 'has_key(v:val, "kind") ? 
v:val["kind"] != "m" : 1')
                            
                                let res = []
                                for i in range(len(diclist))
                                  " New ctags has the "typeref" field.  Patched 
version has "typename".
                                  if has_key(diclist[i], 'typename')
                                call extend(res, 
s:StructMembers(diclist[i]['typename'], items[1:], 1))
                                  elseif has_key(diclist[i], 'typeref')
                                call extend(res, 
s:StructMembers(diclist[i]['typeref'], items[1:], 1))
                                  endif
                            
                                  " For a variable use the command, which must 
be a search pattern that
                                  " shows the declaration of the variable.
                                  if diclist[i]['kind'] == 'v'
                                let line = diclist[i]['cmd']
                                if line[0] == '/' && line[1] == '^'
                                  let col = match(line, '\<' . items[0] . '\>')
                                  call extend(res, s:Nextitem(strpart(line, 2, 
col - 2), items[1:], 0, 1))
                                endif
                                  endif
                                endfor
    1              0.000000   endif
                            
    1              0.000002   if len(res) == 0 && searchdecl(items[0], 1) == 0
                                " Found, now figure out the type.
                                " TODO: join previous line if it makes sense
                                let line = getline('.')
                                let col = col('.')
                                let res = s:Nextitem(strpart(line, 0, col), 
items[1:], 0, 1)
    1              0.000000   endif
                            
                              " If the last item(s) are [...] they need to be 
added to the matches.
    1              0.000002   let last = len(items) - 1
    1              0.000001   let brackets = ''
    1              0.000001   while last >= 0
    1              0.000003     if items[last][0] != '['
    1              0.000001       break
                                endif
                                let brackets = items[last] . brackets
                                let last -= 1
    1              0.000001   endwhile
                            
    1   6.549648   0.000670   return map(res, 's:Tagline2item(v:val, brackets)')

FUNCTION  <SNR>77_StructMembers()
    Defined: /usr/share/vim/vim82/autoload/ccomplete.vim:496
Called 21 times
Total time: 130.873054
 Self time: 130.873054

count  total (s)   self (s)
                              " Todo: What about local structures?
   21              0.002335   let fnames = join(map(tagfiles(), 'escape(v:val, 
" \\#%")'))
   21              0.000034   if fnames == ''
                                return []
   21              0.000007   endif
                            
   21              0.000030   let typename = a:typename
   21              0.000021   let qflist = []
   21              0.000021   let cached = 0
   21              0.000022   if a:all == 0
    1              0.000001     let n = '1'     " stop at first found match
    1              0.000002     if has_key(s:grepCache, a:typename)
                                  let qflist = s:grepCache[a:typename]
                                  let cached = 1
    1              0.000000     endif
   20              0.000010   else
   20              0.000019     let n = ''
   21              0.000010   endif
   21              0.000020   if !cached
   21              0.000019     while 1
   21            130.867568       exe 'silent! keepj noautocmd ' . n . 'vimgrep 
/\t' . typename . '\(\t\|$\)/j ' . fnames
                            
   21              0.000335       let qflist = getqflist()
   21              0.000279       if len(qflist) > 0 || match(typename, "::") < 0
   21              0.000043     break
                                  endif
                                  " No match for "struct:context::name", remove 
"context::" and try again.
                                  let typename = substitute(typename, 
':[^:]*::', ':', '')
   21              0.000029     endwhile
                            
   21              0.000040     if a:all == 0
                                  " Store the result to be able to use it again 
later.
    1              0.000003       let s:grepCache[a:typename] = qflist
   21              0.000014     endif
   21              0.000031   endif
                            
                              " Skip over [...] items
   21              0.000035   let idx = 0
   21              0.000019   while 1
   21              0.000053     if idx >= len(a:items)
                                  let target = ''               " No further 
items, matching all members
                                  break
   21              0.000010     endif
   21              0.000083     if a:items[idx][0] != '['
   21              0.000039       let target = a:items[idx]
   21              0.000006       break
                                endif
                                let idx += 1
   21              0.000034   endwhile
                              " Put matching members in matches[].
   21              0.000026   let matches = []
   45              0.000051   for l in qflist
   24              0.000103     let memb = matchstr(l['text'], '[^\t]*')
   24              0.000042     if memb =~ '^' . target
                                  " Skip matches local to another file.
   24              0.000097       if match(l['text'], "\tfile:") < 0 || 
bufnr('%') == bufnr(matchstr(l['text'], '\t\zs[^\t]*'))
   24              0.000048     let item = {'match': memb, 'tagline': l['text']}
                            
                                " Add the kind of item.
   24              0.000127     let s = matchstr(l['text'], 
'\t\(kind:\)\=\zs\S\ze\(\t\|$\)')
   24              0.000021     if s != ''
   24              0.000026       let item['kind'] = s
   24              0.000018       if s == 'f'
                                    let item['match'] = memb . '('
   24              0.000012       endif
   24              0.000007     endif
                            
   24              0.000036     call add(matches, item)
   24              0.000009       endif
   24              0.000007     endif
   45              0.000035   endfor
                            
   21              0.000039   if len(matches) > 0
                                " Skip over next [...] items
    1              0.000002     let idx += 1
    1              0.000000     while 1
    1              0.000002       if idx >= len(a:items)
    1              0.000003     return matches          " No further items, 
return the result.
                                  endif
                                  if a:items[idx][0] != '['
                                break
                                  endif
                                  let idx += 1
                                endwhile
                            
                                " More items following.  For each of the 
possible members find the
                                " matching following members.
                                return s:SearchMembers(matches, a:items[idx :], 
a:all)
   20              0.000011   endif
                            
                              " Failed to find anything.
   20              0.000018   return []

-- 
Regards,
Pratyush Yadav

-- 
-- 
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_use/20200402090645.wmiurwe4remde6za%40yadavpratyush.com.

Reply via email to