From 6a9036149cea30910de7972562e2fa87a2d3e2a1 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Mon, 10 Apr 2023 04:36:44 +0200 Subject: [PATCH] [MIRROR] Significantly speed up create & destroy by reducing the amount of time to wait for GC [MDB IGNORE] (#20459) * Significantly speed up create & destroy by reducing the amount of time to wait for GC (#74604) The check queue is 5 minutes long because that's the longest a client can hold onto a reference. Without clients, we can drastically decrease the time we have to wait. This lowers the time down to 10 seconds (though everything right now deletes in 5). This will represent a 5 minute decrease in CI across the board, freeing up runners. Makes a few changes to stuff that was being held for more than 10 seconds. - `VARSET_CALLBACK` now works through weakrefs, to allow for pAIs to have their holochassis init timers. - Nar'Sie cleans herself up in GLOB.cult_narsie if she's deleted. - "Spooky portals" no longer hold onto a reference for 2 minutes. - `poll_candidates` short circuits to an empty list if there are no candidates, to avoid several 30 second+ long timers Originally this was going to be a more clever hack from @ MrStonedOne about short circuiting if everything deletes before the wait, but we realized that basically nothing actually holds onto references for that long without clients, and that nothing really should anyway * Significantly speed up create & destroy by reducing the amount of time to wait for GC --------- Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com> --- code/__HELPERS/game.dm | 3 +++ code/__HELPERS/varset_callback.dm | 11 +++++++++++ .../objects/effects/anomalies/anomalies_ectoplasm.dm | 2 +- code/modules/pai/pai.dm | 2 +- code/modules/power/singularity/narsie.dm | 3 +++ code/modules/unit_tests/create_and_destroy.dm | 10 ++++++++-- code/modules/unit_tests/unit_test.dm | 2 +- 7 files changed, 28 insertions(+), 5 deletions(-) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index 75b41b952b7..78a9fbc53f6 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -238,6 +238,9 @@ ///Calls the show_candidate_poll_window() to all eligible ghosts /proc/poll_candidates(question, jobban_type, be_special_flag = 0, poll_time = 300, ignore_category = null, flashwindow = TRUE, list/group = null) + if (group.len == 0) + return list() + var/time_passed = world.time if (!question) question = "Would you like to be a special role?" diff --git a/code/__HELPERS/varset_callback.dm b/code/__HELPERS/varset_callback.dm index 54fc821cacc..4f132b9e20f 100644 --- a/code/__HELPERS/varset_callback.dm +++ b/code/__HELPERS/varset_callback.dm @@ -1,12 +1,23 @@ #define VARSET_LIST_CALLBACK(target, var_name, var_value) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___callbackvarset), ##target, ##var_name, ##var_value) //dupe code because dm can't handle 3 level deep macros #define VARSET_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___callbackvarset), ##datum, NAMEOF(##datum, ##var), ##var_value) +/// Same as VARSET_CALLBACK, but uses a weakref to the datum. +/// Use this if the timer is exceptionally long. +#define VARSET_WEAK_CALLBACK(datum, var, var_value) CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(___callbackvarset), WEAKREF(##datum), NAMEOF(##datum, ##var), ##var_value) /proc/___callbackvarset(list_or_datum, var_name, var_value) if(length(list_or_datum)) list_or_datum[var_name] = var_value return + var/datum/datum = list_or_datum + + if (isweakref(datum)) + var/datum/weakref/datum_weakref = datum + datum = datum_weakref.resolve() + if (isnull(datum)) + return + if(IsAdminAdvancedProcCall()) datum.vv_edit_var(var_name, var_value) //same result generally, unless badmemes else diff --git a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm index 554310bd08a..51fe6b8cc84 100644 --- a/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm +++ b/code/game/objects/effects/anomalies/anomalies_ectoplasm.dm @@ -147,7 +147,7 @@ START_PROCESSING(SSobj, src) INVOKE_ASYNC(src, PROC_REF(make_ghost_swarm), candidate_list) playsound(src, pick(spooky_noises), 100, TRUE) - QDEL_IN(src, 2 MINUTES) + QDEL_IN(WEAKREF(src), 2 MINUTES) /obj/structure/ghost_portal/process(delta_time) . = ..() diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index acb1fba2a40..204b6fdcecf 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -219,7 +219,7 @@ pai_card.set_personality(src) forceMove(pai_card) card = pai_card - addtimer(VARSET_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_INIT_TIME) + addtimer(VARSET_WEAK_CALLBACK(src, holochassis_ready, TRUE), HOLOCHASSIS_INIT_TIME) if(!holoform) add_traits(list(TRAIT_IMMOBILIZED, TRAIT_HANDS_BLOCKED), PAI_FOLDED) desc = "A pAI hard-light holographics emitter. This one appears in the form of a [chassis]." diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index dfe244cda2d..f870ec15e77 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -107,6 +107,9 @@ summon_objective.summoned = FALSE summon_objective.killed = TRUE + if (GLOB.cult_narsie == src) + GLOB.cult_narsie = null + return ..() /obj/narsie/attack_ghost(mob/user) diff --git a/code/modules/unit_tests/create_and_destroy.dm b/code/modules/unit_tests/create_and_destroy.dm index f932098a368..79bd76b8b9b 100644 --- a/code/modules/unit_tests/create_and_destroy.dm +++ b/code/modules/unit_tests/create_and_destroy.dm @@ -157,13 +157,18 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE) GLOB.running_create_and_destroy = FALSE //Hell code, we're bound to have ended the round somehow so let's stop if from ending while we work SSticker.delay_end = TRUE + + // Drastically lower the amount of time it takes to GC, since we don't have clients that can hold it up. + SSgarbage.collection_timeout[GC_QUEUE_CHECK] = 10 SECONDS //Prevent the garbage subsystem from harddeling anything, if only to save time SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = 10000 HOURS //Clear it, just in case cached_contents.Cut() //Now that we've qdel'd everything, let's sleep until the gc has processed all the shit we care about - var/time_needed = SSgarbage.collection_timeout[GC_QUEUE_CHECK] + // + 2 seconds to ensure that everything gets in the queue. + var/time_needed = SSgarbage.collection_timeout[GC_QUEUE_CHECK] + 2 SECONDS + var/start_time = world.time var/garbage_queue_processed = FALSE @@ -215,4 +220,5 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE) SSticker.delay_end = FALSE //This shouldn't be needed, but let's be polite - SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = 10 SECONDS + SSgarbage.collection_timeout[GC_QUEUE_CHECK] = GC_CHECK_QUEUE + SSgarbage.collection_timeout[GC_QUEUE_HARDDELETE] = GC_DEL_QUEUE diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index ab2bc776a27..efd1290d00d 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -223,7 +223,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) SSticker.force_ending = TRUE //We have to call this manually because del_text can preceed us, and SSticker doesn't fire in the post game - SSticker.standard_reboot() + SSticker.declare_completion() /datum/map_template/unit_tests name = "Unit Tests Zone"