N-lane Tick Balancer (Lua library)
Posted: Sat Apr 23, 2016 9:41 pm
TickBalancer 1.0.0
Not 100% sure which board to post this in ... please move as appropriate!
I've seen a lot of mods (in fact, pretty much almost every mod) using the following code pattern:
What's the problem here? Well, handling ticks like this certainly reduces your load to 1/20th. But we still have a problem. 3 times per second we are processing all our entities, and this simply does not scale well. In fact it scales exactly as badly as processing all your entities every frame; in other words, when we have thousands of entities, the player is going to suffer performance problems whether you are checking those entities one tick in 60 or every tick in 60. Arguably the lag is even more jarring when it only happens on some frames rather than every frame!
There's an additional (and slightly hidden) problem; this doesn't play nicely with other mods. If another mod author has used the same pattern (and with any convenient multiple such as 5, 10, 30, 40, 60...) then both your mod and the other mod will both be processing all their entities on the same tick.
So, what is the solution? Well, what you need there is the N-lane Tick Balancer. This will increase your throughput by a factor of 20, assuming the above code.
What this does is spread your tick handlers evenly across every available tick. I think the lane balancer is the most appropriate analogy for this function.
To use this, firstly copy the TickBalancer.lua file into a /lib directory in your mod. Now, just add the following to your control.lua:
For a default setup (i.e. a global table storing some data against an entity, where the table is called "global.myDataProperty") this is all you need. If you are converting an existing mod to use the balancer then you can use the following in your control.lua to perform a migration. Unfortunately it doesn't seem possible to use a standard migration script as the global data is not yet present (correct me if I'm wrong).
(Note, you must change the storage name, the balancer won't initialise correctly on top of the old table.)
I have attempted to implement this as optimally as possible, however some improvements are surely possible so please leave any suggestions!
You can see the balancer in use in my Blueprint Automated Deployment mod: viewtopic.php?f=93&t=24053
The source is hosted on GitHub, get the latest version and submit any bug reports or pull requests here:
https://github.com/chucksellick/factorio-tick-balancer
Not 100% sure which board to post this in ... please move as appropriate!
I've seen a lot of mods (in fact, pretty much almost every mod) using the following code pattern:
Code: Select all
script.on_event(defines.events.on_tick, function(event)
if event.tick % 20 == 0 then
-- Process all your entities here
end
end)
There's an additional (and slightly hidden) problem; this doesn't play nicely with other mods. If another mod author has used the same pattern (and with any convenient multiple such as 5, 10, 30, 40, 60...) then both your mod and the other mod will both be processing all their entities on the same tick.
So, what is the solution? Well, what you need there is the N-lane Tick Balancer. This will increase your throughput by a factor of 20, assuming the above code.
What this does is spread your tick handlers evenly across every available tick. I think the lane balancer is the most appropriate analogy for this function.
To use this, firstly copy the TickBalancer.lua file into a /lib directory in your mod. Now, just add the following to your control.lua:
Code: Select all
require "lib.TickBalancer"
local balancer = nil
function onInit()
balancer = TickBalancer.setupForEntity("my-entity-type", "myDataProperty", 20, function(data)
-- Process data.entity here
end)
end
script.on_init(onInit)
script.on_load(onInit)
Code: Select all
function onConfigurationChanged(data)
if data.mod_changes ~= nil and data.mod_changes["my-mod-name"] ~= nil and (data.mod_changes["my-mod-name"].old_version == "0.0.1") then -- Or another version comparison that makes sense
balancer:migrateEntityData(global.myOldDataProperty)
global.myOldDataProperty = nil
end
end
I have attempted to implement this as optimally as possible, however some improvements are surely possible so please leave any suggestions!
You can see the balancer in use in my Blueprint Automated Deployment mod: viewtopic.php?f=93&t=24053
The source is hosted on GitHub, get the latest version and submit any bug reports or pull requests here:
https://github.com/chucksellick/factorio-tick-balancer