Automated Profiler (#9053)

Adds a lock-up detecting profiler to the game, using BYOND's new programmatic access to the profiler.

The idea is that we have an SS that's roughly called every tick. This will detect a lock-up by using world.timeofday. There might be a small issue with midnight rollover but eh. Don't. Really care. A notice is printed for each printout. These can later be processed in Python.
This commit is contained in:
Erki
2020-06-10 09:03:24 +03:00
committed by GitHub
parent f882fc0762
commit ced8c44d51
5 changed files with 72 additions and 0 deletions

View File

@@ -309,6 +309,10 @@ var/list/gamemode_cache = list()
var/news_use_forum_api = FALSE
var/profiler_is_enabled = FALSE
var/profiler_restart_period = 120 SECONDS
var/profiler_timeout_threshold = 5 SECONDS
/datum/configuration/New()
var/list/L = typesof(/datum/game_mode) - /datum/game_mode
for (var/T in L)
@@ -933,6 +937,13 @@ var/list/gamemode_cache = list()
if ("news_use_forum_api")
news_use_forum_api = TRUE
if ("profiler_enabled")
profiler_is_enabled = TRUE
if ("profiler_restart_period")
profiler_restart_period = text2num(value) SECONDS
if ("profiler_timeout_threshold")
profiler_timeout_threshold = text2num(value)
else
log_misc("Unknown setting in configuration: '[name]'")

View File

@@ -0,0 +1,54 @@
var/datum/controller/subsystem/profiler/SSprofiler
/datum/controller/subsystem/profiler
name = "Profiler"
wait = 1
priority = SS_PRIORITY_PROFILE
flags = SS_TICKER|SS_FIRE_IN_LOBBY
var/last_fire_rt = 0
var/threshold = 0
var/next_restart = 0
var/restart_period = 0
/datum/controller/subsystem/profiler/New()
NEW_SS_GLOBAL(SSprofiler)
/datum/controller/subsystem/profiler/Initialize()
if (!config.profiler_is_enabled)
..()
flags |= SS_NO_FIRE
return
restart_period = config.profiler_restart_period
threshold = config.profiler_timeout_threshold
..()
/datum/controller/subsystem/profiler/fire()
. = world.timeofday
if (!last_fire_rt)
last_fire_rt = .
next_restart = world.time + restart_period
world.Profile(PROFILE_START)
if (. - last_fire_rt > threshold)
DumpData()
else if (world.time > next_restart)
RestartProfiler()
last_fire_rt = .
/datum/controller/subsystem/profiler/proc/DumpData()
admin_notice(SPAN_DANGER("Profiler: dump profile after CPU spike."), R_SERVER|R_DEV)
var/name = "[game_id]_[time2text(world.timeofday, "hh-mm-ss")]"
text2file(world.Profile(0, "json"), "data/logs/profiler/[game_id]/[name].json")
/datum/controller/subsystem/profiler/proc/RestartProfiler()
world.Profile(PROFILE_CLEAR)
next_restart = world.time + restart_period