One thing I was grappling with for a while was garbage collection. I frequently spawn/despawn lots of blocks as the player moves around in the world. This eventually triggers the garbage collector, which results in a really noticeable stutter.
I used the discussion in this thread as a starting point for a solution. Thank you @cornedbeer - your thoughts were really useful and I would have struggled to realise that placing this script in the main collection would ensure it runs last.
The idea is that I run the garbage collector in tiny increments each frame, until I reach the time limit (e.g. 0.167 seconds for 60 fps). I have also implemented a flag which prevents the garbage collector from running on particularly intensive frames (e.g. if I despawn a chunk of blocks).
Simplified, it looks something like this:
if garbage.intensive_frame then
--Don't run the garbage collector during a particulary intensive frame
--This flag can be set by any script and will prevent garbage collection from running that frame
collectgarbage("stop")
garbage.intensive_frame = false
else
--Run garbage collection steps until finished or we run out of time this frame
-- https://forum.defold.com/t/solved-optimizing-frame-stability-avoiding-garbage-collector-related-hitches/70930/3
frame_time_diff = socket.gettime() - frame_start_time
garbage_finished = false
while not garbage_finished and frame_time_diff < frame_time_target do
garbage_finished = collectgarbage("step", 1)
frame_time_diff = socket.gettime() - frame_start_time
end
end
frame_start_time = socket.gettime()
A key component of making this work is setting a reasonable step size for the garbage collector. For me, this was 110:
collectgarbage("setstepmul", 110)