mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
Ports garbage collector improvements and bugfixes from tg
* Writes a log of qdel() problems in a condensed format at the end of each round - tgstation/tgstation/pull/26135 * Moves hard dels into their own proc so that it can be profiled more easily, and uses it for the various types. Includes bugfixes too * https://github.com/tgstation/tgstation/pull/26210 * https://github.com/tgstation/tgstation/pull/26570 * Fix a bug with qdeling non-datums - https://github.com/tgstation/tgstation/pull/27434 * Fix typo - https://github.com/tgstation/tgstation/pull/27730
This commit is contained in:
@@ -50,10 +50,28 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
|
msg += "TGR:[round((totalgcs/(totaldels+totalgcs))*100, 0.01)]%"
|
||||||
..(msg)
|
..(msg)
|
||||||
|
|
||||||
|
/datum/controller/subsystem/garbage/Shutdown()
|
||||||
|
//Adds the del() log to world.log in a format condensable by the runtime condenser found in tools
|
||||||
|
if(didntgc.len || sleptDestroy.len)
|
||||||
|
var/list/dellog = list()
|
||||||
|
for(var/path in didntgc)
|
||||||
|
dellog += "Path : [path] \n"
|
||||||
|
dellog += "Failures : [didntgc[path]] \n"
|
||||||
|
if(path in sleptDestroy)
|
||||||
|
dellog += "Sleeps : [sleptDestroy[path]] \n"
|
||||||
|
sleptDestroy -= path
|
||||||
|
for(var/path in sleptDestroy)
|
||||||
|
dellog += "Path : [path] \n"
|
||||||
|
dellog += "Sleeps : [sleptDestroy[path]] \n"
|
||||||
|
log_misc(dellog.Join())
|
||||||
|
|
||||||
/datum/controller/subsystem/garbage/fire()
|
/datum/controller/subsystem/garbage/fire()
|
||||||
HandleToBeQueued()
|
HandleToBeQueued()
|
||||||
if(state == SS_RUNNING)
|
if(state == SS_RUNNING)
|
||||||
HandleQueue()
|
HandleQueue()
|
||||||
|
|
||||||
|
if (state == SS_PAUSED) //make us wait again before the next run.
|
||||||
|
state = SS_RUNNING
|
||||||
|
|
||||||
//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
|
//If you see this proc high on the profile, what you are really seeing is the garbage collection/soft delete overhead in byond.
|
||||||
//Don't attempt to optimize, not worth the effort.
|
//Don't attempt to optimize, not worth the effort.
|
||||||
@@ -98,24 +116,9 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
var/type = A.type
|
var/type = A.type
|
||||||
testing("GC: -- \ref[A] | [type] was unable to be GC'd and was deleted --")
|
testing("GC: -- \ref[A] | [type] was unable to be GC'd and was deleted --")
|
||||||
didntgc["[type]"]++
|
didntgc["[type]"]++
|
||||||
var/time = world.timeofday
|
|
||||||
var/tick = world.tick_usage
|
HardDelete(A)
|
||||||
var/ticktime = world.time
|
|
||||||
del(A)
|
|
||||||
tick = (world.tick_usage-tick+((world.time-ticktime)/world.tick_lag*100))
|
|
||||||
|
|
||||||
if (tick > highest_del_tickusage)
|
|
||||||
highest_del_tickusage = tick
|
|
||||||
time = world.timeofday - time
|
|
||||||
if (!time && TICK_DELTA_TO_MS(tick) > 1)
|
|
||||||
time = TICK_DELTA_TO_MS(tick)/100
|
|
||||||
if (time > highest_del_time)
|
|
||||||
highest_del_time = time
|
|
||||||
if (time > 10)
|
|
||||||
log_game("Error: [type]([refID]) took longer then 1 second to delete (took [time/10] seconds to delete)")
|
|
||||||
message_admins("Error: [type]([refID]) took longer then 1 second to delete (took [time/10] seconds to delete).")
|
|
||||||
postpone(time/5)
|
|
||||||
break
|
|
||||||
++delslasttick
|
++delslasttick
|
||||||
++totaldels
|
++totaldels
|
||||||
else
|
else
|
||||||
@@ -128,10 +131,10 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
A.gc_destroyed = GC_QUEUED_FOR_QUEUING
|
A.gc_destroyed = GC_QUEUED_FOR_QUEUING
|
||||||
|
|
||||||
/datum/controller/subsystem/garbage/proc/Queue(datum/A)
|
/datum/controller/subsystem/garbage/proc/Queue(datum/A)
|
||||||
if (!istype(A) || (!isnull(A.gc_destroyed) && A.gc_destroyed >= 0))
|
if (isnull(A) || (!isnull(A.gc_destroyed) && A.gc_destroyed >= 0))
|
||||||
return
|
return
|
||||||
if (A.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
|
if (A.gc_destroyed == GC_QUEUED_FOR_HARD_DEL)
|
||||||
del(A)
|
HardDelete(A)
|
||||||
return
|
return
|
||||||
var/gctime = world.time
|
var/gctime = world.time
|
||||||
var/refid = "\ref[A]"
|
var/refid = "\ref[A]"
|
||||||
@@ -143,6 +146,30 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
|
|
||||||
queue[refid] = gctime
|
queue[refid] = gctime
|
||||||
|
|
||||||
|
//this is purely to seperate things profile wise.
|
||||||
|
/datum/controller/subsystem/garbage/proc/HardDelete(datum/A)
|
||||||
|
var/time = world.timeofday
|
||||||
|
var/tick = world.tick_usage
|
||||||
|
var/ticktime = world.time
|
||||||
|
|
||||||
|
var/type = A.type
|
||||||
|
var/refID = "\ref[A]"
|
||||||
|
|
||||||
|
del(A)
|
||||||
|
|
||||||
|
tick = (world.tick_usage-tick+((world.time-ticktime)/world.tick_lag*100))
|
||||||
|
if (tick > highest_del_tickusage)
|
||||||
|
highest_del_tickusage = tick
|
||||||
|
time = world.timeofday - time
|
||||||
|
if (!time && TICK_DELTA_TO_MS(tick) > 1)
|
||||||
|
time = TICK_DELTA_TO_MS(tick)/100
|
||||||
|
if (time > highest_del_time)
|
||||||
|
highest_del_time = time
|
||||||
|
if (time > 10)
|
||||||
|
log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete)")
|
||||||
|
message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).")
|
||||||
|
postpone(time/5)
|
||||||
|
|
||||||
/datum/controller/subsystem/garbage/proc/HardQueue(datum/A)
|
/datum/controller/subsystem/garbage/proc/HardQueue(datum/A)
|
||||||
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
|
if (istype(A) && A.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
|
||||||
tobequeued += A
|
tobequeued += A
|
||||||
@@ -157,15 +184,13 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
// Should be treated as a replacement for the 'del' keyword.
|
// Should be treated as a replacement for the 'del' keyword.
|
||||||
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
|
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
|
||||||
/proc/qdel(datum/D, force=FALSE)
|
/proc/qdel(datum/D, force=FALSE)
|
||||||
if(!D)
|
if(!istype(D))
|
||||||
|
del(D)
|
||||||
return
|
return
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
SSgarbage.qdel_list += D.type
|
SSgarbage.qdel_list += D.type
|
||||||
#endif
|
#endif
|
||||||
if(!istype(D))
|
if(isnull(D.gc_destroyed))
|
||||||
log_debug("qdel() was passed [log_info_line(D)]. qdel() can only handle instances of (sub)type /datum.")
|
|
||||||
del(D)
|
|
||||||
else if(isnull(D.gc_destroyed))
|
|
||||||
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
D.gc_destroyed = GC_CURRENTLY_BEING_QDELETED
|
||||||
var/start_time = world.time
|
var/start_time = world.time
|
||||||
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
|
var/hint = D.Destroy(force) // Let our friend know they're about to get fucked up.
|
||||||
@@ -196,7 +221,7 @@ SUBSYSTEM_DEF(garbage)
|
|||||||
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
|
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
|
||||||
SSgarbage.HardQueue(D)
|
SSgarbage.HardQueue(D)
|
||||||
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
|
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
|
||||||
del(D)
|
SSgarbage.HardDelete(D)
|
||||||
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
|
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
|
||||||
SSgarbage.QueueForQueuing(D)
|
SSgarbage.QueueForQueuing(D)
|
||||||
#ifdef TESTING
|
#ifdef TESTING
|
||||||
|
|||||||
Reference in New Issue
Block a user