Smarter algorithm to patch files list

New algorithm use the fact that files list are always
sorted to optimize the table's insertions and removals.
This commit is contained in:
Francesco Abbate 2021-07-25 00:14:21 +02:00
parent 8f36b776b7
commit 6c5abdd95d
1 changed files with 28 additions and 17 deletions

View File

@ -244,11 +244,16 @@ function core.scan_project_subdir(dirname, filename)
end end
end end
-- for "a" inclusive from i1 + 1 and i2
local function files_list_match(a, i1, i2, b) local function files_info_equal(a, b)
if i2 - i1 ~= #b then return false end return a.filename == b.filename and a.type == b.type
for i = 1, #b do end
if a[i1 + i].filename ~= b[i].filename or a[i1 + i].type ~= b[i].type then
-- for "a" inclusive from i1 + 1 and i1 + n
local function files_list_match(a, i1, n, b)
if n ~= #b then return false end
for i = 1, n do
if not files_info_equal(a[i1 + i], b[i]) then
return false return false
end end
end end
@ -256,16 +261,22 @@ local function files_list_match(a, i1, i2, b)
end end
-- arguments like for files_list_match -- arguments like for files_list_match
local function files_list_replace(a, i1, i2, b) local function files_list_replace(as, i1, n, bs)
local nmin = math.min(i2 - i1, #b) local m = #bs
for i = 1, nmin do local i, j = 1, 1
a[i1 + i] = b[i] while i <= m or i <= n do
end local a, b = as[i1 + i], bs[j]
for j = 1, i2 - i1 - nmin do if i > n or (j <= m and not files_info_equal(a, b) and
table.remove(a, i1 + nmin + 1) not system.path_compare(a.filename, a.type, b.filename, b.type))
end then
for j = 1, #b - nmin do table.insert(as, i1 + i, b)
table.insert(a, i1 + nmin + j, b[nmin + j]) i, j, n = i + 1, j + 1, n + 1
elseif j > m or system.path_compare(a.filename, a.type, b.filename, b.type) then
table.remove(as, i1 + i)
n = n - 1
else
i, j = i + 1, j + 1
end
end end
end end
@ -289,8 +300,8 @@ local function rescan_project_subdir(dir, filename_rooted)
end end
end end
if not files_list_match(dir.files, index, index + n, new_files) then if not files_list_match(dir.files, index, n, new_files) then
files_list_replace(dir.files, index, index + n, new_files) files_list_replace(dir.files, index, n, new_files)
dir.is_dirty = true dir.is_dirty = true
return true return true
end end