mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 23:54:14 +01:00
42ec1d5148
## About The Pull Request I found myself wondering about the best/worse cases of a block of code, this lets me answer that pretty trivially. Also, makes _cost a permanent var, since as is it ends up getting redefined a bunch for no reason. Fun Bonus! [Implements generic semi automated performance testing support](https://github.com/tgstation/tgstation/pull/94529/commits/967ca317db036113174a7f9be8bbe249f91415e6) [967ca31](https://github.com/tgstation/tgstation/pull/94529/commits/967ca317db036113174a7f9be8bbe249f91415e6) I found myself sitting at my desk waiting for the game to init so I could run a proc on a subsystem, then close the game. Figured that was extremely automatable, so here we go
81 lines
3.2 KiB
Plaintext
81 lines
3.2 KiB
Plaintext
#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;\
|
|
STAT_ENTRY[STAT_ENTRY_COUNT] += 1;
|
|
|
|
// Cost tracking macros, to be used in one proc. If you're using this raw you'll want to use global lists
|
|
// If you don't you'll need another way of reading it
|
|
#define INIT_COST(costs, counting) \
|
|
var/list/_costs = costs; \
|
|
var/list/_counting = counting; \
|
|
var/_usage = TICK_USAGE; \
|
|
var/_cost = 0;
|
|
|
|
// STATIC cost tracking macro. Uses static lists instead of the normal global ones
|
|
// Good for debug stuff, and for running before globals init
|
|
#define INIT_COST_STATIC(...) \
|
|
var/static/list/hidden_static_list_for_fun1 = list(); \
|
|
var/static/list/hidden_static_list_for_fun2 = list(); \
|
|
INIT_COST(hidden_static_list_for_fun1, hidden_static_list_for_fun2)
|
|
|
|
// Cost tracking macro for global lists, prevents erroring if GLOB has not yet been initialized
|
|
#define INIT_COST_GLOBAL(costs, counting) \
|
|
INIT_COST_STATIC() \
|
|
if(GLOB){\
|
|
costs = hidden_static_list_for_fun1; \
|
|
counting = hidden_static_list_for_fun2 ; \
|
|
} \
|
|
_usage = TICK_USAGE;
|
|
|
|
#define SET_COST_BOUNDS(category) \
|
|
do { \
|
|
_cost = TICK_USAGE; \
|
|
var/_tmp_delta = TICK_DELTA_TO_MS(_cost - _usage);\
|
|
_costs[category] += _tmp_delta;\
|
|
_counting[category] += 1;\
|
|
_costs["[category]_min"] = min(_tmp_delta, _costs["[category]_min"] || INFINITY);\
|
|
_counting["[category]_min"] += 1;\
|
|
_costs["[category]_max"] = max(_tmp_delta, _costs["[category]_max"] || 0);\
|
|
_counting["[category]_max"] += 1;\
|
|
} while(FALSE); \
|
|
_usage = TICK_USAGE;
|
|
|
|
#define SET_COST(category) \
|
|
do { \
|
|
_cost = TICK_USAGE; \
|
|
_costs[category] += TICK_DELTA_TO_MS(_cost - _usage);\
|
|
_counting[category] += 1; \
|
|
} while(FALSE); \
|
|
_usage = TICK_USAGE;
|
|
|
|
#define SET_COST_LINE(...) SET_COST("[__LINE__]")
|
|
|
|
/// A quick helper for running the code as a statement and profiling its cost.
|
|
/// For example, `SET_COST_STMT(var/x = do_work())`
|
|
#define SET_COST_STMT(code...) ##code; SET_COST("[__LINE__] - [#code]")
|
|
|
|
#define EXPORT_STATS_TO_JSON_LATER(filename, costs, counts) EXPORT_STATS_TO_FILE_LATER(filename, costs, counts, stat_tracking_export_to_json_later)
|
|
#define EXPORT_STATS_TO_CSV_LATER(filename, costs, counts) EXPORT_STATS_TO_FILE_LATER(filename, costs, counts, stat_tracking_export_to_csv_later)
|
|
|
|
#define EXPORT_STATS_TO_FILE_LATER(filename, costs, counts, proc) \
|
|
do { \
|
|
var/static/last_export = 0; \
|
|
/* Need to always run if we haven't yet, since this code can be placed ANYWHERE */ \
|
|
if (world.time - last_export > 1.1 SECONDS || (last_export == 0)) { \
|
|
last_export = world.time; \
|
|
/* spawn() is used here because this is often used to track init times, where timers act oddly. */ \
|
|
/* I was making timers and even after init times were complete, the timers didn't run :shrug: */ \
|
|
spawn (1 SECONDS) { \
|
|
##proc(filename, costs, counts); \
|
|
} \
|
|
} \
|
|
} while (FALSE); \
|
|
_usage = TICK_USAGE;
|