mirror of
https://github.com/dense-analysis/ale.git
synced 2026-02-16 23:14:27 +08:00
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.
This commit is contained in:
@@ -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), ''))
|
||||
|
||||
if !empty(l:data)
|
||||
let s:compile_commands_cache[l:key] = l:data
|
||||
let l:file_lookup = {}
|
||||
let l:dir_lookup = {}
|
||||
|
||||
return l:data
|
||||
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]
|
||||
|
||||
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: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
|
||||
|
||||
Reference in New Issue
Block a user