From 16ca8ca7689c77e3606ea18b599cd777ecc663bb Mon Sep 17 00:00:00 2001 From: Kelenius Date: Thu, 6 Aug 2015 10:48:14 +0300 Subject: [PATCH] Optimizes garbage reference searcher --- code/controllers/Processes/garbage.dm | 65 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/code/controllers/Processes/garbage.dm b/code/controllers/Processes/garbage.dm index 1f053a1186..9e9d3591b1 100644 --- a/code/controllers/Processes/garbage.dm +++ b/code/controllers/Processes/garbage.dm @@ -41,6 +41,31 @@ world/loop_checks = 0 var/checkRemain = max_checks_multiplier * schedule_interval var/maxDels = max_forcedel_multiplier * schedule_interval + #ifdef GC_FINDREF + var/list/searching = list() + for(var/refID in destroyed) // Reference search - before all deletions and for all at once + var/GCd_at_time = destroyed[refID] + if(GCd_at_time > time_to_kill) + break + var/atom/A = locate(refID) + if(A && A.gcDestroyed == GCd_at_time) + searching += A + if(searching.len >= checkRemain) + break + + for(var/atom/A in searching) + testing("GC: Searching references for [A] | [A.type]") + if(A.loc != null) + testing("GC: [A] | [A.type] is located in [A.loc] instead of null") + if(A.contents.len) + testing("GC: [A] | [A.type] has contents: [list2text(A.contents)]") + if(searching.len) + for(var/atom/D in world) + LookForRefs(D, searching) + for(var/datum/D) + LookForRefs(D, searching) + #endif + while(destroyed.len && --checkRemain >= 0) if(dels >= maxDels) #ifdef GC_DEBUG @@ -61,22 +86,6 @@ world/loop_checks = 0 if(A && A.gcDestroyed == GCd_at_time) // So if something else coincidently gets the same ref, it's not deleted by mistake // Something's still referring to the qdel'd object. Kill it. testing("GC: -- \ref[A] | [A.type] was unable to be GC'd and was deleted --") - #ifdef GC_FINDREF - var/found = 0 - if(A.loc != null) - testing("GC: [A] | [A.type] is located in [A.loc] instead of null") - var/searched = "/atom" - for(var/atom/D in world) - found += LookForRef(D, A) - if(!found) - searched = "/datum and /atom" - for(var/datum/D) - found += LookForRef(D, A) - if(!found) - testing("GC: Referencs to [A] | [A.type] not found, possibly in a global list, an object of an unsupported type, or an object that was deleted this gc cycle") - else - testing("GC: Found [found] reference\s to [A] | [A.type] in [searched] types") - #endif logging["[A.type]"]++ del(A) ++dels @@ -88,25 +97,29 @@ world/loop_checks = 0 destroyed.Cut(1, 2) #ifdef GC_FINDREF -/datum/controller/process/garbage_collector/proc/LookForRef(var/datum/D, var/atom/targ) +/datum/controller/process/garbage_collector/proc/LookForRefs(var/datum/D, var/list/targ) . = 0 for(var/V in D.vars) if(V == "contents") continue - if(D.vars[V] == targ) - testing("GC: [targ] | [targ.type] referenced by [D] | [D.type], var [V]") - . += 1 + if(istype(D.vars[V], /atom)) + for(var/atom/A in targ) + if(D.vars[V] == A) + testing("GC: [A] | [A.type] referenced by [D] | [D.type], var [V]") + . += 1 else if(islist(D.vars[V])) - . += LookForListRef(D.vars[V], targ, D, V) + . += LookForListRefs(D.vars[V], targ, D, V) -/datum/controller/process/garbage_collector/proc/LookForListRef(var/list/L, var/atom/targ, var/datum/D, var/V) +/datum/controller/process/garbage_collector/proc/LookForListRefs(var/list/L, var/list/targ, var/datum/D, var/V) . = 0 for(var/F in L) - if(F == targ) - testing("GC: [targ] | [targ.type] referenced by [D] | [D.type], list [V]") - . += 1 + if(istype(F, /atom)) + for(var/atom/A in targ) + if(F == A) + testing("GC: [A] | [A.type] referenced by [D] | [D.type], list [V]") + . += 1 if(islist(F)) - . += LookForListRef(F, targ, D, "[F] in list [V]") + . += LookForListRefs(F, targ, D, "[F] in list [V]") #endif /datum/controller/process/garbage_collector/proc/AddTrash(datum/A)