[MIRROR] Removes the excited cleanup subprocess (#3868)

* Removes the excited cleanup subprocess (#57381)

When I was in the process of developing my atmos fixes/optimizations, I focused heavily on maintaining the area
of excited groups, since growing delayed self_breakdown(), and lead to shitty behavior which I thought was the
result of my sleeping changes.

This was not the case, those who came before me knew better, as always.

Especially now, since I've unhooked breakdown from excited groups gaining new tiles, my concern was unfounded,
and actually lead to shitty behavior and wasted time.

I failed to recognize the value in random garbage_collect()s, they help prevent mass gas equalization over large
spaces, they make gas appear to move more consistently when in these large spaces, and they lessen the amount of
self_breakdown()s over large turf lists, which is very helpful for lowering the overall overtime of the
subsystem.

This fixes my mistake, and purges the excited cleanup subprocess from the air subsystem. It's free real estate
babyyyyyyyy.

* Removes the excited cleanup subprocess

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
This commit is contained in:
SkyratBot
2021-03-04 21:33:13 +00:00
committed by GitHub
co-authored by LemonInTheDark
parent 48b695209b
commit 38c791df0f
7 changed files with 15 additions and 114 deletions
-5
View File
@@ -78,11 +78,6 @@
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION (T20C+80)
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION (T20C+400)
//Excited Group Cleanup helper defines
#define EX_CLEANUP_BREAKDOWN 1
#define EX_CLEANUP_DISMANTLE 2
#define EX_CLEANUP_TURFS 3
//HEAT TRANSFER COEFFICIENTS
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
-2
View File
@@ -88,8 +88,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define NO_LAVA_GEN (1<<3)
/// Blocks ruins spawning on the turf.
#define NO_RUINS (1<<4)
/// Should this tile be cleaned up and reinserted into an excited group?
#define EXCITED_CLEANUP (1<<5)
////////////////Area flags\\\\\\\\\\\\\\
/// If it's a valid territory for cult summoning or the CRAB-17 phone to spawn
+4 -5
View File
@@ -242,11 +242,10 @@
#define SSAIR_ATMOSMACHINERY 2
#define SSAIR_ACTIVETURFS 3
#define SSAIR_HOTSPOTS 4
#define SSAIR_EXCITEDCLEANUP 5
#define SSAIR_EXCITEDGROUPS 6
#define SSAIR_HIGHPRESSURE 7
#define SSAIR_SUPERCONDUCTIVITY 8
#define SSAIR_PROCESS_ATOMS 9
#define SSAIR_EXCITEDGROUPS 5
#define SSAIR_HIGHPRESSURE 6
#define SSAIR_SUPERCONDUCTIVITY 7
#define SSAIR_PROCESS_ATOMS 8
// Explosion Subsystem subtasks
#define SSEXPLOSIONS_MOVABLES 1
-1
View File
@@ -66,7 +66,6 @@ DEFINE_BITFIELD(area_flags, list(
))
DEFINE_BITFIELD(turf_flags, list(
"EXCITED_CLEANUP" = EXCITED_CLEANUP,
"NO_LAVA_GEN" = NO_LAVA_GEN,
"NO_RUINS" = NO_RUINS,
"NOJAUNT" = NOJAUNT,
+1 -45
View File
@@ -10,7 +10,6 @@ SUBSYSTEM_DEF(air)
var/cost_atoms = 0
var/cost_turfs = 0
var/cost_hotspots = 0
var/cost_ex_cleanup = 0
var/cost_groups = 0
var/cost_highpressure = 0
var/cost_superconductivity = 0
@@ -19,7 +18,6 @@ SUBSYSTEM_DEF(air)
var/cost_rebuilds = 0
var/list/excited_groups = list()
var/list/cleanup_ex_groups = list()
var/list/active_turfs = list()
var/list/hotspots = list()
var/list/networks = list()
@@ -51,7 +49,6 @@ SUBSYSTEM_DEF(air)
msg += "C:{"
msg += "AT:[round(cost_turfs,1)]|"
msg += "HS:[round(cost_hotspots,1)]|"
msg += "CL:[round(cost_ex_cleanup, 1)]|"
msg += "EG:[round(cost_groups,1)]|"
msg += "HP:[round(cost_highpressure,1)]|"
msg += "SC:[round(cost_superconductivity,1)]|"
@@ -62,7 +59,6 @@ SUBSYSTEM_DEF(air)
msg += "} "
msg += "AT:[active_turfs.len]|"
msg += "HS:[hotspots.len]|"
msg += "CL:[cleanup_ex_groups.len]|"
msg += "EG:[excited_groups.len]|"
msg += "HP:[high_pressure_delta.len]|"
msg += "SC:[active_super_conductivity.len]|"
@@ -149,18 +145,6 @@ SUBSYSTEM_DEF(air)
return
cost_hotspots = MC_AVERAGE(cost_hotspots, TICK_DELTA_TO_MS(cached_cost))
resumed = FALSE
currentpart = SSAIR_EXCITEDCLEANUP
if(currentpart == SSAIR_EXCITEDCLEANUP)
timer = TICK_USAGE_REAL
if(!resumed)
cached_cost = 0
process_excited_cleanup(resumed)
cached_cost += TICK_USAGE_REAL - timer
if(state != SS_RUNNING)
return
cost_ex_cleanup = MC_AVERAGE(cost_ex_cleanup, TICK_DELTA_TO_MS(cached_cost))
resumed = FALSE
currentpart = SSAIR_EXCITEDGROUPS
if(currentpart == SSAIR_EXCITEDGROUPS)
@@ -312,30 +296,6 @@ SUBSYSTEM_DEF(air)
if (MC_TICK_CHECK)
return
/datum/controller/subsystem/air/proc/process_excited_cleanup(resumed = FALSE)
//cache for sanic speed
var/fire_count = times_fired
if (!resumed)
src.currentrun = cleanup_ex_groups.Copy()
cleanup_ex_groups.Cut() //Cut the list here so any later breakdowns get added properly
//cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun
while(currentrun.len)
var/list/turf_packet = currentrun[currentrun.len]
var/breakdown = turf_packet[EX_CLEANUP_BREAKDOWN]
var/dismantle = turf_packet[EX_CLEANUP_DISMANTLE]
var/list/turf_list = turf_packet[EX_CLEANUP_TURFS]
while(turf_list.len) //The turf list
var/turf/open/T = turf_list[turf_list.len]
//I'd normally check for nulls here, but turfs are dumb with refs, so it's not an issue
//We don't allow planetary turfs as a semi stopgap to worldspanning groups
if(istype(T) && !istype(T.air, /datum/gas_mixture/immutable) && !T.planetary_atmos)
T.cleanup_group(fire_count, breakdown, dismantle)
turf_list.len--
if (MC_TICK_CHECK)
return
currentrun.len-- //If we process all the turfs in a packet, del it.
/datum/controller/subsystem/air/proc/process_excited_groups(resumed = FALSE)
if (!resumed)
src.currentrun = excited_groups.Copy()
@@ -366,7 +326,7 @@ SUBSYSTEM_DEF(air)
if(T.excited_group)
//If this fires during active turfs it'll cause a slight removal of active turfs, as they breakdown if they have no excited group
//The group also expands by a tile per rebuild on each edge, suffering
T.excited_group.garbage_collect(will_cleanup = TRUE) //Poke everybody in the group and reform
T.excited_group.garbage_collect() //Kill the excited group, it'll reform on its own later
///Puts an active turf to sleep so it doesn't process. Do this without cleaning up its excited group.
/datum/controller/subsystem/air/proc/sleep_active_turf(turf/open/T)
@@ -404,10 +364,6 @@ SUBSYSTEM_DEF(air)
else
T.requires_activation = TRUE
/datum/controller/subsystem/air/proc/add_to_cleanup(datum/excited_group/ex_grp)
//Store the cooldowns. If we're already doing cleanup, DO NOT add to the currently processing list, infinite loop man bad.
cleanup_ex_groups += list(list(ex_grp.breakdown_cooldown, ex_grp.dismantle_cooldown, ex_grp.turf_list.Copy()))
/datum/controller/subsystem/air/StartLoadingMap()
LAZYINITLIST(queued_for_activation)
map_loading = TRUE
+9 -14
View File
@@ -50,28 +50,25 @@ Now then, into the breach.
- This is the heart and soul of environmental atmos, see more details below
- All you need to know right now is it manages moving gas from tile to tile
- Calls `process_cell()` on each `/turf/open` in the `active_turfs` list
5. Excited group cleanup
- Rebuilds excited groups when the structure of their turfs changes
- Calls `cleanup_group()` on each `/turf/open` in the `cleanup_ex_groups` list
6. Excited groups
5. Excited groups
- Manages excited groups, which are core to working flow simulation
- More details to come, they handle differences between gasmixtures when active turfs can't do the job
- Increases the `breakdown_cooldown` and `dismantle_cooldown` for each `/datum/excited_group` in the `excited_groups` list
- If either cooldown for a given excited group has passed its threshold
- Calls `self_breakdown()` or `dismantle()` appropriately on the excited group.
7. High pressure deltas
6. High pressure deltas
- Takes the gas movement from Active Turfs and uses it to move objects on said turfs
- Calls `high_pressure_movements()` on each `/turf/open` in the `high_pressure_delta` list.
- Sets each turf's `pressure_difference` to 0
8. Hotspots
7. Hotspots
- These are what you might know as fire, at least the effect of it.
- They deal with burning things, and color calculations, lots of color calculations
- Calls `process()` on each `/obj/effect/hotspot` in the `hotspots` list
9. Superconductivity
8. Superconductivity
- Moves heat through turfs that don't allow gas to pass
- Deals with heating up the floor below windows, and some other more painful heat stuff
- Calls `super_conduct()` on each `/turf` in the `active_super_conductivity` list
10. Atoms
9. Atoms
- Processes things in the world that should know about gas changes, used to account for turfs sleeping, I'll get more into that in a bit
- Calls `process_exposure()` on each `/atom` in the `atom_process` list
@@ -167,7 +164,7 @@ This is a rather large subject, we will need to cover gas flow, turf sleeping, s
Active turfs are the backbone of how gas moves from tile to tile. While most of `process_cell()` should be easy enough to understand, I am going to go into some detail about archiving, since I think it's a common source of hiccups.
* *`archived_cycle`* this var stores the last cycle of the atmos loop that the turf processed on. The key point to notice here is that when processing a turf, we don't share with all its neighbors, we only talk to those who haven't processed yet. This is because the remainder of `process_cell()` and especially `share()` ought to be similar in form to addition. We can add in any order we like, and we only need to add once. This is what archived gases are for by the way, they store the state of the relevant tile before any processing occurs. This isn't strictly the case unfortunately, but it's minor enough that we can ignore the effects.
* *`archived_cycle`* this var stores the last cycle of the atmos loop that the turf processed on. The key point to notice here is that when processing a turf, we don't share with all its neighbors, we only talk to those who haven't processed yet. This is because the remainder of `process_cell()` and especially `share()` ought to be similar in form to addition. We can add in any order we like, and we only need to add once. This is what archived gases are for by the way, they store the state of the relevant tile before any processing occurs. This additive behavior isn't strictly the case unfortunately, but it's minor enough that we can ignore the effects.
Alright then, with that out of the way, what is an active turf.
@@ -216,13 +213,11 @@ When a turf is removed from active, the excited group is broken down, as it's as
Now this issue here is we'd like to keep this napping, but we don't want to `garbage_collect()` the excited group constantly.
So, a new proc was added, `sleep_active_turf()`. It removes the active turf from processing, but doesn't `garbage_collect()` the group. This has some additional costs however.
So, a new proc was added, `sleep_active_turf()`. It removes the active turf from processing, but doesn't `garbage_collect()` the group.
The excited group's `garbage_collect()` proc is the real issue here. When the landscape of the map changes, we need to rebuild the groups, as we don't want to rebuild them across a wall. The old way relied on the group rebuilding itself, in `process_cell()`, but since players can cause rebuilds quite often, can't afford to just wake all the turfs up.
You'd think this would cause issues with maintaining the shape of an excited group, however this isn't actually a priority, since `garbage_collect()` and the subsequent rebuild in `process_cell()` causes turfs that are actually active to reform, just as it always has. This has benefits, as it lessens the tendency of one group to cover a huge space, equalize all at once, and fuck with things.
Thus, we have excited group cleanup, which takes all the old turfs, and reaches out to their neighbors to rebuild the group. This allows us to rebuild excited groups without relying on active turfs.
There's another issue here too, how do we deal with things that react to heat? A firelock shouldn't just open because the turf that the alarm is on went to sleep. Thus, atom_process, as I mentioned before, a list of atoms with requirements and things to do. It processes them until their requirements are not met, then it removes them from its list them.
There's another issue here however, how do we deal with things that react to heat? A firelock shouldn't just open because the turf that the alarm is on went to sleep. Thus, atom_process, as I mentioned before, a list of atoms with requirements and things to do. It processes them until their requirements are not met, then it removes them from its list them.
There's one more major aspect of environmental atmos to cover, and while it's not the most misunderstood, it is the code with the worst set dressing.
@@ -331,43 +331,6 @@
significant_share_ticker = cached_ticker //Save our changes
temperature_expose(our_air, our_air.temperature)
////////////////////Excited Group Cleanup///////////////////////
///For dealing with reforming excited groups, this prevents clog in process_cell
/turf/open/proc/cleanup_group(fire_count, breakdown, dismantle)
current_cycle = fire_count + 0.5 //It works, I know it's dumb but it works
//cache for sanic speed
var/list/adjacent_turfs = atmos_adjacent_turfs
var/datum/excited_group/our_excited_group = excited_group
for(var/t in adjacent_turfs)
var/turf/open/enemy_tile = t
if(current_cycle <= enemy_tile.current_cycle)
continue
//cache for sanic speed
var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group
//If we are both in an excited group, and they aren't the same, merge.
//Otherwise make/take one to join and get to it
if(our_excited_group && enemy_excited_group)
if(our_excited_group != enemy_excited_group)
//combine groups (this also handles updating the excited_group var of all involved turfs)
our_excited_group.merge_groups(enemy_excited_group)
our_excited_group = excited_group //update our cache
else
var/datum/excited_group/EG = our_excited_group || enemy_excited_group || new
if(!our_excited_group)
EG.add_turf(src)
if(!enemy_excited_group && enemy_tile.turf_flags & EXCITED_CLEANUP)
EG.add_turf(enemy_tile)
our_excited_group = excited_group
if(our_excited_group)
our_excited_group.breakdown_cooldown = breakdown //Update with the old data
our_excited_group.dismantle_cooldown = dismantle
turf_flags &= ~EXCITED_CLEANUP
//////////////////////////SPACEWIND/////////////////////////////
/turf/open/proc/consider_pressure_difference(turf/T, difference)
@@ -521,16 +484,12 @@
garbage_collect()
//Breaks down the excited group, this doesn't sleep the turfs mind, just removes them from the group
/datum/excited_group/proc/garbage_collect(will_cleanup = FALSE)
/datum/excited_group/proc/garbage_collect()
if(display_id) //If we ever did make those changes
hide_turfs()
for(var/t in turf_list)
var/turf/open/T = t
T.excited_group = null
if(will_cleanup)
T.turf_flags |= EXCITED_CLEANUP
if(will_cleanup)
SSair.add_to_cleanup(src)
turf_list.Cut()
SSair.excited_groups -= src
if(SSair.currentpart == SSAIR_EXCITEDGROUPS)