MC subsystem tick overrun compensation (#2270)

Port of tgstation/tgstation#27196.

This PR makes the MC track how much a subsystem goes over its allotted tick limit and reduce how much of a tick it is allocated in later fires, as well as delaying later fires if the overrun is high enough.

Subsystems with SS_KEEP_TIMING will not be delayed due to overruns, but they will still get a reduced tick allocation.

Should lead to less tick-drift due to SSgarbage hard-deletions.
This commit is contained in:
Lohikar
2017-05-17 05:51:46 -05:00
committed by skull132
parent 6dea99eb64
commit c08922a181
3 changed files with 15 additions and 7 deletions

View File

@@ -421,26 +421,31 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
else
tick_precentage = tick_remaining
CURRENT_TICKLIMIT = world.tick_usage + tick_precentage
tick_precentage = max(tick_precentage * 0.5, tick_precentage - queue_node.tick_overrun)
CURRENT_TICKLIMIT = round(world.tick_usage + tick_precentage)
if (!(queue_node_flags & SS_TICKER))
ran_non_ticker = TRUE
ran = TRUE
tick_usage = world.tick_usage
queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING)
last_type_processed = queue_node
queue_node.state = SS_RUNNING
tick_usage = world.tick_usage
var/state = queue_node.ignite(queue_node_paused)
tick_usage = world.tick_usage - tick_usage
if (state == SS_RUNNING)
state = SS_IDLE
current_tick_budget -= queue_node_priority
tick_usage = world.tick_usage - tick_usage
if (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
if (state == SS_PAUSED)
@@ -467,13 +472,13 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
queue_node.times_fired++
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 + (queue_node.tick_overrun/100)))
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)
queue_node.next_fire += queue_node.wait
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

View File

@@ -21,6 +21,7 @@
var/next_fire = 0 //scheduled world.time for next fire()
var/cost = 0 //average time to execute
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/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
@@ -213,7 +214,7 @@
if (flags & SS_NO_FIRE)
. = "NO FIRE"
else if (can_fire && !suspended)
. = "[round(cost,1)]ms|[round(tick_usage,1)]%|[round(ticks,0.1)]"
. = "[round(cost,1)]ms|[round(tick_usage,1)]%([round(tick_overrun,1)]%)|[round(ticks,0.1)]"
else if (!can_fire)
. = "OFFLINE"
else