Skip to content

Instantly share code, notes, and snippets.

@appgurueu
Created November 15, 2023 18:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save appgurueu/f566cafa9482b0fc74eb6050417e3ed5 to your computer and use it in GitHub Desktop.
Save appgurueu/f566cafa9482b0fc74eb6050417e3ed5 to your computer and use it in GitHub Desktop.
Spreading expensive operations out over multiple server steps using coroutines
local jobs = {}
minetest.register_globalstep(function(dtime)
local remaining_jobs = {}
local time_per_job = dtime / #jobs
for _, job in ipairs(jobs) do
local time_s = minetest.get_us_time() / 1e6
repeat
assert(coroutine.resume(job))
local dtime_s = minetest.get_us_time() / 1e6 - time_s
until dtime_s > time_per_job or coroutine.status(job) == "dead"
if coroutine.status(job) == "suspended" then
table.insert(remaining_jobs, job)
else
assert(coroutine.status(job) == "dead")
end
end
jobs = remaining_jobs
end)
minetest.register_chatcommand("approximate_pi", {
func = function()
local function job()
-- Approximate pi (very inefficiently)
local hits = 0
local m = 1e5
local k = 1000
local n = m * k
for _ = 1, m do
-- Do many iterations in a row to reduce overhead from yielding
for _ = 1, k do
local x, y = math.random(), math.random()
if x^2 + y^2 < 1 then
hits = hits + 1
end
end
coroutine.yield() -- give control back to scheduler
end
local pi = 4 * hits / n
minetest.chat_send_all("pi = " .. pi)
end
table.insert(jobs, coroutine.create(job))
end,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment