diff --git a/code/__DEFINES/show_message.dm b/code/__DEFINES/messages.dm similarity index 57% rename from code/__DEFINES/show_message.dm rename to code/__DEFINES/messages.dm index 1b97b9a8ddbe..2f4f3c4631da 100644 --- a/code/__DEFINES/show_message.dm +++ b/code/__DEFINES/messages.dm @@ -1,3 +1,10 @@ +#define MAX_MESSAGE_LEN 1024 +#define MAX_PAPER_MESSAGE_LEN 9216 +#define MAX_BOOK_MESSAGE_LEN 27648 +#define MAX_NAME_LEN 26 +#define MAX_LNAME_LEN 64 +#define MAX_REV_REASON_LEN 255 + //#define SHOWMSG_SELF #define SHOWMSG_VISUAL (1<<0) #define SHOWMSG_AUDIO (1<<1) diff --git a/code/__DEFINES/subsystem.dm b/code/__DEFINES/subsystem.dm index 3247fec706af..f2f54da2c92b 100644 --- a/code/__DEFINES/subsystem.dm +++ b/code/__DEFINES/subsystem.dm @@ -19,6 +19,7 @@ // Subsystem init_order, from highest priority to lowest priority // The numbers just define the ordering, they are meaningless otherwise. +#define SS_INIT_PROFILER 100 #define SS_INIT_ASPECTS 86 #define SS_INIT_INPUT 85 #define SS_INIT_RATING 14 diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 206911a83f06..d9a41119aff0 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -2,6 +2,8 @@ //Enables in-depth debug messages to runtime log (used for debugging) //#define TESTING //By using the testing("message") proc you can create debug-feedback for people with this //uncommented, but not visible in the release version) +//#define EARLY_PROFILE // uncomment to automatically start profiler at the world init, not waiting + // for the subsystems initialization. Allows to collect data for the early init phase /***** All toggles for the GC ref finder *****/ @@ -16,14 +18,6 @@ #define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary. // 1 will enable set background. 0 will disable set background. -//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam -#define MAX_MESSAGE_LEN 1024 -#define MAX_PAPER_MESSAGE_LEN 9216 -#define MAX_BOOK_MESSAGE_LEN 27648 -#define MAX_NAME_LEN 26 -#define MAX_LNAME_LEN 64 -#define MAX_REV_REASON_LEN 255 - //Update this whenever you need to take advantage of more recent byond features #define MIN_COMPILER_VERSION 514 #if DM_VERSION < MIN_COMPILER_VERSION diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index ef2a53c33f51..f8cd70140f1d 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -206,6 +206,12 @@ var/global/bridge_secret = null var/load_mine = TRUE var/load_space_levels = TRUE +#ifdef EARLY_PROFILE + var/auto_profile = TRUE +#else + var/auto_profile = FALSE +#endif + var/auto_lag_switch_pop = FALSE var/record_replays = FALSE @@ -679,6 +685,9 @@ var/global/bridge_secret = null if("no_space_levels") config.load_space_levels = FALSE + if("auto_profile") + config.auto_profile = TRUE + if("auto_lag_switch_pop") config.auto_lag_switch_pop = text2num(value) diff --git a/code/controllers/subsystem/profiler.dm b/code/controllers/subsystem/profiler.dm new file mode 100644 index 000000000000..610317a565cb --- /dev/null +++ b/code/controllers/subsystem/profiler.dm @@ -0,0 +1,96 @@ +#define PROFILER_FILENAME "profiler.json" +#define INIT_PROFILE_NAME "init_profiler.json" +#define SENDMAPS_FILENAME "sendmaps.json" + +SUBSYSTEM_DEF(profiler) + name = "Profiler" + init_order = SS_INIT_PROFILER + runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY + flags = SS_SHOW_IN_MC_TAB + wait = 3000 + var/fetch_cost = 0 + var/write_cost = 0 + var/init_logs_dropped = FALSE + +/datum/controller/subsystem/profiler/stat_entry(msg) + msg += "F:[round(fetch_cost,1)]ms" + msg += "|W:[round(write_cost,1)]ms" + return ..() + +/datum/controller/subsystem/profiler/Initialize() + if(!config.auto_profile) + StopProfiling() //Stop the early start profiler + return + + StartProfiling() + + return ..() + +/datum/controller/subsystem/profiler/fire() + if(!init_logs_dropped) // first fire call in lobby after everything is initialized + init_logs_dropped = TRUE + DumpInitData() + return + + DumpData() + +/datum/controller/subsystem/profiler/Shutdown() + if(config.auto_profile) + DumpData(allow_yield = FALSE) + world.Profile(PROFILE_CLEAR, type = "sendmaps") + + return ..() + +/datum/controller/subsystem/profiler/proc/StartProfiling() + info("Byond profiler is enabled.") + + world.Profile(PROFILE_START) + world.Profile(PROFILE_START, type = "sendmaps") + + can_fire = TRUE + +/datum/controller/subsystem/profiler/proc/StopProfiling() + info("Byond profiler is disabled.") + world.Profile(PROFILE_STOP) + world.Profile(PROFILE_STOP, type = "sendmaps") + can_fire = FALSE + +/datum/controller/subsystem/profiler/proc/DumpInitData() + var/current_profile_data = world.Profile(PROFILE_REFRESH, format = "json") + CHECK_TICK + + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/prof_file = file("[global.log_debug_directory]/[INIT_PROFILE_NAME]") + if(fexists(prof_file)) + fdel(prof_file) + WRITE_FILE(prof_file, current_profile_data) + world.Profile(PROFILE_CLEAR) //Now that we're written this data out, dump it. We don't want it getting mixed up with our current round data + +/datum/controller/subsystem/profiler/proc/DumpData(allow_yield = TRUE) + var/timer = TICK_USAGE_REAL + var/current_profile_data = world.Profile(PROFILE_REFRESH, format = "json") + var/current_sendmaps_data = world.Profile(PROFILE_REFRESH, type = "sendmaps", format="json") + fetch_cost = MC_AVERAGE(fetch_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + if(allow_yield) + CHECK_TICK + + if(!length(current_profile_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, profiling stopped manually before dump.") + var/prof_file = file("[global.log_debug_directory]/[PROFILER_FILENAME]") + if(fexists(prof_file)) + fdel(prof_file) + if(!length(current_sendmaps_data)) //Would be nice to have explicit proc to check this + stack_trace("Warning, sendmaps profiling stopped manually before dump.") + var/sendmaps_file = file("[global.log_debug_directory]/[SENDMAPS_FILENAME]") + if(fexists(sendmaps_file)) + fdel(sendmaps_file) + + timer = TICK_USAGE_REAL + WRITE_FILE(prof_file, current_profile_data) + WRITE_FILE(sendmaps_file, current_sendmaps_data) + write_cost = MC_AVERAGE(write_cost, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + +#undef PROFILER_FILENAME +#undef INIT_PROFILE_NAME +#undef SENDMAPS_FILENAME diff --git a/code/game/world.dm b/code/game/world.dm index a346f632c3a1..d97577b01624 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -8,6 +8,11 @@ var/global/it_is_a_snow_day = FALSE enable_debugger() #endif +#ifdef EARLY_PROFILE + Profile(PROFILE_RESTART) + Profile(PROFILE_RESTART, type = "sendmaps") +#endif + it_is_a_snow_day = prob(50) if(byond_version < RECOMMENDED_VERSION) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index bc036432fc1b..8701053026cd 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -166,6 +166,7 @@ var/global/list/admin_verbs_debug = list( /client/proc/generate_round_scoreboard, /client/proc/save_statistics, /client/proc/cmd_admin_list_open_jobs, + /client/proc/toggle_profiler, /client/proc/Debug2, /client/proc/forceEvent, /client/proc/ZASSettings, @@ -295,6 +296,7 @@ var/global/list/admin_verbs_hideable = list( /datum/admins/proc/adjump, /client/proc/cmd_admin_list_open_jobs, // /client/proc/callproc, + /client/proc/toggle_profiler, /client/proc/Debug2, /client/proc/reload_admins, /client/proc/cmd_debug_make_powernets, diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 1a01157cad75..e979e0a1e806 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -14,7 +14,25 @@ feedback_add_details("admin_verb","DG2") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +/client/proc/toggle_profiler() + set category = "Debug" + set name = "Toggle Profiler" + + if(!check_rights(R_DEBUG)) + return + + if(tgui_alert(usr, "Be sure you know what you are doing. You want to [config.auto_profile ? "STOP": "START"] Byond Profiler?",, list("Yes","No")) != "Yes") + return + + config.auto_profile = !config.auto_profile + + if(config.auto_profile) + SSprofiler.StartProfiling() + else + SSprofiler.StopProfiling() + message_admins("[key_name(src)] toggled byond profiler [config.auto_profile ? "on" : "off"].") + log_admin("[key_name(src)] toggled byond profiler [config.auto_profile ? "on" : "off"].") /* 21st Sept 2010 Updated by Skie -- Still not perfect but better! diff --git a/config/example/config.txt b/config/example/config.txt index 9c3d5e85c787..5f0d03ac00b4 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -278,13 +278,17 @@ NO_JUNKYARD ## Saves some initialization time # NO_SPACE_LEVELS +## Uncomment to enable byond profiler. Logs will be dropped in the round log folder. +## Keep in mind it can cause performance degradation. +# AUTO_PROFILE + ## Uncomment to allow drastic performence enhancemet measures to turn on automatically once there are equal or more clients than the configured amount (will also prompt admin for veto) # AUTO_LAG_SWITCH_POP 100 ## Enables demo recordings, works slower on windows # RECORD_REPLAYS -## Use persistent cache for better perfomance +## Use persistent cache for better performance ## You will need to occasionally clean ./cache/persistent yourself from old files ## by removing folder or with ./script/clear_persistent_cache.sh #USE_PERSISTENT_CACHE diff --git a/taucetistation.dme b/taucetistation.dme index 4907bfbba6aa..fa5b91d7c202 100644 --- a/taucetistation.dme +++ b/taucetistation.dme @@ -68,6 +68,7 @@ #include "code\__DEFINES\math_physics.dm" #include "code\__DEFINES\mc.dm" #include "code\__DEFINES\memories.dm" +#include "code\__DEFINES\messages.dm" #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mob.dm" #include "code\__DEFINES\objectives.dm" @@ -85,7 +86,6 @@ #include "code\__DEFINES\role_preferences.dm" #include "code\__DEFINES\round_aspects.dm" #include "code\__DEFINES\say.dm" -#include "code\__DEFINES\show_message.dm" #include "code\__DEFINES\shuttles.dm" #include "code\__DEFINES\sight.dm" #include "code\__DEFINES\size_classes.dm" @@ -253,6 +253,7 @@ #include "code\controllers\subsystem\orbit.dm" #include "code\controllers\subsystem\overlays.dm" #include "code\controllers\subsystem\parallax.dm" +#include "code\controllers\subsystem\profiler.dm" #include "code\controllers\subsystem\qualities.dm" #include "code\controllers\subsystem\quirks.dm" #include "code\controllers\subsystem\religion.dm"