From 96aa691d9adc8e1c489728f232213f3d5b112ae2 Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Sun, 22 Jan 2017 23:00:39 -0800 Subject: [PATCH 1/3] Makes the timer subsystem less chinsky at the cost of performance Making timers run thru qdel will be a cost a pretty fair chunk of resources, and will very likely flood the qdel controller, but it should do for now until i figure out why they randomly decide to stop qdeling. Also, changes the only thing i think could be an issue causing references to not get cleaned up to be less lean and more forgiving. I'll revisit this at some point and see if i can't figure this out. --- code/controllers/subsystem/timer.dm | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 2bc6c40cfe8..b131489aa37 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -72,9 +72,7 @@ var/datum/subsystem/timer/SStimer do var/datum/callback/callBack = timer.callBack if (!callBack || timer.spent) - qdel(timer) - bucket_resolution = null //force bucket recreation - CRASH("Invalid timer: timer.timeToRun=[timer.timeToRun]||qdeleted(timer)=[qdeleted(timer)]||world.time=[world.time]||head_offset=[head_offset]||practical_offset=[practical_offset]||timer.spent=[timer.spent]") + continue spent += timer timer.spent = TRUE @@ -84,15 +82,7 @@ var/datum/subsystem/timer/SStimer timer = timer.next if (MC_TICK_CHECK) - if (!timer || timer == head) - break - if (head.prev) - head.prev.next = timer - if (timer.prev) - timer.prev.next = head - timer.prev = head.prev - bucket_list[practical_offset] = timer - break LOOP_OUTER + return while (timer && timer != head) bucket_list[practical_offset++] = null @@ -251,7 +241,7 @@ var/datum/subsystem/timer/SStimer if (flags & TIMER_CLIENT_TIME) SStimer.clienttime_timers -= src - return QDEL_HINT_IWILLGC + return QDEL_HINT_QUEUE if (flags & TIMER_STOPPABLE) SStimer.timer_id_dict -= "timerid[id]" @@ -286,7 +276,7 @@ var/datum/subsystem/timer/SStimer next.prev = null next = null prev = null - return QDEL_HINT_IWILLGC + return QDEL_HINT_QUEUE proc/addtimer(datum/callback/callback, wait, flags) if (!callback) From 9f2374f2209f8dfdb03d0070903eb742f0e4e627 Mon Sep 17 00:00:00 2001 From: Kyle Spier-Swenson Date: Mon, 23 Jan 2017 00:34:50 -0800 Subject: [PATCH 2/3] Fix warning --- code/controllers/subsystem/timer.dm | 51 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index b131489aa37..1e9e946dc84 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -60,34 +60,33 @@ var/datum/subsystem/timer/SStimer var/list/bucket_list = src.bucket_list var/static/list/spent = list() - LOOP_OUTER - while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK) - var/datum/timedevent/head = bucket_list[practical_offset] - if (!head) - practical_offset++ - if (MC_TICK_CHECK) - break - continue - var/datum/timedevent/timer = head - do - var/datum/callback/callBack = timer.callBack - if (!callBack || timer.spent) - continue - - spent += timer - timer.spent = TRUE - - callBack.InvokeAsync() - - timer = timer.next - - if (MC_TICK_CHECK) - return - while (timer && timer != head) - - bucket_list[practical_offset++] = null + while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK) + var/datum/timedevent/head = bucket_list[practical_offset] + if (!head) + practical_offset++ if (MC_TICK_CHECK) break + continue + var/datum/timedevent/timer = head + do + var/datum/callback/callBack = timer.callBack + if (!callBack || timer.spent) + continue + + spent += timer + timer.spent = TRUE + + callBack.InvokeAsync() + + timer = timer.next + + if (MC_TICK_CHECK) + return + while (timer && timer != head) + + bucket_list[practical_offset++] = null + if (MC_TICK_CHECK) + break bucket_count -= length(spent) From aad872455820906f198fde60d153f721c38fbc5f Mon Sep 17 00:00:00 2001 From: MrStonedOne Date: Tue, 24 Jan 2017 15:38:48 -0800 Subject: [PATCH 3/3] This is better (proper resuming support) --- code/controllers/subsystem/timer.dm | 66 +++++++++++++++++------------ 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm index 1e9e946dc84..aa8b88757cc 100644 --- a/code/controllers/subsystem/timer.dm +++ b/code/controllers/subsystem/timer.dm @@ -39,59 +39,71 @@ var/datum/subsystem/timer/SStimer /datum/subsystem/timer/stat_entry(msg) ..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]") -/datum/subsystem/timer/fire() +/datum/subsystem/timer/fire(resumed = FALSE) if (length(clienttime_timers)) for (var/thing in clienttime_timers) - var/datum/timedevent/timer = thing - if (timer.spent) - qdel(timer) + var/datum/timedevent/ctime_timer = thing + if (ctime_timer.spent) + qdel(ctime_timer) continue - if (timer.timeToRun <= REALTIMEOFDAY) - var/datum/callback/callBack = timer.callBack - timer.spent = TRUE + if (ctime_timer.timeToRun <= REALTIMEOFDAY) + var/datum/callback/callBack = ctime_timer.callBack + ctime_timer.spent = TRUE callBack.InvokeAsync() - qdel(timer) + qdel(ctime_timer) if (MC_TICK_CHECK) return - if (head_offset + (world.tick_lag * BUCKET_LEN) < world.time || length(src.bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution) + var/static/list/spent = list() + var/static/datum/timedevent/timer + var/static/datum/timedevent/head + + if ((practical_offset > BUCKET_LEN * 0.75 && (head_offset + (world.tick_lag * BUCKET_LEN) < world.time)) || length(src.bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution) shift_buckets() + resumed = FALSE + + if (!resumed) + timer = null + head = null var/list/bucket_list = src.bucket_list - var/static/list/spent = list() + while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK) - var/datum/timedevent/head = bucket_list[practical_offset] - if (!head) - practical_offset++ - if (MC_TICK_CHECK) - break - continue - var/datum/timedevent/timer = head + if (!timer || !head || timer == head) + head = bucket_list[practical_offset] + if (!head) + practical_offset++ + if (MC_TICK_CHECK) + break + continue + timer = head do var/datum/callback/callBack = timer.callBack - if (!callBack || timer.spent) - continue + if (!callBack) + qdel(timer) + bucket_resolution = null //force bucket recreation + CRASH("Invalid timer: timer.timeToRun=[timer.timeToRun]||qdeleted(timer)=[qdeleted(timer)]||world.time=[world.time]||head_offset=[head_offset]||practical_offset=[practical_offset]||timer.spent=[timer.spent]") - spent += timer - timer.spent = TRUE - - callBack.InvokeAsync() + if (!timer.spent) + spent += timer + timer.spent = TRUE + callBack.InvokeAsync() timer = timer.next if (MC_TICK_CHECK) return while (timer && timer != head) - + timer = null bucket_list[practical_offset++] = null if (MC_TICK_CHECK) - break + return bucket_count -= length(spent) - for (var/timer in spent) - qdel(timer) + for (var/spent_timer in spent) + qdel(spent_timer) spent.len = 0