Ports "The punisher!"

* From tgstation/tgstation#27196
* The mc will now punish subsystems that overrun their tick allotment with less allotment in later fires.
* The punisher also delays the next fire of subsystems that overrun. Because of how this is ends up being calculated, this will almost never actually kick in, but sometimes subsystems like garbage will overrun into multiple ticks, so delaying their next fire is needed.
* The punisher does not delay the next fire of SS_TICKER subsystems (tgstation/tgstation#34964)
Note: SS_KEEP_TIMING subsystems do not get their next fire delayed.
This commit is contained in:
Leshana
2018-04-20 16:19:29 -04:00
parent 0d957e35a5
commit 0094c74b64
3 changed files with 19 additions and 8 deletions

View File

@@ -27,6 +27,10 @@ if(current_step == this_step || (initial_step && !resumed)) /* So we start at st
#define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current)) #define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current))
#define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current)) #define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current))
#define MC_AVERAGE_SLOW(average, current) (0.9 * (average) + 0.1 * (current)) #define MC_AVERAGE_SLOW(average, current) (0.9 * (average) + 0.1 * (current))
#define MC_AVG_FAST_UP_SLOW_DOWN(average, current) (average > current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define MC_AVG_SLOW_UP_FAST_DOWN(average, current) (average < current ? MC_AVERAGE_SLOW(average, current) : MC_AVERAGE_FAST(average, current))
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;} #define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!Datum.isprocessing) {Datum.isprocessing = 1;Processor.processing += Datum} #define START_PROCESSING(Processor, Datum) if (!Datum.isprocessing) {Datum.isprocessing = 1;Processor.processing += Datum}

View File

@@ -428,7 +428,7 @@ var/datum/controller/master/Master = new()
// in those cases, so we just let them run) // in those cases, so we just let them run)
if (queue_node_flags & SS_NO_TICK_CHECK) if (queue_node_flags & SS_NO_TICK_CHECK)
if (queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker) if (queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker)
queue_node.queued_priority += queue_priority_count * 0.10 queue_node.queued_priority += queue_priority_count * 0.1
queue_priority_count -= queue_node_priority queue_priority_count -= queue_node_priority
queue_priority_count += queue_node.queued_priority queue_priority_count += queue_node.queued_priority
current_tick_budget -= queue_node_priority current_tick_budget -= queue_node_priority
@@ -446,26 +446,32 @@ var/datum/controller/master/Master = new()
else else
tick_precentage = tick_remaining tick_precentage = tick_remaining
current_ticklimit = TICK_USAGE + tick_precentage // Reduce tick allocation for subsystems that overran on their last tick.
tick_precentage = max(tick_precentage*0.5, tick_precentage-queue_node.tick_overrun)
current_ticklimit = round(TICK_USAGE + tick_precentage)
if (!(queue_node_flags & SS_TICKER)) if (!(queue_node_flags & SS_TICKER))
ran_non_ticker = TRUE ran_non_ticker = TRUE
ran = TRUE ran = TRUE
tick_usage = TICK_USAGE
queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING) queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING)
last_type_processed = queue_node last_type_processed = queue_node
queue_node.state = SS_RUNNING queue_node.state = SS_RUNNING
tick_usage = TICK_USAGE
var/state = queue_node.ignite(queue_node_paused) var/state = queue_node.ignite(queue_node_paused)
tick_usage = TICK_USAGE - tick_usage
if (state == SS_RUNNING) if (state == SS_RUNNING)
state = SS_IDLE state = SS_IDLE
current_tick_budget -= queue_node_priority current_tick_budget -= queue_node_priority
tick_usage = TICK_USAGE - tick_usage
if (tick_usage < 0) if (tick_usage < 0)
tick_usage = 0 tick_usage = 0
queue_node.tick_overrun = max(0, MC_AVG_FAST_UP_SLOW_DOWN(queue_node.tick_overrun, tick_usage-tick_precentage))
queue_node.state = state queue_node.state = state
if (state == SS_PAUSED) if (state == SS_PAUSED)
@@ -494,11 +500,11 @@ var/datum/controller/master/Master = new()
if (queue_node_flags & SS_TICKER) if (queue_node_flags & SS_TICKER)
queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait) queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait)
else if (queue_node_flags & SS_POST_FIRE_TIMING) else if (queue_node_flags & SS_POST_FIRE_TIMING)
queue_node.next_fire = world.time + queue_node.wait queue_node.next_fire = world.time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
else if (queue_node_flags & SS_KEEP_TIMING) else if (queue_node_flags & SS_KEEP_TIMING)
queue_node.next_fire += queue_node.wait queue_node.next_fire += queue_node.wait
else else
queue_node.next_fire = queue_node.queued_time + queue_node.wait queue_node.next_fire = queue_node.queued_time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
queue_node.queued_time = 0 queue_node.queued_time = 0

View File

@@ -17,6 +17,7 @@
var/next_fire = 0 //scheduled world.time for next fire() var/next_fire = 0 //scheduled world.time for next fire()
var/cost = 0 //average time to execute var/cost = 0 //average time to execute
var/tick_usage = 0 //average tick usage var/tick_usage = 0 //average tick usage
var/tick_overrun = 0 //average tick overrun
var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc. var/state = SS_IDLE //tracks the current state of the ss, running, paused, etc.
var/paused_ticks = 0 //ticks this ss is taking to run right now. var/paused_ticks = 0 //ticks this ss is taking to run right now.
var/paused_tick_usage //total tick_usage of all of our runs while pausing this run var/paused_tick_usage //total tick_usage of all of our runs while pausing this run
@@ -167,7 +168,7 @@
if(can_fire && !(SS_NO_FIRE & flags)) if(can_fire && !(SS_NO_FIRE & flags))
msg = "[round(cost,1)]ms|[round(tick_usage,1)]%|[round(ticks,0.1)]\t[msg]" msg = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]\t[msg]"
else else
msg = "OFFLINE\t[msg]" msg = "OFFLINE\t[msg]"