From 471d1d9c985e5a7ac6992634d5bd2a4b2ab5fc15 Mon Sep 17 00:00:00 2001 From: Krausus Date: Sun, 19 Feb 2017 23:37:54 -0500 Subject: [PATCH] Lighting performance/profiling tweaks - Lighting process now yields at 10% of a tick and defers at 80% of a tick - There is no longer a limit to how many sources/corners/overlays will update in a single work run - Source/corner/overlay totals are now simple counts instead of lists - Lighting update stats now show updates over each of the previous 5 seconds - Space turfs now remove their starlight when changing to a different turf, fixing a runtime --- code/controllers/Processes/lighting.dm | 71 +++++++++++------------ code/game/turfs/space/space.dm | 2 + code/modules/lighting/lighting_corner.dm | 4 +- code/modules/lighting/lighting_overlay.dm | 6 +- code/modules/lighting/lighting_source.dm | 6 +- 5 files changed, 43 insertions(+), 46 deletions(-) diff --git a/code/controllers/Processes/lighting.dm b/code/controllers/Processes/lighting.dm index d92fe8a36b1..d46cab1d19f 100644 --- a/code/controllers/Processes/lighting.dm +++ b/code/controllers/Processes/lighting.dm @@ -1,9 +1,3 @@ -// Solves problems with lighting updates lagging shit -// Max constraints on number of updates per doWork(): -#define MAX_LIGHT_UPDATES_PER_WORK 100 -#define MAX_CORNER_UPDATES_PER_WORK 1000 -#define MAX_OVERLAY_UPDATES_PER_WORK 2000 - /var/lighting_overlays_initialised = FALSE /var/list/lighting_update_lights = list() // List of lighting sources queued for update. @@ -16,10 +10,22 @@ /datum/controller/process/lighting + // Queues of update counts, waiting to be rolled into stats lists + var/list/stats_queues = list( + "Source" = list(), "Corner" = list(), "Overlay" = list()) + // Stats lists + var/list/stats_lists = list( + "Source" = list(), "Corner" = list(), "Overlay" = list()) + var/update_stats_every = (1 SECONDS) + var/next_stats_update = 0 + var/stat_updates_to_keep = 5 + /datum/controller/process/lighting/setup() name = "lighting" - schedule_interval = world.tick_lag // run as fast as you possibly can + schedule_interval = 0 // run as fast as you possibly can + sleep_interval = 10 // Yield every 10% of a tick + defer_usage = 80 // Defer at 80% of a tick create_all_lighting_overlays() lighting_overlays_initialised = TRUE @@ -28,17 +34,10 @@ doWork(1) /datum/controller/process/lighting/doWork(roundstart) - // Counters - var/light_updates = 0 - var/corner_updates = 0 - var/overlay_updates = 0 lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated. lighting_update_lights = list() for(var/datum/light_source/L in lighting_update_lights_old) - if(light_updates >= MAX_LIGHT_UPDATES_PER_WORK && !roundstart) - lighting_update_lights += L - continue // DON'T break, we're adding stuff back into the update queue. if(L.check() || L.destroyed || L.force_update) L.remove_lum() @@ -52,52 +51,48 @@ L.force_update = FALSE L.needs_update = FALSE - light_updates++ - SCHECK lighting_update_corners_old = lighting_update_corners //Same as above. lighting_update_corners = list() for(var/A in lighting_update_corners_old) - if(corner_updates >= MAX_CORNER_UPDATES_PER_WORK && !roundstart) - lighting_update_corners += A - continue // DON'T break, we're adding stuff back into the update queue. - var/datum/lighting_corner/C = A C.update_overlays() C.needs_update = FALSE - corner_updates++ - SCHECK lighting_update_overlays_old = lighting_update_overlays //Same as above. lighting_update_overlays = list() - for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old) - if(overlay_updates >= MAX_OVERLAY_UPDATES_PER_WORK && !roundstart) - lighting_update_overlays += O - continue // DON'T break, we're adding stuff back into the update queue. - + for(var/A in lighting_update_overlays_old) + var/atom/movable/lighting_overlay/O = A O.update_overlay() O.needs_update = 0 - overlay_updates++ SCHECK + stats_queues["Source"] += lighting_update_lights_old.len + stats_queues["Corner"] += lighting_update_corners_old.len + stats_queues["Overlay"] += lighting_update_overlays_old.len + if(next_stats_update <= world.time) + next_stats_update = world.time + update_stats_every + for(var/stat_name in stats_queues) + var/stat_sum = 0 + var/list/stats_queue = stats_queues[stat_name] + for(var/count in stats_queue) + stat_sum += count + stats_queue.Cut() + var/list/stats_list = stats_lists[stat_name] + stats_list.Insert(1, stat_sum) + if(stats_list.len > stat_updates_to_keep) + stats_list.Cut(stats_list.len) /datum/controller/process/lighting/statProcess() ..() - stat(null, "[all_lighting_sources.len] light sources exist") - stat(null, "[all_lighting_corners.len] light corners exist") - stat(null, "[global.all_lighting_overlays.len] light overlays exist") - stat(null, "[lighting_update_lights.len] lighting sources queued") - stat(null, "[lighting_update_corners.len] lighting corners queued") - stat(null, "[lighting_update_overlays.len] lighting overlays queued") - -#undef MAX_LIGHT_UPDATES_PER_WORK -#undef MAX_CORNER_UPDATES_PER_WORK -#undef MAX_OVERLAY_UPDATES_PER_WORK + stat(null, "[total_lighting_sources] sources, [total_lighting_corners] corners, [total_lighting_overlays] overlays") + for(var/stat_type in stats_lists) + stat(null, "[stat_type] updates: [jointext(stats_lists[stat_type], " | ")]") diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index da667768341..90454f9952b 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -31,6 +31,8 @@ ..() var/datum/space_level/S = space_manager.get_zlev(z) S.remove_from_transit(src) + if(light_sources) // Turn off starlight, if present + set_light(0) /turf/space/AfterChange(ignore_air, keep_cabling = FALSE) ..() diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index a464f5af2d0..907e7aab8b5 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -1,4 +1,4 @@ -/var/list/datum/lighting_corner/all_lighting_corners = list() +/var/total_lighting_corners = 0 /var/datum/lighting_corner/dummy/dummy_lighting_corner = new // Because we can control each corner of every lighting overlay. // And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). @@ -32,7 +32,7 @@ /datum/lighting_corner/New(var/turf/new_turf, var/diagonal) . = ..() - all_lighting_corners += src + total_lighting_corners++ masters[new_turf] = turn(diagonal, 180) z = new_turf.z diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index b6e4b8b066b..6fe55eed0ff 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -1,4 +1,4 @@ -var/list/all_lighting_overlays = list() // Global list of lighting overlays. +/var/total_lighting_overlays = 0 /atom/movable/lighting_overlay name = "" mouse_opacity = 0 @@ -21,7 +21,7 @@ var/list/all_lighting_overlays = list() // Global list of lighting overlays. /atom/movable/lighting_overlay/New(var/atom/loc, var/no_update = FALSE) . = ..() verbs.Cut() - global.all_lighting_overlays += src + total_lighting_overlays++ var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays outside of turfs. T.lighting_overlay = src @@ -77,7 +77,7 @@ var/list/all_lighting_overlays = list() // Global list of lighting overlays. return /atom/movable/lighting_overlay/Destroy() - global.all_lighting_overlays -= src + total_lighting_overlays-- global.lighting_update_overlays -= src global.lighting_update_overlays_old -= src diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 01f967a0544..d878d8c4b6e 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -1,4 +1,4 @@ -/var/list/datum/light_source/all_lighting_sources = list() +/var/total_lighting_sources = 0 // This is where the fun begins. // These are the main datums that emit light. @@ -32,7 +32,7 @@ var/force_update /datum/light_source/New(var/atom/owner, var/atom/top) - all_lighting_sources += src + total_lighting_sources++ source_atom = owner // Set our new owner. if(!source_atom.light_sources) source_atom.light_sources = list() @@ -62,7 +62,7 @@ // Kill ourselves. /datum/light_source/proc/destroy() - all_lighting_sources -= src + total_lighting_sources-- destroyed = TRUE force_update() if(source_atom)