From 8469b4223eef83db794073f4757a4d20c35af561 Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Fri, 27 Oct 2017 02:56:34 -0700 Subject: [PATCH 1/2] Find references fix. (#32022) * Find references fix. Made it go from taking years to hours Removed Datum based recursion, this was unneeded. Fixed it calling a proc for what ended up being a costly noop millions of times (this was a moderate speed up as it would call DoSearchVar on every fucking number or string or null in a things vars list.) Fixed it calling itself on the vars list. luckily it only checked keys, so this didn't stack overflow. I'm intentionally leaving the debugging stuff in right now so that its on the record somewhere. I'll remove that when I pr line by line profiling as its own separate thing * Remove debugging stuff * i forgot --- code/__HELPERS/cmp.dm | 1 + code/_compile_options.dm | 11 ++++- code/controllers/subsystem/garbage.dm | 63 +++++++++++++++++---------- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 1c9c33f21a..f7b0f726d3 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -58,3 +58,4 @@ GLOBAL_VAR_INIT(cmp_field, "name") . = B.failures - A.failures if (!.) . = B.qdels - A.qdels + diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 1c1ad2e692..1f20614c17 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -5,8 +5,10 @@ #ifdef TESTING //#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing. - //Also allows for recursive reference searching of datums. - //Sets world.loop_checks to false and prevents find references from sleeping + //implies FIND_REF_NO_CHECK_TICK + +//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping + //#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green #endif @@ -58,6 +60,11 @@ #warn compiling in TESTING mode. testing() debug messages will be visible. #endif + +#ifdef GC_FAILURE_HARD_LOOKUP +#define FIND_REF_NO_CHECK_TICK +#endif + #ifdef TRAVISTESTING #define TESTING #endif diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 689ff83935..ccfc041b21 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -362,9 +362,17 @@ SUBSYSTEM_DEF(garbage) testing("Beginning search for references to a [type].") last_find_references = world.time - DoSearchVar(GLOB) - for(var/datum/thing in world) - DoSearchVar(thing, "WorldRef: [thing]") + + DoSearchVar(GLOB) //globals + for(var/datum/thing in world) //atoms (don't beleive it's lies) + DoSearchVar(thing, "World -> [thing]") + + for (var/datum/thing) //datums + DoSearchVar(thing, "World -> [thing]") + + for (var/client/thing) //clients + DoSearchVar(thing, "World -> [thing]") + testing("Completed search for references to a [type].") if(usr && usr.client) usr.client.running_find_references = null @@ -384,35 +392,44 @@ SUBSYSTEM_DEF(garbage) if(!running_find_references) find_references(TRUE) -/datum/proc/DoSearchVar(X, Xname) +/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) if(usr && usr.client && !usr.client.running_find_references) return + if (!recursive_limit) + return + if(istype(X, /datum)) var/datum/D = X if(D.last_find_references == last_find_references) return + D.last_find_references = last_find_references - for(var/V in D.vars) - for(var/varname in D.vars) - var/variable = D.vars[varname] - if(variable == src) - testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") - else if(islist(variable)) - if(src in variable) - testing("Found [src.type] \ref[src] in [D.type]'s [varname] list var. Global: [Xname]") -#ifdef GC_FAILURE_HARD_LOOKUP - for(var/I in variable) - DoSearchVar(I, TRUE) - else - DoSearchVar(variable, "[Xname]: [varname]") -#endif + var/list/L = D.vars + + for(var/varname in L) + if (varname == "vars") + continue + var/variable = L[varname] + + if(variable == src) + testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") + + else if(islist(variable)) + DoSearchVar(variable, "[Xname] -> list", recursive_limit-1) + else if(islist(X)) - if(src in X) - testing("Found [src.type] \ref[src] in list [Xname].") -#ifdef GC_FAILURE_HARD_LOOKUP + var/normal = IS_NORMAL_LIST(X) for(var/I in X) - DoSearchVar(I, Xname + ": list") -#else + if (I == src) + testing("Found [src.type] \ref[src] in list [Xname].") + + else if (I && !isnum(I) && normal && X[I] == src) + testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]") + + else if (islist(I)) + DoSearchVar(I, "[Xname] -> list", recursive_limit-1) + +#ifndef FIND_REF_NO_CHECK_TICK CHECK_TICK #endif