Skip to content

Commit

Permalink
Optimizes timer insertion by 80% (W QDEL_IN micro) (#76214)
Browse files Browse the repository at this point in the history
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

[Reduces timer insertion cost by
80%](c9e5b28)

Timer name generation involved a LOT of string shit, some in ways where
the string only existed for a moment.
This costs a good bit of time, and can be reduced with only minimal
impacts on the end product, so let's do that. Includes a compile flag to
flip it back if we ever have trouble in future.

This is about 0.1s off init, since we do a lot of timer stuff then too

[Removes STOPPABLE flag from QDEL_IN, moves it to a bespoke
macro](e7a5d7f)

Its a waste most of the time, tho I would LOVE to analyze at compile
time to work out if we care
## Why It's Good For The Game

I like it when we don't spend all of our cpu time just setting the name
var on timers. that's good and not bad.
This saves time fucking everywhere. 15% off explosions, 0.1 seconds off
init, bunch of time off foam. it's just good.

Cherry picked out of #76104 since that was too cluttered (sannnnnn)

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
  • Loading branch information
LemonInTheDark authored Jun 22, 2023
1 parent cf92862 commit a8e1603
Show file tree
Hide file tree
Showing 10 changed files with 27 additions and 10 deletions.
6 changes: 5 additions & 1 deletion code/__DEFINES/qdel.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@
#define QDELETED(X) (isnull(X) || QDELING(X))
#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)

#define QDEL_IN(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_STOPPABLE)
// This is a bit hacky, we do it to avoid people relying on a return value for the macro
// If you need that you should use QDEL_IN_STOPPABLE instead
#define QDEL_IN(item, time) ; \
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time);
#define QDEL_IN_STOPPABLE(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), (time) > GC_FILTER_QUEUE ? WEAKREF(item) : item), time, TIMER_STOPPABLE)
#define QDEL_IN_CLIENT_TIME(item, time) addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), item), time, TIMER_STOPPABLE | TIMER_CLIENT_TIME)
#define QDEL_NULL(item) qdel(item); item = null
#define QDEL_LIST(L) if(L) { for(var/I in L) qdel(I); L.Cut(); }
Expand Down
6 changes: 6 additions & 0 deletions code/_compile_options.dm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
// We do not ship byond-tracy. Build it yourself here: https://github.com/mafemergency/byond-tracy/
// #define USE_BYOND_TRACY

// If defined, we will compile with FULL timer debug info, rather then a limited scope
// Be warned, this increases timer creation cost by 5x
// #define TIMER_DEBUG

// If defined, we will NOT defer asset generation till later in the game, and will instead do it all at once, during initiialize
//#define DO_NOT_DEFER_ASSETS

Expand Down Expand Up @@ -124,6 +128,8 @@
#define GC_FAILURE_HARD_LOOKUP
//Ensures all early assets can actually load early
#define DO_NOT_DEFER_ASSETS
//Test at full capacity, the extra cost doesn't matter
#define TIMER_DEBUG
#endif

#ifdef TGS
Expand Down
9 changes: 8 additions & 1 deletion code/controllers/subsystem/timer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,18 @@ SUBSYSTEM_DEF(timer)
* If the timed event is tracking client time, it will be added to a special bucket.
*/
/datum/timedevent/proc/bucketJoin()
// Generate debug-friendly name for timer
#if defined(TIMER_DEBUG)
// Generate debug-friendly name for timer, more complex but also more expensive
var/static/list/bitfield_flags = list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT", "TIMER_LOOP")
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]"
#else
// Generate a debuggable name for the timer, simpler but wayyyy cheaper, string generation is a bitch and this saves a LOT of time
name = "Timer: [id] ([text_ref(src)]), TTR: [timeToRun], wait:[wait] Flags: [flags], \
callBack: [text_ref(callBack)], callBack.object: [callBack.object]([getcallingtype()]), \
callBack.delegate:[callBack.delegate], source: [source]"
#endif

if (bucket_joined)
stack_trace("Bucket already joined! [name]")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
if(randomdir)
setDir(pick(GLOB.cardinals))

timerid = QDEL_IN(src, duration)
timerid = QDEL_IN_STOPPABLE(src, duration)

/obj/effect/temp_visual/Destroy()
. = ..()
Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/implants/implant_track.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

/obj/item/implant/tracking/c38/implant(mob/living/target, mob/user, silent, force)
. = ..()
timerid = QDEL_IN(src, lifespan)
timerid = QDEL_IN_STOPPABLE(src, lifespan)

/obj/item/implant/tracking/c38/removed(mob/living/source, silent, special)
. = ..()
Expand Down
4 changes: 2 additions & 2 deletions code/modules/hallucination/body.dm
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@

/datum/hallucination/body/staticguy/queue_cleanup()
RegisterSignal(hallucinator, COMSIG_MOVABLE_MOVED, PROC_REF(on_move))
del_timerid = QDEL_IN(src, rand(2 MINUTES, 3 MINUTES))
del_timerid = QDEL_IN_STOPPABLE(src, rand(2 MINUTES, 3 MINUTES))
return TRUE

/// Signal proc for [COMSIG_MOVABLE_MOVED] - if we move out of view of the hallucination, it disappears, how spooky
Expand All @@ -110,7 +110,7 @@
if(shown_body.loc == hallucinator.loc)
animate(shown_body, alpha = 0, time = 0.5 SECONDS)
deltimer(del_timerid)
del_timerid = QDEL_IN(src, 0.6 SECONDS)
del_timerid = QDEL_IN_STOPPABLE(src, 0.6 SECONDS)
return

// Staying in view will do nothing
Expand Down
2 changes: 1 addition & 1 deletion code/modules/hallucination/fake_alert.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
override = TRUE,
)

del_timer_id = QDEL_IN(src, duration)
del_timer_id = QDEL_IN_STOPPABLE(src, duration)
return TRUE

/datum/hallucination/fake_alert/need_oxygen
Expand Down
2 changes: 1 addition & 1 deletion code/modules/hallucination/screwy_health_doll.dm
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
return FALSE

add_fake_limb()
del_timer_id = QDEL_IN(src, duration)
del_timer_id = QDEL_IN_STOPPABLE(src, duration)
return TRUE

/// Increments the severity of the damage seen on all the limbs we are already tracking.
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mafia/controller.dm
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ GLOBAL_LIST_INIT(mafia_role_by_alignment, setup_mafia_role_by_alignment())
roles.mafia_alert.update_text("[message]")
roles.reveal_role(src)
phase = MAFIA_PHASE_VICTORY_LAP
next_phase_timer = QDEL_IN(src, VICTORY_LAP_PERIOD_LENGTH)
next_phase_timer = QDEL_IN_STOPPABLE(src, VICTORY_LAP_PERIOD_LENGTH)

/**
* Cleans up the game, resetting variables back to the beginning and removing the map with the generator.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
/obj/effect/temp_visual/goliath_tentacle/proc/retract()
icon_state = "goliath_tentacle_retract"
deltimer(timerid)
timerid = QDEL_IN(src, 7)
timerid = QDEL_IN_STOPPABLE(src, 7)

/obj/item/saddle
name = "saddle"
Expand Down

0 comments on commit a8e1603

Please sign in to comment.