Coroutines are awesome
Posted: Thu Mar 22, 2012 4:03 am
Because of the thread over in Support and Development, I decided to do some testing with the examples for Coroutines on lua.org and they look like they could be really useful. Especially if you need to create a lot of tables in memory and usually have long delays while waiting for them to be created.
Like if you need to create a grid. The bigger it is, the longer it takes to generate. But you shouldn't yield every single time in the loop because you end up making something that might take a few seconds into a half a minute or more. So you only yield every few hundred or thousand or so.
For example:
vs.
Now, with a 5,000x5,000 grid that's 25,000,000. So if you bump the yield cutoff up a bit, you can still keep it fast. See, while the grid creation part is fast, the other side may be the bottleneck. So raising the cutoff higher will cut down on how often the other side is processed and give more time per frame to the coroutine and allow it to do its thing faster. I mean 25 million is a lot. So cutting it into smaller chunks will make it go much much faster.
For instance:
These could be useful for stuff like progressbars too. Loading stuff while drawing the bar. A while ago I was playing with some code for downloading a file from the internet and instead of coroutines it instead just called certain love.run() functions from inside itself. But using a coroutine would be a lot more useful and better. More flexible too. And file downloading can take a while. For instance, when I downloaded some user levels for Mari0, the game froze while large files were downloading. I bet if it were modified to use coroutines it could be much better. No spinning rainbow cursor or hourglass.
Kind of makes me wish stuff loaded slower so I could make really cool loading screens.
Like if you need to create a grid. The bigger it is, the longer it takes to generate. But you shouldn't yield every single time in the loop because you end up making something that might take a few seconds into a half a minute or more. So you only yield every few hundred or thousand or so.
For example:
Code: Select all
function love.load()
--Create a 5000x5000 grid
local t = love.timer.getTime()
grid = {}
for x = 1, 5000 do
grid[x] = {}
for y = 1, 5000 do
grid[x][y] = 1
end
end
print("Time for non Coroutine Grid", love.timer.getTime() - t)
end
Code: Select all
function love.load()
--Set it up for coroutine this time
total = 0
grid = {}
co = coroutine.create(function()
local t = love.timer.getTime()
local i = 0
for x = 1, 5000 do
grid[x] = {}
for y = 1, 5000 do
grid[x][y] = 1
total = total + 1
i = i + 1
if i >= 10000 then
coroutine.yield()
i = 0
end
end
end
print("Time for Coroutine Grid", love.timer.getTime() - t)
end)
end
function love.update(dt)
coroutine.yield(co)
end
function love.draw()
love.graphics.print(love.graphics.getFPS() .. "\n" .. total, 10, 10)
end
For instance:
Code: Select all
1000 per call:
Time for non Coroutine Grid 0.385
Time for Coroutine Grid 45.052
10000 per call:
Time for non Coroutine Grid 0.385
Time for Coroutine Grid 4.329
100000 per call:
Time for non Coroutine Grid 0.427
Time for Coroutine Grid 0.93
Kind of makes me wish stuff loaded slower so I could make really cool loading screens.