Adds "fast" reference tracking (#95333)

## About The Pull Request

Port of "fast" reftracking from
https://github.com/Monkestation/Monkestation2.0/pull/6893

This adds a `FAST_REFERENCE_TRACKING` define, which makes it so the
reftracker will completely skip over specific types - if my math is
right, on icebox, it will need to scan **1.1+ million fewer items**
compared to normally (stats based on me using Count Atoms/Datums on an
icebox manuel round)

it's still the reftracker, so it's still not magically super speedy now
- it's only enabled by default when `REFERENCE_DOING_IT_LIVE` is set,
you shouldn't really use this locally or in CI.

## Why It's Good For The Game

hopefully makes running reftracker on live less hellish of an experience

## Changelog

No player-facing changes.
This commit is contained in:
Lucy
2026-03-08 22:05:35 -07:00
committed by GitHub
parent 70a716fc8e
commit 1564c1234f
2 changed files with 77 additions and 0 deletions
@@ -1,6 +1,65 @@
#ifdef REFERENCE_TRACKING
#define REFSEARCH_RECURSE_LIMIT 64
#ifdef FAST_REFERENCE_TRACKING
// typecache of types that almost certainly have no refs, and thus can be safely skipped when finding references
GLOBAL_ALIST_INIT(reftracker_skip_typecache, init_reftracker_skip_typecache())
// empty alist we swap with GLOB.reftracker_skip_typecache whenever someone calls toggle_fast_reftracking
GLOBAL_ALIST_EMPTY(reftracker_skip_typecache_b)
/proc/toggle_fast_reftracking()
var/alist/a = GLOB.reftracker_skip_typecache
var/alist/b = GLOB.reftracker_skip_typecache_b
GLOB.reftracker_skip_typecache = b
GLOB.reftracker_skip_typecache_b = a
/proc/init_reftracker_skip_typecache()
. = alist()
for(var/base_type in list(
/icon,
/matrix,
/regex,
/atom/movable/mirage_holder,
/atom/movable/render_step/emissive_blocker,
/datum/armor,
/datum/asset_cache_item,
/datum/book_info,
/datum/card,
/datum/chat_payload,
/datum/comm_log_entry,
/datum/gas_mixture,
/datum/greyscale_layer,
/datum/icon_transformer,
/datum/instrument_key,
/datum/lighting_object, // only contains turf and MA refs
/datum/movespeed_modifier,
/datum/painting,
/datum/paper_input,
/datum/physiology,
/datum/plant_gene/reagent,
/datum/qdel_item,
/datum/stack_recipe,
/datum/tlv,
/datum/universal_icon,
/datum/weakref,
/datum/z_pillar,
/obj/effect/abstract/z_holder,
// stuff below isn't 100% guaranteed to be ref-free, but they're prolly not an issue
/turf/closed/mineral,
/turf/open/lava,
/turf/open/misc/asteroid,
/turf/open/openspace,
/turf/open/space,
/obj/structure/flora, // icebox and such has a LOT of these
/datum/chatmessage,
/datum/lighting_corner,
/datum/log_entry, // hopefully nobody's silly enough to accidentally pass a reference to these... right???
/datum/reagent/consumable/nutriment,
))
for(var/type in typesof(base_type))
.[type] = TRUE
#endif
/datum/proc/find_references(references_to_clear = INFINITY)
if(usr?.client)
if(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")
@@ -36,7 +95,15 @@
if(src.references_to_clear == 0)
return
#ifdef FAST_REFERENCE_TRACKING
var/alist/skip_types = GLOB.reftracker_skip_typecache
#endif
for(var/datum/thing in world) //atoms (don't beleive its lies)
#ifdef FAST_REFERENCE_TRACKING
if(skip_types[thing.type])
continue
#endif
DoSearchVar(thing, "World -> [thing.type]", starting_time)
if(src.references_to_clear == 0)
break
@@ -45,6 +112,10 @@
return
for(var/datum/thing) //datums
#ifdef FAST_REFERENCE_TRACKING
if(skip_types[thing.type])
continue
#endif
DoSearchVar(thing, "Datums -> [thing.type]", starting_time)
if(src.references_to_clear == 0)
break