Page 1 of 1

Reducing impact of ontick event scripts

Posted: Mon Dec 29, 2014 4:58 pm
by starholme
So, in the control.lua script I have a ontick event handler. Every tick it goes through a table, does some stuff with each entity in the table. Pretty standard stuff.

To prevent wasted cycles I currently skip the handler if there is no entities. This is simple, and works fine.

Does anyone have a good example of a way for an entity to 'back off' when it's not very busy?
I'm thinking about using something like:

if current tick % backoff == 0 then
if entityDidStuff() then
backoff = 1
else
backoff = backoff + 6(one tenth of a second, could be any number really)
if backoff > 60 (one second, but whatever makes sense)
backoff = 60

I'd like to know anyone else's experience with this sort of system, or if they have some sort of improvements. I'm not worried about having actual code here(although if we find a nice general solution, I'll add it to the op), pseudo code is just fine.

Any other tips and tricks for reducing your script impact are welcome here as well.

Re: Reducing impact of ontick event scripts

Posted: Thu Jan 01, 2015 1:33 am
by Degraine
I haven't come up with anything better than that myself. I use a simple gametick % 5 check in the ontick event in Slipstream, but maybe you could do something with loading and unloading event subscriptions...?

Re: Reducing impact of ontick event scripts

Posted: Thu Jan 01, 2015 2:44 pm
by Choumiko
I'm currently using something like this (shortened):

Code: Select all

function ontick(event)
  if #glob.waitingTrains > 0 then
    for i,t in ipairs(glob.waitingTrains) do
      local wait = t.lastCheck + t.settings.autoDepart.interval
      if event.tick >= wait then
        --do stuff
        t.lastCheck = event.tick
    end
  end
Note that the vars wait and lastCheck have nothing to do with your backoff, it's a vital part of my mod.
One idea i had is:

Code: Select all

function ontick(event)
  if event.tick >= glob.nextCheck and #glob.waitingTrains > 0 then
    for i,t in ipairs(glob.waitingTrains) do
      local wait = t.lastCheck + t.settings.autoDepart.interval
      if event.tick >= wait then
        --do stuff
        t.lastCheck = event.tick
        local nextTick = event.tick + t.settings.autoDepart.interval
        glob.nextCheck =  math.min(nextTick, glob.nextCheck)
      end
    end
  end
end
Basically the enities tell the mod the tick when they need to do stuff again, and until then the table with them doesn't even get touched. With my entities being trains i decided not to bother with it, since the count should be in dimensions where it's not going to matter (much).
I guess optimisations like this really depend on the amount of entities and the work/cpu time they need.