Skip to content

Commit

Permalink
perf: prevent active waiting in coroutines. suspend/resume instead
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Jun 27, 2024
1 parent 79bcc02 commit 68cee30
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
28 changes: 27 additions & 1 deletion lua/lazy/async.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ local M = {}
M._queue = {}
M._executor = assert(vim.loop.new_check())
M._running = false
M.SLEEP = "sleep"
---@type Async
M.current = nil

---@class Async
---@field co thread
---@field opts AsyncOpts
---@field sleeping? boolean
local Async = {}

---@param fn async fun()
Expand All @@ -29,16 +33,38 @@ function Async:running()
return coroutine.status(self.co) ~= "dead"
end

function Async:sleep(ms)
self.sleeping = true
vim.defer_fn(function()
self.sleeping = false
end, ms)
end

function Async:suspend()
self.sleeping = true
end

function Async:resume()
self.sleeping = false
end

function Async:step()
if self.sleeping then
return true
end
local status = coroutine.status(self.co)
if status == "suspended" then
M.current = self
local ok, res = coroutine.resume(self.co)
M.current = nil
if not ok then
if self.opts.on_error then
self.opts.on_error(tostring(res))
end
elseif res then
if self.opts.on_yield then
if res == M.SLEEP then
self.sleeping = true
elseif self.opts.on_yield then
self.opts.on_yield(res)
end
end
Expand Down
8 changes: 5 additions & 3 deletions lua/lazy/manage/task/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ function Task:spawn(cmd, opts)
end
end

self._running:suspend()

local running = true
local ret = true
---@param output string
Expand All @@ -234,6 +236,7 @@ function Task:spawn(cmd, opts)
end
ret = ok
running = false
self._running:resume()
end

if headless then
Expand All @@ -244,9 +247,8 @@ function Task:spawn(cmd, opts)
end
end
Process.spawn(cmd, opts)
while running do
coroutine.yield()
end
coroutine.yield()
assert(not running, "process still running?")
return ret
end

Expand Down
10 changes: 3 additions & 7 deletions lua/lazy/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,9 @@ end
---@async
---@param ms number
function M.sleep(ms)
local continue = false
vim.defer_fn(function()
continue = true
end, ms)
while not continue do
coroutine.yield()
end
local async = require("lazy.async").current
assert(async, "Not in an async context")
async:sleep(ms)
end

function M._dump(value, result)
Expand Down

0 comments on commit 68cee30

Please sign in to comment.