diff --git a/code/__DEFINES/_profile.dm b/code/__DEFINES/_profile.dm new file mode 100644 index 00000000000..5fc84789014 --- /dev/null +++ b/code/__DEFINES/_profile.dm @@ -0,0 +1,29 @@ +#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; + +#define PROFILE_TICK ;\ + if (PROFILE_STORE) {\ + var/PROFILE_TICK_USAGE_REAL = TICK_USAGE_REAL;\ + if (PROFILE_SLEEPCHECK == world.time) {\ + var/PROFILE_STRING = "[PROFILE_FILE]:[PROFILE_LINE] - [__FILE__]:[__LINE__]";\ + var/list/PROFILE_ITEM = PROFILE_STORE[PROFILE_STRING];\ + if (!PROFILE_ITEM) {\ + PROFILE_ITEM = new(PROFILE_ITEM_LEN);\ + PROFILE_STORE[PROFILE_STRING] = PROFILE_ITEM;\ + PROFILE_ITEM[PROFILE_ITEM_TIME] = 0;\ + PROFILE_ITEM[PROFILE_ITEM_COUNT] = 0;\ + };\ + PROFILE_ITEM[PROFILE_ITEM_TIME] += TICK_DELTA_TO_MS(PROFILE_TICK_USAGE_REAL-PROFILE_TIME);\ + var/PROFILE_INCR_AMOUNT = min(1, 2**round(PROFILE_ITEM[PROFILE_ITEM_COUNT]/SHORT_REAL_LIMIT));\ + if (prob(100/PROFILE_INCR_AMOUNT)) {\ + PROFILE_ITEM[PROFILE_ITEM_COUNT] += PROFILE_INCR_AMOUNT;\ + };\ + };\ + PROFILE_SET;\ + }; + +#define PROFILE_ITEM_LEN 2 +#define PROFILE_ITEM_TIME 1 +#define PROFILE_ITEM_COUNT 2 diff --git a/code/__HELPERS/sorts/comparators.dm b/code/__HELPERS/sorts/comparators.dm index 36484e7e2d5..9741b55b9ff 100644 --- a/code/__HELPERS/sorts/comparators.dm +++ b/code/__HELPERS/sorts/comparators.dm @@ -145,3 +145,15 @@ GLOBAL_VAR_INIT(cmp_field, "name") */ /datum/proc/compare_to(datum/D) return cmp_text_asc("[src]", "[D]") + +// profile stuff + +/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)) + +/proc/cmp_profile_time_dsc(list/A, list/B) + return B[PROFILE_ITEM_TIME] - A[PROFILE_ITEM_TIME] + +/proc/cmp_profile_count_dsc(list/A, list/B) + return B[PROFILE_ITEM_COUNT] - A[PROFILE_ITEM_COUNT] + diff --git a/code/datums/profile.dm b/code/datums/profile.dm new file mode 100644 index 00000000000..9f73d3d96ca --- /dev/null +++ b/code/datums/profile.dm @@ -0,0 +1,17 @@ +//these are real globals so you can use profiling to profile early world init stuff. +GLOBAL_REAL_VAR(list/PROFILE_STORE) +GLOBAL_REAL_VAR(PROFILE_LINE) +GLOBAL_REAL_VAR(PROFILE_FILE) +GLOBAL_REAL_VAR(PROFILE_SLEEPCHECK) +GLOBAL_REAL_VAR(PROFILE_TIME) + +/proc/profile_show(user, sort = /proc/cmp_profile_avg_time_dsc) + sortTim(PROFILE_STORE, sort, TRUE) + + var/list/lines = list() + + for (var/entry in PROFILE_STORE) + var/list/data = PROFILE_STORE[entry] + lines += "[entry] => [num2text(data[PROFILE_ITEM_TIME], 10)]ms ([data[PROFILE_ITEM_COUNT]]) (avg:[num2text(data[PROFILE_ITEM_TIME]/(data[PROFILE_ITEM_COUNT] || 1), 99)])" + + user << browse("
  1. [lines.Join("
  2. ")]
", "window=[url_encode(GUID())]") diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 00e05f1970e..30bde72d27e 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -404,10 +404,6 @@ GLOBAL_LIST_INIT(multiz_hole_baseturfs, typecacheof(list( levelupdate() update_vertical_turf_graphics() -/turf/simulated/AfterChange(flags, oldType) - ..() - RemoveLattice() - /turf/proc/RemoveLattice() for(var/obj/structure/lattice/L in src) qdel(L) diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index efa4bdefdb9..e2d7ed55608 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -35,20 +35,50 @@ return !flooring /turf/simulated/floor/Initialize(mapload, floortype) + PROFILE_SET . = ..() + PROFILE_TICK if(!floortype && initial_flooring) floortype = initial_flooring if(floortype) - set_flooring(get_flooring_data(floortype)) + set_flooring(get_flooring_data(floortype), mapload) else footstep_sounds = base_footstep_sounds + PROFILE_TICK if(mapload && can_dirty && can_start_dirty) if(prob(dirty_prob)) dirt += rand(50,100) update_dirt() //5% chance to start with dirt on a floor tile- give the janitor something to do + if(outdoors) + SSplanets.addTurf(src) + PROFILE_TICK -/turf/simulated/floor/proc/set_flooring(var/decl/flooring/newflooring) - make_plating(defer_icon_update = TRUE, strip_bare = TRUE) +/turf/simulated/floor/Destroy() + if(outdoors) + SSplanets.removeTurf(src) + return ..() + +/turf/simulated/proc/make_outdoors() + outdoors = TRUE + SSplanets.addTurf(src) + +/turf/simulated/proc/make_indoors() + outdoors = FALSE + SSplanets.removeTurf(src) + +/turf/simulated/AfterChange(flags, oldType) + . = ..() + RemoveLattice() + // If it was outdoors and still is, it will not get added twice when the planet controller gets around to putting it in. + if(flags & CHANGETURF_PRESERVE_OUTDOORS) + // if it didn't preserve then we don't need to recheck now do we + if(outdoors) + make_outdoors() + else + make_indoors() + +/turf/simulated/floor/proc/set_flooring(decl/flooring/newflooring, mapload) + make_plating(null, TRUE, TRUE) flooring = newflooring footstep_sounds = newflooring.footstep_sounds // VOREStation Edit - We are plating switching to flooring, swap out old_decals for decals @@ -56,28 +86,31 @@ old_decals = decals decals = overfloor_decals // VOREStation Edit End + QUEUE_SMOOTH(src) QUEUE_SMOOTH_NEIGHBORS(src) levelupdate() //This proc will set floor_type to null and the update_icon() proc will then change the icon_state of the turf //This proc auto corrects the grass tiles' siding. -/turf/simulated/floor/proc/make_plating(place_product, defer_icon_update, strip_bare = FALSE) +/turf/simulated/floor/proc/make_plating(place_product, defer_icon_update, strip_bare) + if(!defer_icon_update) + name = base_name + desc = base_desc + icon = base_icon + icon_state = base_icon_state + footstep_sounds = base_footstep_sounds + cut_overlays() + QUEUE_SMOOTH(src) + QUEUE_SMOOTH_NEIGHBORS(src) + levelupdate() - cut_overlays() - // VOREStation Edit - We are flooring switching to plating, swap out old_decals for decals. if(flooring) + // VOREStation Edit - We are flooring switching to plating, swap out old_decals for decals. var/list/underfloor_decals = old_decals old_decals = decals decals = underfloor_decals - // VOREStation Edit End + // VOREStation Edit End - name = base_name - desc = base_desc - icon = base_icon - icon_state = base_icon_state - footstep_sounds = base_footstep_sounds - - if(flooring) if(place_product) flooring.drop_product(src) var/newtype = flooring.get_plating_type() @@ -89,10 +122,6 @@ broken = null burnt = null flooring_override = null - levelupdate() - - if(!defer_icon_update) - QUEUE_SMOOTH_NEIGHBORS(src) /turf/simulated/floor/levelupdate() for(var/obj/O in src) diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm index 5f9da9de279..a83927773ec 100644 --- a/code/game/turfs/simulated/floor_icon.dm +++ b/code/game/turfs/simulated/floor_icon.dm @@ -17,13 +17,17 @@ GLOBAL_LIST_EMPTY(turf_edge_cache) var/list/flooring_cache = list() /turf/simulated/floor/update_icon() + PROFILE_SET cut_overlays() + PROFILE_TICK if(flooring) // Set initial icon and strings. + PROFILE_TICK name = flooring.name desc = flooring.desc icon = flooring.icon + PROFILE_TICK if(flooring_override) icon_state = flooring_override @@ -32,6 +36,7 @@ var/list/flooring_cache = list() if(flooring.has_base_range) icon_state = "[icon_state][rand(0,flooring.has_base_range)]" flooring_override = icon_state + PROFILE_TICK // Apply edges, corners, and inner corners. if(flooring.flags & TURF_HAS_EDGES) @@ -71,15 +76,21 @@ var/list/flooring_cache = list() var/turf/simulated/floor/T = get_step(src, SOUTHWEST) if(!flooring.test_link(src, T)) add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-corner-[SOUTHWEST]", "[flooring.icon_base]_corners", SOUTHWEST)) + PROFILE_TICK if(!isnull(broken) && (flooring.flags & TURF_CAN_BREAK)) add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-broken-[broken]","broken[broken]")) if(!isnull(burnt) && (flooring.flags & TURF_CAN_BURN)) add_overlay(flooring.get_flooring_overlay("[flooring.icon_base]-burned-[burnt]","burned[burnt]")) + PROFILE_TICK else + PROFILE_TICK // no flooring - just handle plating stuff if(is_plating() && !(isnull(broken) && isnull(burnt))) //temp, todo icon = 'icons/turf/flooring/plating.dmi' icon_state = "dmg[rand(1,4)]" + PROFILE_TICK + + PROFILE_TICK // Re-apply floor decals if(LAZYLEN(decals)) @@ -90,8 +101,12 @@ var/list/flooring_cache = list() if(isopenturf(above) && !istype(src, /turf/simulated/floor/outdoors)) // This won't apply to outdoor turfs since its assumed they don't have a ceiling anyways. add_overlay(GLOB.no_ceiling_image) + PROFILE_TICK + // ..() has to be last to prevent trampling managed overlays - return ..() + . = ..() + + PROFILE_TICK /** * welcome to the less modular but more sensical and efficient way to do icon edges diff --git a/code/game/turfs/simulated/floors/outdoors.dm b/code/game/turfs/simulated/floors/outdoors.dm index 48466b9a99b..8e2c587a4b2 100644 --- a/code/game/turfs/simulated/floors/outdoors.dm +++ b/code/game/turfs/simulated/floors/outdoors.dm @@ -11,36 +11,8 @@ /turf/simulated/floor/outdoors/Initialize(mapload) QUEUE_SMOOTH(src) - . = ..() - -/turf/simulated/floor/Initialize(mapload) - . = ..() - if(outdoors) - SSplanets.addTurf(src) - -/turf/simulated/floor/Destroy() - if(outdoors) - SSplanets.removeTurf(src) return ..() -/turf/simulated/proc/make_outdoors() - outdoors = TRUE - SSplanets.addTurf(src) - -/turf/simulated/proc/make_indoors() - outdoors = FALSE - SSplanets.removeTurf(src) - -/turf/simulated/AfterChange(flags, oldType) - . = ..() - // If it was outdoors and still is, it will not get added twice when the planet controller gets around to putting it in. - if(flags & CHANGETURF_PRESERVE_OUTDOORS) - // if it didn't preserve then we don't need to recheck now do we - if(outdoors) - make_outdoors() - else - make_indoors() - /turf/simulated/floor/outdoors/mud name = "mud" icon_state = "mud_dark" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 15862f45ad9..fa649b3b7b6 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -228,6 +228,9 @@ var/list/admin_verbs_debug = list( /client/proc/SDQL2_query, /client/proc/Jump, /client/proc/debug_rogueminer, + /client/proc/start_line_profiling, + /client/proc/stop_line_profiling, + /client/proc/show_line_profiling, /client/proc/jumptomob, /client/proc/jumptocoord, /client/proc/dsay, diff --git a/code/modules/admin/verbs/debug/profiling.dm b/code/modules/admin/verbs/debug/profiling.dm new file mode 100644 index 00000000000..16f7915d414 --- /dev/null +++ b/code/modules/admin/verbs/debug/profiling.dm @@ -0,0 +1,37 @@ +/client/proc/start_line_profiling() + set category = "Profile" + set name = "Start Line Profiling" + set desc = "Starts tracking line by line profiling for code lines that support it" + + LINE_PROFILE_START + + message_admins("[key_name_admin(src)] started line by line profiling.") + // SSblackbox.record_feedback("tally", "admin_verb", 1, "Start Line Profiling") + log_admin("[key_name(src)] started line by line profiling.") + +/client/proc/stop_line_profiling() + set category = "Profile" + set name = "Stops Line Profiling" + set desc = "Stops tracking line by line profiling for code lines that support it" + + LINE_PROFILE_STOP + + message_admins("[key_name_admin(src)] stopped line by line profiling.") + // SSblackbox.record_feedback("tally", "admin_verb", 1, "Stop Line Profiling") + log_admin("[key_name(src)] stopped line by line profiling.") + +/client/proc/show_line_profiling() + set category = "Profile" + set name = "Show Line Profiling" + set desc = "Shows tracked profiling info from code lines that support it" + + var/sortlist = list( + "Avg time" = /proc/cmp_profile_avg_time_dsc, + "Total Time" = /proc/cmp_profile_time_dsc, + "Call Count" = /proc/cmp_profile_count_dsc + ) + var/sort = input(src, "Sort type?", "Sort Type", "Avg time") as null|anything in sortlist + if (!sort) + return + sort = sortlist[sort] + profile_show(src, sort) diff --git a/code/modules/admin/functions/server/admin_reboot.dm b/code/modules/admin/verbs/server/admin_reboot.dm similarity index 100% rename from code/modules/admin/functions/server/admin_reboot.dm rename to code/modules/admin/verbs/server/admin_reboot.dm diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 0e384b79636..1786ff68dc7 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -90,6 +90,7 @@ turf/simulated/mineral/floor/light_corner can_build_into_floor = TRUE SSplanets.addTurf(src) SSair.mark_for_update(src) + QUEUE_SMOOTH(src) QUEUE_SMOOTH_NEIGHBORS(src) /turf/simulated/mineral/proc/make_wall() @@ -103,6 +104,7 @@ turf/simulated/mineral/floor/light_corner can_build_into_floor = FALSE SSplanets.removeTurf(src) SSair.mark_for_update(src) + QUEUE_SMOOTH(src) QUEUE_SMOOTH_NEIGHBORS(src) /turf/simulated/mineral/Entered(atom/movable/M as mob|obj) @@ -126,6 +128,7 @@ turf/simulated/mineral/floor/light_corner else UpdateMineral() // this'll work because we're INITIALIZED if(!mapload) + QUEUE_SMOOTH(src) QUEUE_SMOOTH_NEIGHBORS(src) /* custom smoothing code */ diff --git a/vorestation.dme b/vorestation.dme index 42b65b0f5a6..2c3d68a25d1 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -24,6 +24,7 @@ #include "code\__DEFINES\_globals.dm" #include "code\__DEFINES\_lists.dm" #include "code\__DEFINES\_planes+layers.dm" +#include "code\__DEFINES\_profile.dm" #include "code\__DEFINES\_protect.dm" #include "code\__DEFINES\_tick.dm" #include "code\__DEFINES\access.dm" @@ -391,6 +392,7 @@ #include "code\datums\mutable_appearance.dm" #include "code\datums\perspective.dm" #include "code\datums\position_point_vector.dm" +#include "code\datums\profile.dm" #include "code\datums\progressbar.dm" #include "code\datums\recipe.dm" #include "code\datums\riding.dm" @@ -1539,7 +1541,6 @@ #include "code\modules\admin\callproc\callproc.dm" #include "code\modules\admin\DB ban\functions.dm" #include "code\modules\admin\functions\modify_traits.dm" -#include "code\modules\admin\functions\server\admin_reboot.dm" #include "code\modules\admin\permissionverbs\permissionedit.dm" #include "code\modules\admin\secrets\admin_secrets\admin_logs.dm" #include "code\modules\admin\secrets\admin_secrets\alter_narsie.dm" @@ -1609,9 +1610,11 @@ #include "code\modules\admin\verbs\striketeam.dm" #include "code\modules\admin\verbs\ticklag.dm" #include "code\modules\admin\verbs\tripAI.dm" +#include "code\modules\admin\verbs\debug\profiling.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_parser.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2_wrappers.dm" +#include "code\modules\admin\verbs\server\admin_reboot.dm" #include "code\modules\admin\view_variables\admin_delete.dm" #include "code\modules\admin\view_variables\color_matrix_editor.dm" #include "code\modules\admin\view_variables\debug_variables.dm"