From 6a62a139a81bdaa674fb64c755163aaa378c81d1 Mon Sep 17 00:00:00 2001 From: AnturK Date: Fri, 10 Jan 2020 01:32:57 +0100 Subject: [PATCH] Basic auto profiler (#48672) * Basic auto profiler * Makes it update periodically in case of crash. * informative comment. * Early start & config upgrades. * Fixup --- code/__DEFINES/profile.dm | 4 +- code/__DEFINES/subsystems.dm | 1 + .../configuration/entries/general.dm | 1 + code/controllers/subsystem/profiler.dm | 50 +++++++++++++++++++ code/game/world.dm | 5 ++ code/modules/admin/verbs/debug.dm | 4 +- config/config.txt | 4 ++ tgstation.dme | 1 + 8 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 code/controllers/subsystem/profiler.dm diff --git a/code/__DEFINES/profile.dm b/code/__DEFINES/profile.dm index 3c9650876e2..5fc84789014 100644 --- a/code/__DEFINES/profile.dm +++ b/code/__DEFINES/profile.dm @@ -1,5 +1,5 @@ -#define PROFILE_START ;PROFILE_STORE = list();PROFILE_SET; -#define PROFILE_STOP ;PROFILE_STORE = null; +#define LINE_PROFILE_START ;PROFILE_STORE = list();PROFILE_SET; +#define LINE_PROFILE_STOP ;PROFILE_STORE = null; #define PROFILE_SET ;PROFILE_TIME = TICK_USAGE_REAL; PROFILE_LINE = __LINE__; PROFILE_FILE = __FILE__; PROFILE_SLEEPCHECK = world.time; diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 6907a153bd6..efd8a80e9e2 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -98,6 +98,7 @@ // Subsystems shutdown in the reverse of the order they initialize in // The numbers just define the ordering, they are meaningless otherwise. +#define INIT_ORDER_PROFILER 101 #define INIT_ORDER_TITLE 100 #define INIT_ORDER_GARBAGE 99 #define INIT_ORDER_DBCORE 95 diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index e8ff6697233..811937deb13 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -489,3 +489,4 @@ /datum/config_entry/flag/reopen_roundstart_suicide_roles_command_report +/datum/config_entry/flag/auto_profile diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm new file mode 100644 index 00000000000..2136f3cace0 --- /dev/null +++ b/code/controllers/subsystem/profiler.dm @@ -0,0 +1,50 @@ +#define PROFILER_FILENAME "profiler.json" + +SUBSYSTEM_DEF(profiler) + name = "Profiler" + init_order = INIT_ORDER_PROFILER + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + wait = 600 + +/datum/controller/subsystem/profiler/Initialize() + if(CONFIG_GET(flag/auto_profile)) + StartProfiling() + else + StopProfiling() //Stop the early start from world/New + return ..() + +/datum/controller/subsystem/profiler/fire() + if(CONFIG_GET(flag/auto_profile)) + DumpFile() + +/datum/controller/subsystem/profiler/Shutdown() + if(CONFIG_GET(flag/auto_profile)) + DumpFile() + return ..() + +/datum/controller/subsystem/profiler/proc/StartProfiling() +#if DM_BUILD < 1506 || DM_VERSION < 513 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else + world.Profile(PROFILE_START) +#endif + +/datum/controller/subsystem/profiler/proc/StopProfiling() +#if DM_BUILD >= 1506 && DM_VERSION >= 513 + world.Profile(PROFILE_STOP) +#endif + +/datum/controller/subsystem/profiler/proc/DumpFile() +#if DM_BUILD < 1506 || DM_VERSION < 513 + stack_trace("Auto profiling unsupported on this byond version") + CONFIG_SET(flag/auto_profile, FALSE) +#else + var/current_profile_data = world.Profile(PROFILE_REFRESH,format="json") + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/json_file = file("[GLOB.log_directory]/[PROFILER_FILENAME]") + if(fexists(json_file)) + fdel(json_file) + WRITE_FILE(json_file, current_profile_data) +#endif diff --git a/code/game/world.dm b/code/game/world.dm index 3746cad1d4a..322a77c7508 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -21,6 +21,11 @@ GLOBAL_VAR(restart_counter) /world/New() enable_debugger() + //Early profile for auto-profiler - will be stopped on profiler init if necessary. +#if DM_VERSION >= 513 && DM_BUILD >= 1506 + world.Profile(PROFILE_START) +#endif + log_world("World loaded at [time_stamp()]!") SetupExternalRSC() diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 3d05b4e1f60..799e26378ef 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -839,7 +839,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that set name = "Start Line Profiling" set desc = "Starts tracking line by line profiling for code lines that support it" - PROFILE_START + LINE_PROFILE_START message_admins("[key_name_admin(src)] started line by line profiling.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Line Profiling") @@ -850,7 +850,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that set name = "Stops Line Profiling" set desc = "Stops tracking line by line profiling for code lines that support it" - PROFILE_STOP + LINE_PROFILE_STOP message_admins("[key_name_admin(src)] stopped line by line profiling.") SSblackbox.record_feedback("tally", "admin_verb", 1, "Stop Line Profiling") diff --git a/config/config.txt b/config/config.txt index 58058c2c58d..4cd17022a6a 100644 --- a/config/config.txt +++ b/config/config.txt @@ -502,3 +502,7 @@ DEFAULT_VIEW 15x15 ## The alternative square viewport size if you're using a widescreen view size ## You probably shouldn't ever be changing this, but it's here if you want to. DEFAULT_VIEW_SQUARE 15x15 + + +## Enable automatic profiling - Byond 513.1506 and newer only. +#AUTO_PROFILE diff --git a/tgstation.dme b/tgstation.dme index ca23a270dfb..480b9d2d8b0 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -275,6 +275,7 @@ #include "code\controllers\subsystem\pathfinder.dm" #include "code\controllers\subsystem\persistence.dm" #include "code\controllers\subsystem\ping.dm" +#include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\radiation.dm" #include "code\controllers\subsystem\radio.dm" #include "code\controllers\subsystem\research.dm"