Skip to content

Commit ebbc372

Browse files
authored
Merge pull request #2738 from tomlau10/perf
Perf: Improve performance of multithreaded `--check` and `undefined-field` diagnostic
2 parents 3886d2e + f58d0ba commit ebbc372

File tree

4 files changed

+43
-12
lines changed

4 files changed

+43
-12
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* `NEW` Add postfix snippet for `unpack`
66
* `FIX` `diagnostics.severity` defaulting to "Warning" when run using `--check` [#2730](https://github.com/LuaLS/lua-language-server/issues/2730)
77
* `NEW` Add support for lambda style functions, `|paramList| expr` is syntactic sugar for `function(paramList) return expr end`
8+
* `CHG` Improve performance of multithreaded `--check` and `undefined-field` diagnostic
89

910
## 3.9.3
1011
`2024-6-11`

script/cli/check_worker.lua

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,6 @@ local checkLevel = define.DiagnosticSeverity[CHECKLEVEL] or define.DiagnosticSev
4343

4444
util.enableCloseFunction()
4545

46-
-- Hash function used to distribute work.
47-
local function hashString(str)
48-
local hash = 0
49-
for i = 1, #str do
50-
hash = (hash * 37 & 0xFFFFFFFF) + str:byte(i, i)
51-
end
52-
return hash
53-
end
54-
5546
local lastClock = os.clock()
5647
local results = {}
5748

@@ -109,9 +100,9 @@ xpcall(lclient.start, errorhandler, lclient, function (client)
109100

110101
local uris = files.getChildFiles(rootUri)
111102
local max = #uris
103+
table.sort(uris) -- sort file list to ensure the work distribution order across multiple threads
112104
for i, uri in ipairs(uris) do
113-
local hash = hashString(uri) % numThreads + 1
114-
if hash == threadId then
105+
if (i % numThreads + 1) == threadId then
115106
files.open(uri)
116107
diag.doDiagnostic(uri, true)
117108
-- Print regularly but always print the last entry to ensure that logs written to files don't look incomplete.

script/core/diagnostics/undefined-field.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ return function (uri, callback)
2121
local function checkUndefinedField(src)
2222
await.delay()
2323

24-
if #vm.getDefs(src) > 0 then
24+
if vm.hasDef(src) then
2525
return
2626
end
2727
local node = src.node

script/vm/def.lua

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,42 @@ function vm.getDefs(source)
9292

9393
return results
9494
end
95+
96+
local HAS_DEF_ERR = {} -- the error object for comparing
97+
local function checkHasDef(checkFunc, source, pushResult)
98+
local _, err = pcall(checkFunc, source, pushResult)
99+
return err == HAS_DEF_ERR
100+
end
101+
102+
---@param source parser.object
103+
function vm.hasDef(source)
104+
local mark = {}
105+
local hasLocal
106+
local function pushResult(src)
107+
if src.type == 'local' then
108+
if hasLocal then
109+
return
110+
end
111+
hasLocal = true
112+
if source.type ~= 'local'
113+
and source.type ~= 'getlocal'
114+
and source.type ~= 'setlocal'
115+
and source.type ~= 'doc.cast.name' then
116+
return
117+
end
118+
end
119+
if not mark[src] then
120+
mark[src] = true
121+
if guide.isAssign(src)
122+
or guide.isLiteral(src) then
123+
-- break out on 1st result using error() with a unique error object
124+
error(HAS_DEF_ERR)
125+
end
126+
end
127+
end
128+
129+
return checkHasDef(searchBySimple, source, pushResult)
130+
or checkHasDef(searchByLocalID, source, pushResult)
131+
or checkHasDef(vm.compileByNodeChain, source, pushResult)
132+
or checkHasDef(searchByNode, source, pushResult)
133+
end

0 commit comments

Comments
 (0)