Updated SSgarbage (#18173)

* pain

* sadfas

* sdfa

* sdfasf

* sfa

* sdf

* might the lord have mercy on our soul

* i cri everidai

* adeste fideles

* sdf

* where will this lead, what's coming next, from your inventions

* dear lord

* gjvhk

* i cri everidai

* fsgf

* sdfa

* sdaf

* hiuhi
This commit is contained in:
Fluffy
2024-01-15 15:08:27 +01:00
committed by GitHub
parent 0c8bdbdd68
commit ca6b04e1d7
125 changed files with 1574 additions and 805 deletions
+3
View File
@@ -218,6 +218,7 @@ var/list/admin_verbs_debug = list(
/client/proc/lighting_show_verbs,
/client/proc/restart_controller,
/client/proc/cmd_display_del_log,
/client/proc/cmd_display_harddel_log,
/client/proc/cmd_display_init_log,
/client/proc/cmd_ss_panic,
/client/proc/reset_openturf,
@@ -388,6 +389,7 @@ var/list/admin_verbs_hideable = list(
/client/proc/kill_air,
/client/proc/kill_airgroup,
/client/proc/cmd_display_del_log,
/client/proc/cmd_display_harddel_log,
/datum/admins/proc/ccannoucment,
/client/proc/cmd_display_init_log,
/client/proc/getruntimelog,
@@ -476,6 +478,7 @@ var/list/admin_verbs_dev = list( //will need to be altered - Ryan784
/client/proc/cmd_dev_bst,
/client/proc/lighting_show_verbs,
/client/proc/cmd_display_del_log,
/client/proc/cmd_display_harddel_log,
/client/proc/cmd_display_init_log,
/client/proc/create_poll, //Allows to create polls
/client/proc/profiler_start,
+70 -11
View File
@@ -421,21 +421,80 @@
/client/proc/cmd_display_del_log()
set category = "Debug"
set name = "Display del() Log"
set desc = "Displays a list of things that have failed to GC this round"
set desc = "Display del's log of everything that's passed through it."
var/dat = "<B>List of things that failed to GC this round</B><BR><BR>"
for(var/path in SSgarbage.didntgc)
dat += "[path] - [SSgarbage.didntgc[path]] times<BR>"
var/list/dellog = list("<B>List of things that have gone through qdel this round</B><BR><BR><ol>")
sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in SSgarbage.items)
var/datum/qdel_item/I = SSgarbage.items[path]
dellog += "<li><u>[path]</u><ul>"
if (I.qdel_flags & QDEL_ITEM_SUSPENDED_FOR_LAG)
dellog += "<li>SUSPENDED FOR LAG</li>"
if (I.failures)
dellog += "<li>Failures: [I.failures]</li>"
dellog += "<li>qdel() Count: [I.qdels]</li>"
dellog += "<li>Destroy() Cost: [I.destroy_time]ms</li>"
if (I.hard_deletes)
dellog += "<li>Total Hard Deletes [I.hard_deletes]</li>"
dellog += "<li>Time Spent Hard Deleting: [I.hard_delete_time]ms</li>"
dellog += "<li>Highest Time Spent Hard Deleting: [I.hard_delete_max]ms</li>"
if (I.hard_deletes_over_threshold)
dellog += "<li>Hard Deletes Over Threshold: [I.hard_deletes_over_threshold]</li>"
if (I.slept_destroy)
dellog += "<li>Sleeps: [I.slept_destroy]</li>"
if (I.no_respect_force)
dellog += "<li>Ignored force: [I.no_respect_force]</li>"
if (I.no_hint)
dellog += "<li>No hint: [I.no_hint]</li>"
if(LAZYLEN(I.extra_details))
var/details = I.extra_details.Join("</li><li>")
dellog += "<li>Extra Info: <ul><li>[details]</li></ul>"
dellog += "</ul></li>"
dat += "<B>List of paths that did not return a qdel hint in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.noqdelhint)
dat += "[path]<BR>"
dellog += "</ol>"
dat += "<B>List of paths that slept in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.sleptDestroy)
dat += "[path]<BR>"
usr << browse(dellog.Join(), "window=dellog")
usr << browse(dat, "window=dellog")
/**
* Same as `cmd_display_del_log`, but only shows harddels
*/
/client/proc/cmd_display_harddel_log()
set category = "Debug"
set name = "Display harddel() Log"
set desc = "Display harddel's log."
var/list/dellog = list("<B>List of things that have harddel'd this round</B><BR><BR><ol>")
sortTim(SSgarbage.items, cmp=/proc/cmp_qdel_item_time, associative = TRUE)
for(var/path in SSgarbage.items)
var/datum/qdel_item/I = SSgarbage.items[path]
if(I.hard_deletes)
dellog += "<li><u>[path]</u><ul>"
if (I.qdel_flags & QDEL_ITEM_SUSPENDED_FOR_LAG)
dellog += "<li>SUSPENDED FOR LAG</li>"
if (I.failures)
dellog += "<li>Failures: [I.failures]</li>"
dellog += "<li>qdel() Count: [I.qdels]</li>"
dellog += "<li>Destroy() Cost: [I.destroy_time]ms</li>"
if (I.hard_deletes)
dellog += "<li>Total Hard Deletes [I.hard_deletes]</li>"
dellog += "<li>Time Spent Hard Deleting: [I.hard_delete_time]ms</li>"
dellog += "<li>Highest Time Spent Hard Deleting: [I.hard_delete_max]ms</li>"
if (I.hard_deletes_over_threshold)
dellog += "<li>Hard Deletes Over Threshold: [I.hard_deletes_over_threshold]</li>"
if (I.slept_destroy)
dellog += "<li>Sleeps: [I.slept_destroy]</li>"
if (I.no_respect_force)
dellog += "<li>Ignored force: [I.no_respect_force]</li>"
if (I.no_hint)
dellog += "<li>No hint: [I.no_hint]</li>"
if(LAZYLEN(I.extra_details))
var/details = I.extra_details.Join("</li><li>")
dellog += "<li>Extra Info: <ul><li>[details]</li></ul>"
dellog += "</ul></li>"
dellog += "</ol>"
usr << browse(dellog.Join(), "window=harddellog")
/client/proc/cmd_display_init_log()
set category = "Debug"
@@ -0,0 +1,170 @@
#ifdef REFERENCE_TRACKING
/datum/proc/find_references(skip_alert)
running_find_references = type
if(usr?.client)
if(usr.client.running_find_references)
log_subsystem_garbage_harddel("CANCELLED search for references to a [usr.client.running_find_references].")
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = TRUE
SSgarbage.update_nextfire(reset_time = TRUE)
return
if(!skip_alert && tgui_alert(usr,"Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", list("Yes", "No")) != "Yes")
running_find_references = null
return
//this keeps the garbage collector from failing to collect objects being searched for in here
SSgarbage.can_fire = FALSE
if(usr?.client)
usr.client.running_find_references = type
log_subsystem_garbage_harddel("Beginning search for references to a [type].")
var/starting_time = world.time
log_subsystem_garbage_harddel("Refcount for [type]: [refcount(src)]")
//Time to search the whole game for our ref
DoSearchVar(GLOB, "GLOB", search_time = starting_time) //globals
log_subsystem_garbage_harddel("Finished searching globals")
//Yes we do actually need to do this. The searcher refuses to read weird lists
//And global.vars is a really weird list
var/global_vars = list()
for(var/key in global.vars)
global_vars[key] = global.vars[key]
DoSearchVar(global_vars, "Native Global", search_time = starting_time)
log_subsystem_garbage_harddel("Finished searching native globals")
for(var/datum/thing in world) //atoms (don't beleive its lies)
DoSearchVar(thing, "World -> [thing.type]", search_time = starting_time)
log_subsystem_garbage_harddel("Finished searching atoms")
for(var/datum/thing) //datums
DoSearchVar(thing, "Datums -> [thing.type]", search_time = starting_time)
log_subsystem_garbage_harddel("Finished searching datums")
//Warning, attempting to search clients like this will cause crashes if done on live. Watch yourself
#ifndef REFERENCE_DOING_IT_LIVE
for(var/client/thing) //clients
DoSearchVar(thing, "Clients -> [thing.type]", search_time = starting_time)
log_subsystem_garbage_harddel("Finished searching clients")
#endif
log_subsystem_garbage_harddel("Completed search for references to a [type].")
if(usr?.client)
usr.client.running_find_references = null
running_find_references = null
//restart the garbage collector
SSgarbage.can_fire = TRUE
SSgarbage.update_nextfire(reset_time = TRUE)
/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64, search_time = world.time)
#ifdef REFERENCE_TRACKING_DEBUG
if(SSgarbage.should_save_refs && !found_refs)
found_refs = list()
#endif
if(usr?.client && !usr.client.running_find_references)
return
if(!recursive_limit)
log_subsystem_garbage_harddel("Recursion limit reached. [container_name]")
return
//Check each time you go down a layer. This makes it a bit slow, but it won't effect the rest of the game at all
#ifndef FIND_REF_NO_CHECK_TICK
CHECK_TICK
#endif
if(isdatum(potential_container))
var/datum/datum_container = potential_container
if(datum_container.last_find_references == search_time)
return
datum_container.last_find_references = search_time
var/container_print = datum_container.ref_search_details()
var/list/vars_list = datum_container.vars
for(var/varname in vars_list)
#ifndef FIND_REF_NO_CHECK_TICK
CHECK_TICK
#endif
if (varname == "vars" || varname == "vis_locs") //Fun fact, vis_locs don't count for references
continue
var/variable = vars_list[varname]
if(variable == src)
#ifdef REFERENCE_TRACKING_DEBUG
if(SSgarbage.should_save_refs)
found_refs[varname] = TRUE
continue //End early, don't want these logging
#endif
log_subsystem_garbage_harddel("Found [type] [text_ref(src)] in [datum_container.type]'s [container_print] [varname] var. [container_name]")
continue
if(islist(variable))
DoSearchVar(variable, "[container_name] [container_print] -> [varname] (list)", recursive_limit - 1, search_time)
else if(islist(potential_container))
var/normal = IS_NORMAL_LIST(potential_container)
var/list/potential_cache = potential_container
for(var/element_in_list in potential_cache)
#ifndef FIND_REF_NO_CHECK_TICK
CHECK_TICK
#endif
//Check normal entrys
if(element_in_list == src)
#ifdef REFERENCE_TRACKING_DEBUG
if(SSgarbage.should_save_refs)
found_refs[potential_cache] = TRUE
continue //End early, don't want these logging
#endif
log_subsystem_garbage_harddel("Found [type] [text_ref(src)] in list [container_name].")
continue
var/assoc_val = null
if(!isnum(element_in_list) && normal)
assoc_val = potential_cache[element_in_list]
//Check assoc entrys
if(assoc_val == src)
#ifdef REFERENCE_TRACKING_DEBUG
if(SSgarbage.should_save_refs)
found_refs[potential_cache] = TRUE
continue //End early, don't want these logging
#endif
log_subsystem_garbage_harddel("Found [type] [text_ref(src)] in list [container_name]\[[element_in_list]\]")
continue
//We need to run both of these checks, since our object could be hiding in either of them
//Check normal sublists
if(islist(element_in_list))
DoSearchVar(element_in_list, "[container_name] -> [element_in_list] (list)", recursive_limit - 1, search_time)
//Check assoc sublists
if(islist(assoc_val))
DoSearchVar(potential_container[element_in_list], "[container_name]\[[element_in_list]\] -> [assoc_val] (list)", recursive_limit - 1, search_time)
/proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE)
thing_to_del.qdel_and_find_ref_if_fail(force)
/datum/proc/qdel_and_find_ref_if_fail(force = FALSE)
SSgarbage.reference_find_on_fail[text_ref(src)] = TRUE
qdel(src, force)
#endif
// Kept outside the ifdef so overrides are easy to implement
/// Return info about us for reference searching purposes
/// Will be logged as a representation of this datum if it's a part of a search chain
/datum/proc/ref_search_details()
return text_ref(src)
/datum/callback/ref_search_details()
return "[text_ref(src)] (obj: [object] proc: [delegate] args: [json_encode(arguments)]" // Used to include `user: [user?.resolve() || "null"])` but dreamchecker no happy with non static ref