More ZAS performance stuff (#3186)

Should be good.
This commit is contained in:
Lohikar
2017-09-14 13:19:07 -05:00
committed by Erki
parent e2a2c56f47
commit 3803b29661
4 changed files with 55 additions and 43 deletions

View File

@@ -47,6 +47,23 @@
SSair.connect(sim, src)
// Helper for can_safely_remove_from_zone().
#define GET_ZONE_NEIGHBOURS(T, ret) \
ret = 0; \
if (T.zone) { \
for (var/_gzn_dir in gzn_check) { \
var/turf/simulated/other = get_step(T, _gzn_dir); \
if (istype(other) && other.zone == T.zone) { \
var/block; \
ATMOS_CANPASS_TURF(block, other, T); \
if (!(block & AIR_BLOCKED)) { \
ret |= _gzn_dir; \
} \
} \
} \
} \
/*
Simple heuristic for determining if removing the turf from it's zone will not partition the zone (A very bad thing).
Instead of analyzing the entire zone, we only check the nearest 3x3 turfs surrounding the src turf.
@@ -54,41 +71,27 @@
*/
/turf/simulated/proc/can_safely_remove_from_zone()
if(!zone) return 1
if(!zone)
return 1
var/check_dirs = get_zone_neighbours(src)
var/unconnected_dirs = check_dirs
var/to_check = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
#ifdef MULTIZAS
to_check += list(NORTHUP, EASTUP, WESTUP, SOUTHUP, NORTHDOWN, EASTDOWN, WESTDOWN, SOUTHDOWN)
#endif
for(var/dir in to_check)
var/check_dirs
GET_ZONE_NEIGHBOURS(src, check_dirs)
. = check_dirs
for(var/dir in csrfz_check)
//for each pair of "adjacent" cardinals (e.g. NORTH and WEST, but not NORTH and SOUTH)
if((dir & check_dirs) == dir)
//check that they are connected by the corner turf
var/connected_dirs = get_zone_neighbours(get_step(src, dir))
var/turf/simulated/T = get_step(src, dir)
var/connected_dirs
GET_ZONE_NEIGHBOURS(T, connected_dirs)
if(connected_dirs && (dir & reverse_dir[connected_dirs]) == dir)
unconnected_dirs &= ~dir //they are, so unflag the cardinals in question
. &= ~dir //they are, so unflag the cardinals in question
//it is safe to remove src from the zone if all cardinals are connected by corner turfs
return !unconnected_dirs
. = !.
//helper for can_safely_remove_from_zone()
/turf/simulated/proc/get_zone_neighbours(turf/simulated/T)
. = 0
if(istype(T) && T.zone)
var/to_check = cardinal.Copy()
#ifdef MULTIZAS
to_check += list(UP, DOWN)
#endif
for(var/dir in to_check)
var/turf/simulated/other = get_step(T, dir)
if (istype(other) && other.zone == T.zone)
var/block
ATMOS_CANPASS_TURF(block, other, T)
if (!(block & AIR_BLOCKED) && get_dist(src, other) <= 1)
. |= dir
#undef GET_ZONE_NEIGHBOURS
/turf/simulated/update_air_properties()
@@ -202,21 +205,17 @@
SSair.connect(src, sim)
#ifdef ZASDBG
else if(verbose) log_debug("[d] has same zone.")
else if(verbose) log_debug("[d] has invalid zone.")
#endif
else
//Postponing connections to tiles until a zone is assured.
if(!postponed) postponed = list()
postponed.Add(unsim)
LAZYADD(postponed, unsim)
if(!TURF_HAS_VALID_ZONE(src)) //Still no zone, make a new one.
var/zone/newzone = new/zone()
var/zone/newzone = new
newzone.add(src)
#ifdef ZASDBG
@@ -227,7 +226,8 @@
//At this point, a zone should have happened. If it hasn't, don't add more checks, fix the bug.
for(var/turf/T in postponed)
for(var/thing in postponed)
var/turf/T = thing
SSair.connect(src, T)
/turf/proc/post_update_air_properties()
@@ -304,6 +304,7 @@
air.volume = CELL_VOLUME
/turf/simulated/proc/c_copy_air()
if(!air) air = new/datum/gas_mixture
air.copy_from(zone.air)
if(!air)
air = new /datum/gas_mixture
air.group_multiplier = 1
air.copy_from(zone.air, TRUE)

View File

@@ -16,6 +16,10 @@
#define TURF_HAS_VALID_ZONE(T) (istype(T, /turf/simulated) && T:zone && !T:zone:invalid)
#ifdef MULTIZAS
var/list/csrfz_check = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST, NORTHUP, EASTUP, WESTUP, SOUTHUP, NORTHDOWN, EASTDOWN, WESTDOWN, SOUTHDOWN)
var/list/gzn_check = list(NORTH, SOUTH, EAST, WEST, UP, DOWN)
#define ATMOS_CANPASS_TURF(ret,A,B) \
if (A.blocks_air & AIR_BLOCKED || B.blocks_air & AIR_BLOCKED) { \
ret = BLOCKED; \
@@ -66,6 +70,9 @@
}
#else
var/list/csrfz_check = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
var/list/gzn_check = list(NORTH, SOUTH, EAST, WEST)
#define ATMOS_CANPASS_TURF(ret,A,B) \
if (A.blocks_air & AIR_BLOCKED || B.blocks_air & AIR_BLOCKED) { \
ret = BLOCKED; \

View File

@@ -167,11 +167,13 @@
new /obj/effect/decal/cleanable/blood/oil(src)
/turf/simulated/Destroy()
//Yeah, we're just going to rebuild the whole thing.
//Despite this being called a bunch during explosions,
//the zone will only really do heavy lifting once.
if (zone)
zone.rebuild()
// Try to remove it gracefully first.
if (can_safely_remove_from_zone())
c_copy_air()
zone.remove(src)
else // Can't remove it safely, just rebuild the entire thing.
zone.rebuild()
// Letting this timer continue to exist can cause runtimes, so we delete it.
if (unwet_timer)

View File

@@ -295,15 +295,17 @@
. += gas[g]
//Copies gas and temperature from another gas_mixture.
/datum/gas_mixture/proc/copy_from(const/datum/gas_mixture/sample)
// If fast is TRUE, use a less accurate method that doesn't involve list iteraton.
/datum/gas_mixture/proc/copy_from(const/datum/gas_mixture/sample, fast = FALSE)
gas = sample.gas.Copy()
temperature = sample.temperature
update_values()
if (fast)
total_moles = sample.total_moles
else
update_values()
return 1
//Checks if we are within acceptable range of another gas_mixture to suspend processing or merge.
/datum/gas_mixture/proc/compare(const/datum/gas_mixture/sample, var/vacuum_exception = 0)
if(!sample) return 0