summaryrefslogtreecommitdiff
path: root/autoload
diff options
context:
space:
mode:
authorJacob Segal <jacob.e.segal@gmail.com>2018-12-16 20:47:35 -0800
committerJacob Segal <jacob.e.segal@gmail.com>2019-01-06 00:41:57 -0800
commitcb0a5c7a36122a053c6c86cab145aa4c0336f5ba (patch)
treefc61bb533d5f629e611fad30bb26d8806f2333cc /autoload
parent5bbe77101db18968fde65210956e54750d7ff4f5 (diff)
downloadale-cb0a5c7a36122a053c6c86cab145aa4c0336f5ba.zip
Improve perf for compile dbs in large projects
When using a compilation database (compile_commands.json) in very large projects, significant delays would occur when changing files -- particularly those that happened to be far down the db. Rather than iterating over the whole list every time, we now build up a lookup table based on the tail of the filename (and tail of the directory for widening searches) and iterate over the much smaller list of compile commands for files with the given name. Test metrics (from compile_database_perf/test.sh) show a 90% performance improvement -- from 25 seconds to 2.5 seconds per run.
Diffstat (limited to 'autoload')
-rw-r--r--autoload/ale/c.vim50
1 files changed, 36 insertions, 14 deletions
diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim
index 617e81f6..746d19b0 100644
--- a/autoload/ale/c.vim
+++ b/autoload/ale/c.vim
@@ -157,15 +157,17 @@ if !exists('s:compile_commands_cache')
let s:compile_commands_cache = {}
endif
-function! s:GetListFromCompileCommandsFile(compile_commands_file) abort
+function! s:GetLookupFromCompileCommandsFile(compile_commands_file) abort
+ let l:empty = [{}, {}]
+
if empty(a:compile_commands_file)
- return []
+ return l:empty
endif
let l:time = getftime(a:compile_commands_file)
if l:time < 0
- return []
+ return l:empty
endif
let l:key = a:compile_commands_file . ':' . l:time
@@ -174,21 +176,36 @@ function! s:GetListFromCompileCommandsFile(compile_commands_file) abort
return s:compile_commands_cache[l:key]
endif
- let l:data = []
- silent! let l:data = json_decode(join(readfile(a:compile_commands_file), ''))
+ let l:raw_data = []
+ silent! let l:raw_data = json_decode(join(readfile(a:compile_commands_file), ''))
+
+ let l:file_lookup = {}
+ let l:dir_lookup = {}
+
+ for l:entry in l:raw_data
+ let l:basename = tolower(fnamemodify(l:entry.file, ':t'))
+ let l:file_lookup[l:basename] = get(l:file_lookup, l:basename, []) + [l:entry]
- if !empty(l:data)
- let s:compile_commands_cache[l:key] = l:data
+ let l:dirbasename = tolower(fnamemodify(l:entry.directory, ':p:h:t'))
+ let l:dir_lookup[l:dirbasename] = get(l:dir_lookup, l:basename, []) + [l:entry]
+ endfor
+
+ if !empty(l:file_lookup) && !empty(l:dir_lookup)
+ let l:result = [l:file_lookup, l:dir_lookup]
+ let s:compile_commands_cache[l:key] = l:result
- return l:data
+ return l:result
endif
- return []
+ return l:empty
endfunction
-function! ale#c#ParseCompileCommandsFlags(buffer, dir, json_list) abort
+function! ale#c#ParseCompileCommandsFlags(buffer, dir, file_lookup, dir_lookup) abort
" Search for an exact file match first.
- for l:item in a:json_list
+ let l:basename = tolower(expand('#' . a:buffer . ':t'))
+ let l:file_list = get(a:file_lookup, l:basename, [])
+
+ for l:item in l:file_list
if bufnr(l:item.file) is a:buffer
return ale#c#ParseCFlags(a:dir, l:item.command)
endif
@@ -197,7 +214,10 @@ function! ale#c#ParseCompileCommandsFlags(buffer, dir, json_list) abort
" Look for any file in the same directory if we can't find an exact match.
let l:dir = ale#path#Simplify(expand('#' . a:buffer . ':p:h'))
- for l:item in a:json_list
+ let l:dirbasename = tolower(expand('#' . a:buffer . ':p:h:t'))
+ let l:dir_list = get(a:dir_lookup, l:dirbasename, [])
+
+ for l:item in l:dir_list
if ale#path#Simplify(fnamemodify(l:item.file, ':h')) is? l:dir
return ale#c#ParseCFlags(a:dir, l:item.command)
endif
@@ -208,9 +228,11 @@ endfunction
function! ale#c#FlagsFromCompileCommands(buffer, compile_commands_file) abort
let l:dir = ale#path#Dirname(a:compile_commands_file)
- let l:json_list = s:GetListFromCompileCommandsFile(a:compile_commands_file)
+ let l:lookups = s:GetLookupFromCompileCommandsFile(a:compile_commands_file)
+ let l:file_lookup = l:lookups[0]
+ let l:dir_lookup = l:lookups[1]
- return ale#c#ParseCompileCommandsFlags(a:buffer, l:dir, l:json_list)
+ return ale#c#ParseCompileCommandsFlags(a:buffer, l:dir, l:file_lookup, l:dir_lookup)
endfunction
function! ale#c#GetCFlags(buffer, output) abort