mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 01:49:19 +00:00
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:
committed by
CitadelStationBot
parent
f8d0646b09
commit
7b30be0058
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
while(loc)
|
||||
if(paused)
|
||||
next_run = world.time
|
||||
sleep(1)
|
||||
stoplag(1)
|
||||
continue
|
||||
|
||||
if((!( current ) || loc == current))
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user