mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-07-17 10:57:19 +01:00
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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user