MC Performance Tweaks (#3621)

Ports some StonedMC performance tweaks from /tg/, should reduce the amount of fighting between BYOND sleeps and the MC.
This commit is contained in:
Lohikar
2017-10-14 19:31:14 +03:00
committed by Erki
parent 37908e5c4b
commit 4773a8a626
8 changed files with 55 additions and 38 deletions
+23 -15
View File
@@ -31,7 +31,7 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
var/init_time
var/tickdrift = 0
var/sleep_delta
var/sleep_delta = 1
var/make_runtime = 0
@@ -266,33 +266,40 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
iteration = 1
var/error_level = 0
var/sleep_delta = 0
var/sleep_delta = 1
var/list/subsystems_to_check
//the actual loop.
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
var/starting_tick_usage = world.tick_usage
if (processing <= 0)
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
sleep(10)
continue
//if there are mutiple sleeping procs running before us hogging the cpu, we have to run later
// because sleeps are processed in the order received, so longer sleeps are more likely to run first
if (world.tick_usage > TICK_LIMIT_MC)
sleep_delta += 2
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.5)
sleep(world.tick_lag * (processing + sleep_delta))
//Anti-tick-contention heuristics:
//if there are mutiple sleeping procs running before us hogging the cpu, we have to run later.
// (because sleeps are processed in the order received, longer sleeps are more likely to run first)
if (starting_tick_usage > TICK_LIMIT_MC)
sleep_delta *= 2
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING * 0.5
sleep(world.tick_lag * (processing * sleep_delta))
continue
sleep_delta = MC_AVERAGE_FAST(sleep_delta, 0)
if (last_run + (world.tick_lag * processing) > world.time)
sleep_delta += 1
if (world.tick_usage > (TICK_LIMIT_MC*0.5))
//Byond resumed us late. assume it might have to do the same next tick
if (last_run + Ceiling(world.tick_lag * (processing * sleep_delta), world.tick_lag) < world.time)
sleep_delta += 1
sleep_delta = MC_AVERAGE_FAST(sleep_delta, 1) //decay sleep_delta
if (starting_tick_usage > (TICK_LIMIT_MC*0.75)) //we ran 3/4 of the way into the tick
sleep_delta += 1
// debug
if (make_runtime)
var/datum/controller/subsystem/SS
SS.can_fire = 0
if (!Failsafe || (Failsafe.processing_interval > 0 && (Failsafe.lasttick+(Failsafe.processing_interval*5)) < world.time))
new/datum/controller/failsafe() // (re)Start the failsafe.
if (!queue_head || !(iteration % 3))
@@ -332,10 +339,11 @@ var/CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
iteration++
last_run = world.time
src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta)
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc.
sleep(world.tick_lag * (processing + sleep_delta))
CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING
if (processing * sleep_delta <= world.tick_lag)
CURRENT_TICKLIMIT -= (TICK_LIMIT_RUNNING)
sleep(world.tick_lag * (processing * sleep_delta))
// This is what decides if something should run.