From 6e6f3365e245c8b37ccb5d34ebb7f7a404305a3a Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Wed, 25 Nov 2015 15:06:50 -0800 Subject: [PATCH] Master Controller lag fixes When the MC is making up missed subsystem fires from lag, it will now only fire that subsystem at most, half of that subsystem's normal fire rate until missed fires are made up, rather than firing as quick as possible making lag worst. When a subsystem causes byond to miss a byond tick, it will stop processing subsystems and sleep for two extra byond ticks on top of its normal sleep rate. When the cpu is above 80%, the MC will also sleep for twice as long between ticks (stacks with the change above) The processing interval of the MC is now capped to a lower bound of two byond ticks or 1ds, whatever is lower. Dwait now scales with the cpu usage var. 10% cpu adds 10% extra to dwait, 50% cpu adds 50% extra to dwait, etc. --- code/controllers/master_controller.dm | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 5eed9591ec3..6a7c120a7c9 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -36,12 +36,14 @@ calculate the longest number of ticks the MC can wait between each cycle without */ /datum/controller/game_controller/proc/calculateGCD() var/GCD + //shortest fire rate is the lower of two ticks or 1ds + var/minimumInterval = min(world.tick_lag*2,1) for(var/datum/subsystem/SS in subsystems) if(SS.wait) GCD = Gcd(round(SS.wait*10), GCD) GCD = round(GCD) - if(GCD < world.tick_lag*10) - GCD = world.tick_lag*10 + if(GCD < minimumInterval*10) + GCD = minimumInterval*10 processing_interval = GCD/10 /datum/controller/game_controller/proc/setup(zlevel) @@ -94,12 +96,12 @@ calculate the longest number of ticks the MC can wait between each cycle without while(1) //far more efficient than recursively calling ourself if(processing_interval > 0) ++iteration - + var/startingtick = world.time start_time = world.timeofday var/SubSystemRan = 0 for(var/datum/subsystem/SS in subsystems) if(SS.can_fire > 0) - if(SS.next_fire <= world.time) + if(SS.next_fire <= world.time && SS.last_fire+(wait*0.5) <= world.time) SubSystemRan = 1 timer = world.timeofday last_thing_processed = SS.type @@ -110,18 +112,27 @@ calculate the longest number of ticks the MC can wait between each cycle without var/oldwait = SS.wait var/GlobalCostDelta = (SSCostPerSecond-(SS.cost/(SS.wait/10)))-1 var/NewWait = MC_AVERAGE(oldwait,(SS.cost-SS.dwait_buffer+GlobalCostDelta)*SS.dwait_delta) + NewWait = NewWait*(world.cpu/100+1) SS.wait = Clamp(NewWait,SS.dwait_lower,SS.dwait_upper) if (oldwait != SS.wait) calculateGCD() SS.next_fire += SS.wait ++SS.times_fired - + //we caused byond to miss a tick, stop processing for a bit + if (startingtick < world.time || start_time+1 < world.timeofday) + break sleep(-1) cost = MC_AVERAGE(cost, world.timeofday - start_time) if (SubSystemRan) calculateSScost() - sleep(processing_interval) + var/extrasleep = 0 + if (startingtick < world.time || start_time+1 < world.timeofday) + //we caused byond to miss a tick, sleep a bit extra + extrasleep += world.tick_lag*2 + if (world.cpu > 80) + extrasleep += extrasleep+processing_interval + sleep(processing_interval+extrasleep) else sleep(50)