diff --git a/code/__DEFINES/stat_tracking.dm b/code/__DEFINES/stat_tracking.dm new file mode 100644 index 0000000000..d7d207469d --- /dev/null +++ b/code/__DEFINES/stat_tracking.dm @@ -0,0 +1,17 @@ +#define STAT_ENTRY_TIME 1 +#define STAT_ENTRY_COUNT 2 +#define STAT_ENTRY_LENGTH 2 + + +#define STAT_START_STOPWATCH var/STAT_STOP_WATCH = TICK_USAGE +#define STAT_STOP_STOPWATCH var/STAT_TIME = TICK_USAGE_TO_MS(STAT_STOP_WATCH) +#define STAT_LOG_ENTRY(entrylist, entryname) \ + var/list/STAT_ENTRY = entrylist[entryname] || (entrylist[entryname] = new /list(STAT_ENTRY_LENGTH));\ + STAT_ENTRY[STAT_ENTRY_TIME] += STAT_TIME;\ + var/STAT_INCR_AMOUNT = min(1, 2**round((STAT_ENTRY[STAT_ENTRY_COUNT] || 0)/SHORT_REAL_LIMIT));\ + if (STAT_INCR_AMOUNT == 1 || prob(100/STAT_INCR_AMOUNT)) {\ + STAT_ENTRY[STAT_ENTRY_COUNT] += STAT_INCR_AMOUNT;\ + };\ + + + diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 247e1109f8..b8579e7dbe 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -76,3 +76,27 @@ #define RUNLEVEL_POSTGAME 8 #define RUNLEVELS_DEFAULT (RUNLEVEL_SETUP | RUNLEVEL_GAME | RUNLEVEL_POSTGAME) + + + + +#define COMPILE_OVERLAYS(A)\ + if (TRUE) {\ + var/list/oo = A.our_overlays;\ + var/list/po = A.priority_overlays;\ + if(LAZYLEN(po)){\ + if(LAZYLEN(oo)){\ + A.overlays = oo + po;\ + }\ + else{\ + A.overlays = po;\ + }\ + }\ + else if(LAZYLEN(oo)){\ + A.overlays = oo;\ + }\ + else{\ + A.overlays.Cut();\ + }\ + A.flags_1 &= ~OVERLAY_QUEUED_1;\ + } \ No newline at end of file diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index a939ab7e90..3831349536 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -58,7 +58,12 @@ GLOBAL_VAR_INIT(cmp_field, "name") . = B.failures - A.failures if (!.) . = B.qdels - A.qdels - + +/proc/cmp_generic_stat_item_time(list/A, list/B) + . = B[STAT_ENTRY_TIME] - A[STAT_ENTRY_TIME] + if (!.) + . = B[STAT_ENTRY_COUNT] - A[STAT_ENTRY_COUNT] + /proc/cmp_profile_avg_time_dsc(list/A, list/B) return (B[PROFILE_ITEM_TIME]/(B[PROFILE_ITEM_COUNT] || 1)) - (A[PROFILE_ITEM_TIME]/(A[PROFILE_ITEM_COUNT] || 1)) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index b55ec948b8..6b014efd6a 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -1006,23 +1006,26 @@ GLOBAL_LIST_EMPTY(friendly_animal_types) if(J) J.equip(body, TRUE, FALSE) - SSoverlays.Flush() var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") body.setDir(NORTH) + COMPILE_OVERLAYS(body) var/icon/partial = getFlatIcon(body) out_icon.Insert(partial,dir=NORTH) body.setDir(SOUTH) + COMPILE_OVERLAYS(body) partial = getFlatIcon(body) out_icon.Insert(partial,dir=SOUTH) body.setDir(WEST) + COMPILE_OVERLAYS(body) partial = getFlatIcon(body) out_icon.Insert(partial,dir=WEST) body.setDir(EAST) + COMPILE_OVERLAYS(body) partial = getFlatIcon(body) out_icon.Insert(partial,dir=EAST) diff --git a/code/__HELPERS/stat_tracking.dm b/code/__HELPERS/stat_tracking.dm new file mode 100644 index 0000000000..007cd2695d --- /dev/null +++ b/code/__HELPERS/stat_tracking.dm @@ -0,0 +1,13 @@ +/proc/render_stats(list/stats, user, sort = /proc/cmp_generic_stat_item_time) + sortTim(stats, sort, TRUE) + + var/list/lines = list() + + for (var/entry in stats) + var/list/data = stats[entry] + lines += "[entry] => [num2text(data[STAT_ENTRY_TIME], 10)]ms ([data[STAT_ENTRY_COUNT]]) (avg:[num2text(data[STAT_ENTRY_TIME]/(data[STAT_ENTRY_COUNT] || 1), 99)])" + + if (user) + user << browse("
  1. [lines.Join("
  2. ")]
", "window=[url_encode("stats:[REF(stats)]")]") + + . = lines.Join("\n") diff --git a/code/controllers/subsystem/processing/overlays.dm b/code/controllers/subsystem/overlays.dm similarity index 80% rename from code/controllers/subsystem/processing/overlays.dm rename to code/controllers/subsystem/overlays.dm index d7f260be0e..498890d430 100644 --- a/code/controllers/subsystem/processing/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -1,4 +1,4 @@ -PROCESSING_SUBSYSTEM_DEF(overlays) +SUBSYSTEM_DEF(overlays) name = "Overlay" flags = SS_TICKER wait = 1 @@ -6,62 +6,63 @@ PROCESSING_SUBSYSTEM_DEF(overlays) init_order = INIT_ORDER_OVERLAY runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_SETUP - stat_tag = "Ov" - currentrun = null + var/list/queue + var/list/stats var/list/overlay_icon_state_caches var/list/overlay_icon_cache var/initialized = FALSE -/datum/controller/subsystem/processing/overlays/PreInit() - LAZYINITLIST(overlay_icon_state_caches) - LAZYINITLIST(overlay_icon_cache) +/datum/controller/subsystem/overlays/PreInit() + overlay_icon_state_caches = list() + overlay_icon_cache = list() + queue = list() + stats = list() -/datum/controller/subsystem/processing/overlays/Initialize() +/datum/controller/subsystem/overlays/Initialize() initialized = TRUE - Flush() + fire(mc_check = FALSE) ..() -/datum/controller/subsystem/processing/overlays/Recover() + +/datum/controller/subsystem/overlays/stat_entry() + ..("Ov:[length(queue)]") + + +/datum/controller/subsystem/overlays/Shutdown() + text2file("[GLOB.log_directory]/overlay.log", render_stats(stats)) + + +/datum/controller/subsystem/overlays/Recover() overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches overlay_icon_cache = SSoverlays.overlay_icon_cache - processing = SSoverlays.processing + queue = SSoverlays.queue -#define COMPILE_OVERLAYS(A)\ - var/list/oo = A.our_overlays;\ - var/list/po = A.priority_overlays;\ - if(LAZYLEN(po)){\ - if(LAZYLEN(oo)){\ - A.overlays = oo + po;\ - }\ - else{\ - A.overlays = po;\ - }\ - }\ - else if(LAZYLEN(oo)){\ - A.overlays = oo;\ - }\ - else{\ - A.overlays.Cut();\ - }\ - A.flags_1 &= ~OVERLAY_QUEUED_1 -/datum/controller/subsystem/processing/overlays/fire(resumed = FALSE, mc_check = TRUE) - var/list/processing = src.processing - while(processing.len) - var/atom/thing = processing[processing.len] - processing.len-- +/datum/controller/subsystem/overlays/fire(resumed = FALSE, mc_check = TRUE) + var/list/queue = src.queue + var/static/count = 0 + if (count) + var/c = count + count = 0 //so if we runtime on the Cut, we don't try again. + queue.Cut(1,c+1) + + for (var/thing in queue) + count++ if(thing) - COMPILE_OVERLAYS(thing) + STAT_START_STOPWATCH + var/atom/A = thing + COMPILE_OVERLAYS(A) + STAT_STOP_STOPWATCH + STAT_LOG_ENTRY(stats, A.type) if(mc_check) if(MC_TICK_CHECK) break else CHECK_TICK -/datum/controller/subsystem/processing/overlays/proc/Flush() - if(processing.len) - testing("Flushing [processing.len] overlays") - fire(mc_check = FALSE) //pair this thread up with the MC to get extra compile time + if (count) + queue.Cut(1,count+1) + count = 0 /proc/iconstate2appearance(icon, iconstate) var/static/image/stringbro = new() @@ -102,6 +103,10 @@ PROCESSING_SUBSYSTEM_DEF(overlays) else if(isicon(overlay)) new_overlays += icon2appearance(overlay) else + if(isloc(overlay)) + var/atom/A = overlay + if (A.flags_1 & OVERLAY_QUEUED_1) + COMPILE_OVERLAYS(A) appearance_bro.appearance = overlay //this works for images and atoms too! if(!ispath(overlay)) var/image/I = overlay @@ -110,7 +115,7 @@ PROCESSING_SUBSYSTEM_DEF(overlays) return new_overlays #define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1)) -#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.processing += src; +#define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src; /atom/proc/cut_overlays(priority = FALSE) var/list/cached_overlays = our_overlays var/list/cached_priority = priority_overlays diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index ae7f73be8f..200443b1fa 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -281,8 +281,6 @@ SUBSYSTEM_DEF(ticker) collect_minds() equip_characters() - SSoverlays.Flush() //Flush the majority of the shit - GLOB.data_core.manifest() transfer_characters() //transfer keys to the new mobs diff --git a/code/game/atoms.dm b/code/game/atoms.dm index f17905b5be..e450c54c1b 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -99,7 +99,6 @@ LAZYCLEARLIST(overlays) LAZYCLEARLIST(priority_overlays) - //SSoverlays.processing -= src //we COULD do this, but it's better to just let it fall out of the processing queue QDEL_NULL(light) diff --git a/code/game/world.dm b/code/game/world.dm index 026d7324e4..9132f3cd6d 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -124,7 +124,7 @@ GLOBAL_PROTECT(security_mode) if(I in input) handler = topic_handlers[I] break - + if((!handler || initial(handler.log)) && config && CONFIG_GET(flag/log_world_topic)) WRITE_FILE(GLOB.world_game_log, "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]") diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 01f825492f..56ae734044 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -156,7 +156,8 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug()) /client/proc/toggle_medal_disable, /client/proc/view_runtimes, /client/proc/pump_random_event, - /client/proc/cmd_display_init_log + /client/proc/cmd_display_init_log, + /client/proc/cmd_display_overlay_log ) GLOBAL_PROTECT(admin_verbs_possess) GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release)) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 9371792683..73965d52ad 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -778,6 +778,13 @@ GLOBAL_PROTECT(LastAdminCalledProc) usr << browse(dellog.Join(), "window=dellog") +/client/proc/cmd_display_overlay_log() + set category = "Debug" + set name = "Display overlay Log" + set desc = "Display SSoverlays log of everything that's passed through it." + + render_stats(SSoverlays.stats, src) + /client/proc/cmd_display_init_log() set category = "Debug" set name = "Display Initialize() Log" diff --git a/tgstation.dme b/tgstation.dme index 7c14107f36..33de1cae2b 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -75,6 +75,7 @@ #include "code\__DEFINES\sight.dm" #include "code\__DEFINES\sound.dm" #include "code\__DEFINES\stat.dm" +#include "code\__DEFINES\stat_tracking.dm" #include "code\__DEFINES\status_effects.dm" #include "code\__DEFINES\subsystems.dm" #include "code\__DEFINES\tgui.dm" @@ -105,6 +106,7 @@ #include "code\__HELPERS\radio.dm" #include "code\__HELPERS\sanitize_values.dm" #include "code\__HELPERS\shell.dm" +#include "code\__HELPERS\stat_tracking.dm" #include "code\__HELPERS\text.dm" #include "code\__HELPERS\text_vr.dm" #include "code\__HELPERS\time.dm" @@ -245,6 +247,7 @@ #include "code\controllers\subsystem\mobs.dm" #include "code\controllers\subsystem\npcpool.dm" #include "code\controllers\subsystem\orbit.dm" +#include "code\controllers\subsystem\overlays.dm" #include "code\controllers\subsystem\pai.dm" #include "code\controllers\subsystem\parallax.dm" #include "code\controllers\subsystem\persistence.dm" @@ -269,7 +272,6 @@ #include "code\controllers\subsystem\processing\fields.dm" #include "code\controllers\subsystem\processing\flightpacks.dm" #include "code\controllers\subsystem\processing\obj.dm" -#include "code\controllers\subsystem\processing\overlays.dm" #include "code\controllers\subsystem\processing\processing.dm" #include "code\controllers\subsystem\processing\projectiles.dm" #include "code\datums\action.dm"