mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-28 07:38:05 +01:00
Optimizes qdel related things (slight init time savings) (#70729)
* Moves spawners and decals to a different init/delete scheme Rather then fully creating and then immediately deleting these things, we instead do the bare minimum. This is faster, if in theory more fragile. We should be safe since any errors should be caught in compile since this is very close to a "static" action. It does mean these atoms cannot use signals, etc. * Potentially saves init time, mostly cleans up a silly pattern We use sleeps and INVOKE_ASYNC to ensure that handing back turfs doesn't block a space reservation, but this by nature consumes up to the threshold and a bit more of whatever working block we were in. This is silly. Should just be a subsystem, so I made it one, with support for awaiting its finish if you want to * Optimizes garbage/proc/Queue slightly Queue takes about 1.6 seconds to process 26k items right now. The MASSIVE majority of this time is spent on using \ref This is because \ref returns a string, and that string requires being inserted into the global cache of strings we store What I'm doing is caching the result of ANY \ref on the datum it's applied to. This ensures previous uses will never decay from the string tree. This saves about 0.2 seconds of init
This commit is contained in:
@@ -207,7 +207,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
var/type = D.type
|
||||
var/datum/qdel_item/I = items[type]
|
||||
|
||||
log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --")
|
||||
log_world("## TESTING: GC: -- [text_ref(D)] | [type] was unable to be GC'd --")
|
||||
#ifdef TESTING
|
||||
for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
|
||||
var/client/admin = c
|
||||
@@ -249,7 +249,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
HardDelete(D)
|
||||
return
|
||||
var/gctime = world.time
|
||||
var/refid = "\ref[D]"
|
||||
var/refid = text_ref(D)
|
||||
|
||||
D.gc_destroyed = gctime
|
||||
var/list/queue = queues[level]
|
||||
@@ -261,7 +261,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
++delslasttick
|
||||
++totaldels
|
||||
var/type = D.type
|
||||
var/refID = "\ref[D]"
|
||||
var/refID = text_ref(D)
|
||||
|
||||
var/tick_usage = TICK_USAGE
|
||||
del(D)
|
||||
@@ -376,7 +376,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
D.find_references() //This breaks ci. Consider it insurance against somehow pring reftracking on accident
|
||||
if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object.
|
||||
SSgarbage.Queue(D)
|
||||
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
|
||||
SSgarbage.reference_find_on_fail[text_ref(D)] = TRUE
|
||||
#endif
|
||||
else
|
||||
#ifdef TESTING
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
SUBSYSTEM_DEF(mapping)
|
||||
name = "Mapping"
|
||||
init_order = INIT_ORDER_MAPPING
|
||||
flags = SS_NO_FIRE
|
||||
runlevels = ALL
|
||||
|
||||
var/list/nuke_tiles = list()
|
||||
var/list/nuke_threats = list()
|
||||
@@ -54,6 +54,8 @@ SUBSYSTEM_DEF(mapping)
|
||||
var/list/turf/unused_turfs = list() //Not actually unused turfs they're unused but reserved for use for whatever requests them. "[zlevel_of_turf]" = list(turfs)
|
||||
var/list/datum/turf_reservations //list of turf reservations
|
||||
var/list/used_turfs = list() //list of turf = datum/turf_reservation
|
||||
/// List of lists of turfs to reserve
|
||||
var/list/lists_to_reserve = list()
|
||||
|
||||
var/list/reservation_ready = list()
|
||||
var/clearing_reserved_turfs = FALSE
|
||||
@@ -149,6 +151,33 @@ SUBSYSTEM_DEF(mapping)
|
||||
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/datum/controller/subsystem/mapping/fire(resumed)
|
||||
// Cache for sonic speed
|
||||
var/list/unused_turfs = src.unused_turfs
|
||||
var/list/world_contents = GLOB.areas_by_type[world.area].contents
|
||||
var/list/lists_to_reserve = src.lists_to_reserve
|
||||
var/index = 0
|
||||
while(length(lists_to_reserve))
|
||||
var/list/packet = lists_to_reserve[index + 1]
|
||||
var/packetlen = length(packet)
|
||||
while(packetlen)
|
||||
if(MC_TICK_CHECK)
|
||||
lists_to_reserve.Cut(1, index)
|
||||
return
|
||||
var/turf/T = packet[packetlen]
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF
|
||||
world_contents += T
|
||||
packet.len--
|
||||
packetlen = length(packet)
|
||||
|
||||
index++
|
||||
// If we're here, we're done with that lad
|
||||
lists_to_reserve.len--
|
||||
lists_to_reserve.Cut(1, index)
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/calculate_default_z_level_gravities()
|
||||
for(var/z_level in 1 to length(z_list))
|
||||
calculate_z_level_gravity(z_level)
|
||||
@@ -646,15 +675,12 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
reservation_ready["[z]"] = TRUE
|
||||
clearing_reserved_turfs = FALSE
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs)
|
||||
for(var/i in turfs)
|
||||
var/turf/T = i
|
||||
T.empty(RESERVED_TURF_TYPE, RESERVED_TURF_TYPE, null, TRUE)
|
||||
LAZYINITLIST(unused_turfs["[T.z]"])
|
||||
unused_turfs["[T.z]"] |= T
|
||||
T.flags_1 |= UNUSED_RESERVATION_TURF
|
||||
GLOB.areas_by_type[world.area].contents += T
|
||||
CHECK_TICK
|
||||
/// Schedules a group of turfs to be handed back to the reservation system's control
|
||||
/// If await is true, will sleep until the turfs are finished work
|
||||
/datum/controller/subsystem/mapping/proc/reserve_turfs(list/turfs, await = FALSE)
|
||||
lists_to_reserve += list(turfs)
|
||||
if(await)
|
||||
UNTIL(!length(turfs))
|
||||
|
||||
//DO NOT CALL THIS PROC DIRECTLY, CALL wipe_reservations().
|
||||
/datum/controller/subsystem/mapping/proc/do_wipe_turf_reservations()
|
||||
@@ -672,7 +698,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
|
||||
unused_turfs.Cut()
|
||||
used_turfs.Cut()
|
||||
reserve_turfs(clearing)
|
||||
reserve_turfs(clearing, await = TRUE)
|
||||
|
||||
///Initialize all biomes, assoc as type || instance
|
||||
/datum/controller/subsystem/mapping/proc/initialize_biomes()
|
||||
|
||||
@@ -237,16 +237,16 @@ SUBSYSTEM_DEF(statpanels)
|
||||
list("CPU:", world.cpu),
|
||||
list("Instances:", "[num2text(world.contents.len, 10)]"),
|
||||
list("World Time:", "[world.time]"),
|
||||
list("Globals:", GLOB.stat_entry(), "\ref[GLOB]"),
|
||||
list("[config]:", config.stat_entry(), "\ref[config]"),
|
||||
list("Globals:", GLOB.stat_entry(), text_ref(GLOB)),
|
||||
list("[config]:", config.stat_entry(), text_ref(config)),
|
||||
list("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)"),
|
||||
list("Master Controller:", Master.stat_entry(), "\ref[Master]"),
|
||||
list("Failsafe Controller:", Failsafe.stat_entry(), "\ref[Failsafe]"),
|
||||
list("Master Controller:", Master.stat_entry(), text_ref(Master)),
|
||||
list("Failsafe Controller:", Failsafe.stat_entry(), text_ref(Failsafe)),
|
||||
list("","")
|
||||
)
|
||||
for(var/datum/controller/subsystem/sub_system as anything in Master.subsystems)
|
||||
mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), "\ref[sub_system]")
|
||||
mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", "\ref[GLOB.cameranet]")
|
||||
mc_data[++mc_data.len] = list("\[[sub_system.state_letter()]][sub_system.name]", sub_system.stat_entry(), text_ref(sub_system))
|
||||
mc_data[++mc_data.len] = list("Camera Net", "Cameras: [GLOB.cameranet.cameras.len] | Chunks: [GLOB.cameranet.chunks.len]", text_ref(GLOB.cameranet))
|
||||
|
||||
///immediately update the active statpanel tab of the target client
|
||||
/datum/controller/subsystem/statpanels/proc/immediate_send_stat_data(client/target)
|
||||
|
||||
@@ -505,8 +505,8 @@ SUBSYSTEM_DEF(timer)
|
||||
/datum/timedevent/proc/bucketJoin()
|
||||
// Generate debug-friendly name for timer
|
||||
var/static/list/bitfield_flags = list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")
|
||||
name = "Timer: [id] (\ref[src]), TTR: [timeToRun], wait:[wait] Flags: [jointext(bitfield_to_list(flags, bitfield_flags), ", ")], \
|
||||
callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), \
|
||||
name = "Timer: [id] ([text_ref(src)]), TTR: [timeToRun], wait:[wait] Flags: [jointext(bitfield_to_list(flags, bitfield_flags), ", ")], \
|
||||
callBack: [text_ref(callBack)], callBack.object: [callBack.object][text_ref(callBack.object)]([getcallingtype()]), \
|
||||
callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""]), source: [source]"
|
||||
|
||||
if (bucket_joined)
|
||||
|
||||
@@ -42,7 +42,7 @@ SUBSYSTEM_DEF(vis_overlays)
|
||||
else
|
||||
overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags)
|
||||
overlay.cache_expiration = -1
|
||||
var/cache_id = "\ref[overlay]@{[world.time]}"
|
||||
var/cache_id = "[text_ref(overlay)]@{[world.time]}"
|
||||
vis_overlay_cache[cache_id] = overlay
|
||||
. = overlay
|
||||
thing.vis_contents += overlay
|
||||
|
||||
Reference in New Issue
Block a user