Merge pull request #31494 from MrStonedOne/tick_contention_tug_of_war

In which the stoner one gets stoned and tries to address tick contention... again
This commit is contained in:
Jordan Brown
2017-10-10 14:27:59 -04:00
committed by CitadelStationBot
parent f8d0646b09
commit 7b30be0058
21 changed files with 72 additions and 54 deletions

View File

@@ -1,5 +1,5 @@
#define TICK_LIMIT_RUNNING 80
#define TICK_LIMIT_TO_RUN 78
#define TICK_LIMIT_TO_RUN 70
#define TICK_LIMIT_MC 70
#define TICK_LIMIT_MC_INIT_DEFAULT 98

View File

@@ -20,4 +20,8 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
#define HOURS MINUTES*60
#define TICKS *world.tick_lag
#define TICKS *world.tick_lag
#define DS2TICKS(DS) (DS/world.tick_lag)
#define TICKS2DS(T) (T TICKS)

View File

@@ -321,7 +321,7 @@ Proc for attack log creation, because really why not
var/starttime = world.time
. = 1
while (world.time < endtime)
stoplag()
stoplag(1)
if (progress)
progbar.update(world.time - starttime)
if(QDELETED(user) || QDELETED(target))
@@ -382,7 +382,7 @@ Proc for attack log creation, because really why not
var/starttime = world.time
. = 1
while (world.time < endtime)
stoplag()
stoplag(1)
if (progress)
progbar.update(world.time - starttime)
@@ -437,7 +437,7 @@ Proc for attack log creation, because really why not
. = 1
mainloop:
while(world.time < endtime)
sleep(1)
stoplag(1)
if(progress)
progbar.update(world.time - starttime)
if(QDELETED(user) || !targets)

View File

@@ -504,10 +504,10 @@ Turf and target are separate in case you want to teleport some distance from a t
/atom/proc/GetAllContents(list/output=list())
. = output
output += src
for(var/i in 1 to contents.len)
var/atom/thing = contents[i]
thing.GetAllContents(output)
output += src
for(var/i in 1 to contents.len)
var/atom/thing = contents[i]
thing.GetAllContents(output)
//Step-towards method of determining whether one atom can see another. Similar to viewers()
/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
@@ -1225,16 +1225,19 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types())
//Increases delay as the server gets more overloaded,
//as sleeps aren't cheap and sleeping only to wake up and sleep again is wasteful
#define DELTA_CALC max(((max(TICK_USAGE, world.cpu) / 100) * max(Master.sleep_delta,1)), 1)
#define DELTA_CALC max(((max(TICK_USAGE, world.cpu) / 100) * max(Master.sleep_delta-1,1)), 1)
/proc/stoplag()
//returns the number of ticks slept
/proc/stoplag(initial_delay)
if (!Master || !(Master.current_runlevel & RUNLEVELS_DEFAULT))
sleep(world.tick_lag)
return 1
if (!initial_delay)
initial_delay = world.tick_lag
. = 0
var/i = 1
var/i = DS2TICKS(initial_delay)
do
. += round(i*DELTA_CALC)
. += Ceiling(i*DELTA_CALC)
sleep(i*world.tick_lag*DELTA_CALC)
i *= 2
while (TICK_USAGE > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit))

View File

@@ -33,7 +33,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/init_time
var/tickdrift = 0
var/sleep_delta
var/sleep_delta = 1
var/make_runtime = 0
@@ -53,7 +53,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/static/restart_clear = 0
var/static/restart_timeout = 0
var/static/restart_count = 0
//current tick limit, assigned before running a subsystem.
//used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
var/static/current_ticklimit = TICK_LIMIT_RUNNING
@@ -276,35 +276,45 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
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 = 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 (TICK_USAGE > TICK_LIMIT_MC)
sleep_delta += 2
//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) //if there isn't enough time to bother doing anything this tick, sleep a bit.
sleep_delta *= 2
current_ticklimit = TICK_LIMIT_RUNNING * 0.5
sleep(world.tick_lag * (processing + sleep_delta))
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 (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.
//now do the actual stuff
if (!queue_head || !(iteration % 3))
var/checking_runlevel = current_runlevel
if(cached_runlevel != checking_runlevel)
@@ -321,6 +331,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
subsystems_to_check = current_runlevel_subsystems
else
subsystems_to_check = tickersubsystems
if (CheckQueue(subsystems_to_check) <= 0)
if (!SoftReset(tickersubsystems, runlevel_sorted_subsystems))
log_world("MC: SoftReset() failed, crashing")
@@ -351,8 +362,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
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 * 0.25) //reserve the tail 1/4 of the next tick for the mc if we plan on running next tick
sleep(world.tick_lag * (processing * sleep_delta))

View File

@@ -177,7 +177,7 @@
/datum/browser/alert/proc/wait()
while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time))
stoplag()
stoplag(1)
/datum/browser/alert/Topic(href,href_list)
if (href_list["close"] || !user || !user.client)

View File

@@ -61,14 +61,14 @@ GLOBAL_LIST_EMPTY(explosions)
flash_range = min(GLOB.MAX_EX_FLASH_RANGE, flash_range)
flame_range = min(GLOB.MAX_EX_FLAME_RANGE, flame_range)
//DO NOT REMOVE THIS SLEEP, IT BREAKS THINGS
//DO NOT REMOVE THIS STOPLAG, IT BREAKS THINGS
//not sleeping causes us to ex_act() the thing that triggered the explosion
//doing that might cause it to trigger another explosion
//this is bad
//I would make this not ex_act the thing that triggered the explosion,
//but everything that explodes gives us their loc or a get_turf()
//and somethings expect us to ex_act them so they can qdel()
sleep(1) //tldr, let the calling proc call qdel(src) before we explode
stoplag() //tldr, let the calling proc call qdel(src) before we explode
EX_PREPROCESS_EXIT_CHECK

View File

@@ -199,7 +199,7 @@
set waitfor = FALSE
if (D)
animate(D, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0)
sleep (15)
sleep(15)
if (D)
animate(D, transform = null, time = 1, loop = 0)
@@ -258,7 +258,7 @@
D.pixel_y = 0
return 0
sleep (1)
sleep(1)
if (A && D)
A.pixel_x = 0

View File

@@ -1300,7 +1300,7 @@
if (istype(M))
for(var/datum/disease/transformation/jungle_fever/JF in M.viruses)
JF.cure(0)
sleep(0) //because deleting of virus is doing throught spawn(0) //What
stoplag() //because deleting of virus is doing throught spawn(0) //What
log_admin("[key_name(usr)] attempting to humanize [key_name(current)]")
message_admins("<span class='notice'>[key_name_admin(usr)] attempting to humanize [key_name_admin(current)]</span>")
H = M.humanize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_DEFAULTMSG)

View File

@@ -123,10 +123,9 @@
if(glow_type)
glow = new glow_type(get_turf(src))
animate(glow, alpha = 255, time = convert_time)
var/I = 0
while(I < convert_time && get_turf(L) == get_turf(src))
I++
sleep(1)
var/end_time = world.time+convert_time
while(world.time < end_time && get_turf(L) == get_turf(src))
stoplag(1)
if(get_turf(L) != get_turf(src))
if(glow)
qdel(glow)

View File

@@ -319,7 +319,7 @@ Applications: 8 servants, 3 caches, and 100 CV
qdel(progbar)
else
progbar.update(end_time - world.time)
sleep(1)
stoplag(1)
if(slab)
if(slab.slab_ability)
successful = slab.slab_ability.successful

View File

@@ -381,7 +381,7 @@
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-3,0)
animate(M, transform = initial_matrix, time = 1, loop = 0)
sleep (1)
sleep(1)
M.lying_fix()
@@ -428,7 +428,7 @@
initial_matrix = matrix(M.transform)
initial_matrix.Translate(-3,0)
animate(M, transform = initial_matrix, time = 1, loop = 0)
sleep (1)
sleep(1)
M.lying_fix()

View File

@@ -344,7 +344,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/datum/progressbar/progress = new(user, len, loc)
while (do_after(user, 10, TRUE, S, FALSE, CALLBACK(src, .proc/handle_mass_pickup, S, things, loc, rejections, progress)))
sleep(1)
stoplag(1)
qdel(progress)

View File

@@ -88,7 +88,7 @@
var/list/things = src_object.contents.Copy()
var/datum/progressbar/progress = new(user, things.len, src)
while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src, .proc/handle_mass_item_insertion, things, src_object, user, progress)))
sleep(1)
stoplag(1)
qdel(progress)
orient2hud(user)
src_object.orient2hud(user)
@@ -489,7 +489,7 @@
var/list/things = contents.Copy()
var/datum/progressbar/progress = new(usr, things.len, T)
while (do_after(usr, 10, TRUE, T, FALSE, CALLBACK(src, .proc/mass_remove_from_storage, T, things, progress)))
sleep(1)
stoplag(1)
qdel(progress)
/obj/item/storage/proc/mass_remove_from_storage(atom/target, list/things, datum/progressbar/progress)

View File

@@ -120,7 +120,7 @@
return
emagged = TRUE
to_chat(user, "<span class='notice'>You emag the barsign. Takeover in progress...</span>")
sleep(100) //10 seconds
sleep(10 SECONDS)
set_sign(new /datum/barsign/hiddensigns/syndibarsign)
req_access = list(ACCESS_SYNDICATE)

View File

@@ -330,7 +330,7 @@
var/list/things = src_object.contents.Copy()
var/datum/progressbar/progress = new(user, things.len, src)
while (do_after(usr, 10, TRUE, src, FALSE, CALLBACK(src_object, /obj/item/storage.proc/mass_remove_from_storage, src, things, progress)))
sleep(1)
stoplag(1)
qdel(progress)
return TRUE

View File

@@ -61,7 +61,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
var/t = 0
var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
sleep(1) // Lock up the caller until this is received.
stoplag(1) // Lock up the caller until this is received.
t++
if(client)
@@ -112,7 +112,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
var/t = 0
var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len
while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic()
sleep(1) // Lock up the caller until this is received.
stoplag(1) // Lock up the caller until this is received.
t++
if(client)
@@ -131,7 +131,7 @@ You can set verify to TRUE if you want send() to sleep until the client has the
if (register_asset)
register_asset(file,files[file])
send_asset(client,file)
sleep(0) //queuing calls like this too quickly can cause issues in some client versions
stoplag(0) //queuing calls like this too quickly can cause issues in some client versions
//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up.
//if it's an icon or something be careful, you'll have to copy it before further use.

View File

@@ -631,10 +631,9 @@ GLOBAL_LIST(external_rsc_urls)
/client/Stat()
. = ..()
if (holder)
sleep(1)
stoplag(1)
else
sleep(5)
stoplag()
stoplag(5)
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
/client/proc/send_resources()

View File

@@ -161,7 +161,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
if(next_move <= world.time)
sleep(1)
stoplag(1)
.() //retry
return
sleep((next_move - world.time) * 1.5)

View File

@@ -228,7 +228,7 @@
while(loc)
if(paused)
next_run = world.time
sleep(1)
stoplag(1)
continue
if((!( current ) || loc == current))

View File

@@ -21,7 +21,7 @@
return 0
while(attached_hand) //hibernate untill the spell is actually used
charge_counter = 0
sleep(1)
stoplag(1)
/obj/effect/proc_holder/spell/targeted/touch/proc/ChargeHand(mob/living/carbon/user)
attached_hand = new hand_path(src)