Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes most 'abnormal' lag caused by processing subsystems. #4538

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions code/__DEFINES/MC.dm
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ if (Datum.is_processing) {\
Processor.processing += Datum;\
}

//stopProcessingWrapper catches removal from processing list before it happens to adjust last position in memory during resumes
#define STOP_PROCESSING(Processor, Datum) \
if(Datum.is_processing) {\
Processor.stopProcessingWrapper(Datum);\
if(Processor.processing.Remove(Datum)) {\
Datum.is_processing = null;\
} else {\
Expand Down
1 change: 0 additions & 1 deletion code/__DEFINES/subsystems.dm
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ if (Datum.is_processing) {\
//stopProcessingWrapper catches removal from processing list before it happens to adjust last position in memory during resumes
#define STOP_PROCESSING_IN_LIST(Datum, List) \
if(Datum.is_processing) {\
SSmachines.stopProcessingWrapper(Datum, SSmachines.List);\
if(SSmachines.List.Remove(Datum)) {\
Datum.is_processing = null;\
} else {\
Expand Down
153 changes: 48 additions & 105 deletions code/controllers/subsystems/machines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(machines)
var/list/power_objects = list()

var/list/processing
var/nextProcessingListPosition = 0 //position of next thing to be processed, inside of currently processed list
var/list/current_run = list()

/datum/controller/subsystem/machines/PreInit()
processing = machinery
Expand All @@ -34,14 +34,6 @@ SUBSYSTEM_DEF(machines)
fire()
..()

/datum/controller/subsystem/machines/stopProcessingWrapper(var/D, var/list/L = processing) //called before a thing stops being processed
if (!nextProcessingListPosition) //0 position means currently processed list is not paused or running, no point in adjusting last position due to removals from list
return
var/position = L.Find(D) //find exact position in list
if (position)
if (position < nextProcessingListPosition) //removals from list are only relevant to currently processed position if they are on the left side of it, otherwise they do not alter order of processing
nextProcessingListPosition-- //adjust current position to compensate for removed thing

#define INTERNAL_PROCESS_STEP(this_step, check_resumed, proc_to_call, cost_var, next_step)\
if(current_step == this_step || (check_resumed && !resumed)) {\
timer = TICK_USAGE_REAL;\
Expand Down Expand Up @@ -119,114 +111,65 @@ datum/controller/subsystem/machines/proc/setup_atmos_machinery(list/machines)

/datum/controller/subsystem/machines/proc/process_pipenets(resumed = 0)
if (!resumed)
nextProcessingListPosition = 1 //fresh start, otherwise from saved posisition

//localizations
var/list/local_list = pipenets
var/datum/pipe_network/thing
var/wait = src.wait

var/tickCheckPeriod = round(local_list.len/16+1) //pause process at most every 1/16th length of list
while(nextProcessingListPosition && (nextProcessingListPosition <= local_list.len)) //until position is valid
thing = local_list[nextProcessingListPosition]
nextProcessingListPosition++

if(!QDELETED(thing))
thing.Process(wait)
else
local_list.Remove(thing)
thing.is_processing = null
nextProcessingListPosition-- //removing processed thing from list moves the queue to the left, adjust accordingly
src.current_run = pipenets.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
while(current_run.len)
var/datum/pipe_network/PN = current_run[1]
current_run.Cut(1, 2)
if(istype(PN) && !QDELETED(PN))
PN.Process(wait)
pipenets.Remove(PN)
PN.is_processing = null
if(MC_TICK_CHECK)
return

if(!(nextProcessingListPosition%tickCheckPeriod)) //pauses only every tickCheckPeriod-th processed thing
if (MC_TICK_CHECK)
return

nextProcessingListPosition = 0 //entire list was processed

/datum/controller/subsystem/machines/proc/process_machinery(resumed = 0)
if (!resumed)
src.nextProcessingListPosition = 1 //fresh start, otherwise from saved posisition

//localizations
var/list/local_list = machinery
var/obj/machinery/thing
var/wait = src.wait
var/nextProcessingListPosition = src.nextProcessingListPosition
if(!nextProcessingListPosition)
return

var/tickCheckPeriod = round(local_list.len/16+1) //pause process at most every 1/16th length of list
while(nextProcessingListPosition <= local_list.len) //until position is valid
thing = local_list[nextProcessingListPosition]
nextProcessingListPosition++

if(!QDELETED(thing) && (thing.Process(wait) != PROCESS_KILL))
if(thing.use_power)
thing.auto_use_power()
else
local_list.Remove(thing)
thing.is_processing = null
nextProcessingListPosition-- //removing processed thing from list moves the queue to the left, adjust accordingly

if(!(nextProcessingListPosition%tickCheckPeriod)) //pauses only tickCheckPeriod-th processed thing
if (MC_TICK_CHECK)
src.nextProcessingListPosition = nextProcessingListPosition
return

src.nextProcessingListPosition = 0 //entire list was processed
src.current_run = machinery.Copy()

var/list/current_run = src.current_run
while(current_run.len)
var/obj/machinery/M = current_run[1]
current_run.Cut(1, 2)
if(istype(M) && !QDELETED(M) && !(M.Process(wait) == PROCESS_KILL))
if(M.use_power)
M.auto_use_power()
machinery.Remove(M)
M.is_processing = null
if(MC_TICK_CHECK)
return

/datum/controller/subsystem/machines/proc/process_powernets(resumed = 0)
if (!resumed)
nextProcessingListPosition = 1 //fresh start, otherwise from saved posisition

//localizations
var/list/local_list = powernets
var/datum/powernet/thing
var/wait = src.wait

var/tickCheckPeriod = round(local_list.len/16+1) //pause process at most every 1/16th length of list
while(nextProcessingListPosition && (nextProcessingListPosition <= local_list.len)) //until position is valid
thing = local_list[nextProcessingListPosition]
nextProcessingListPosition++
src.current_run = powernets.Copy()

if(!QDELETED(thing))
thing.reset(wait)
else
local_list.Remove(thing)
thing.is_processing = null
nextProcessingListPosition-- //removing processed thing from list moves the queue to the left, adjust accordingly
var/list/current_run = src.current_run
while(current_run.len)
var/datum/powernet/PN = current_run[1]
current_run.Cut(1, 2)
if(istype(PN) && !QDELETED(PN))
PN.reset(wait)
powernets.Remove(PN)
PN.is_processing = null
if(MC_TICK_CHECK)
return

if(!(nextProcessingListPosition%tickCheckPeriod)) //pauses only every tickCheckPeriod-th processed thing
if (MC_TICK_CHECK)
return

nextProcessingListPosition = 0 //entire list was processed

/datum/controller/subsystem/machines/proc/process_power_objects(resumed = 0)
if (!resumed)
nextProcessingListPosition = 1 //fresh start, otherwise from saved posisition

//localizations
var/list/local_list = power_objects
var/obj/item/thing
var/wait = src.wait

var/tickCheckPeriod = round(local_list.len/16+1) //pause process at most every 1/16th length of list
while(nextProcessingListPosition && (nextProcessingListPosition <= local_list.len)) //until position is valid
thing = local_list[nextProcessingListPosition]
nextProcessingListPosition++

if(!thing.pwr_drain(wait)) // 0 = Process Kill, remove from processing list.
local_list.Remove(thing)
thing.is_processing = null
nextProcessingListPosition-- //removing processed thing from list moves the queue to the left, adjust accordingly

if(!(nextProcessingListPosition%tickCheckPeriod)) //pauses only every tickCheckPeriod-th processed thing
if (MC_TICK_CHECK)
return

nextProcessingListPosition = 0 //entire list was processed
src.current_run = power_objects.Copy()

var/list/current_run = src.current_run
while(current_run.len)
var/obj/item/I = current_run[current_run.len]
current_run.len--
if(!I.pwr_drain(wait)) // 0 = Process Kill, remove from processing list.
power_objects.Remove(I)
I.is_processing = null
if(MC_TICK_CHECK)
return

/datum/controller/subsystem/machines/Recover()
if (istype(SSmachines.pipenets))
Expand Down
41 changes: 10 additions & 31 deletions code/controllers/subsystems/processing/processing.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,28 @@ SUBSYSTEM_DEF(processing)

var/debug_last_thing
var/debug_original_process_proc // initial() does not work with procs
var/nextProcessingListPosition = 0 //position of next thing to be processed, inside of currently processed list

/datum/controller/subsystem/processing/stopProcessingWrapper(var/D) //called before a thing stops being processed
if (!nextProcessingListPosition) //0 position means currently processed list is not paused or running, no point in adjusting last position due to removals from list
return
var/position = processing.Find(D) //find exact position in list
if (position)
if (position < nextProcessingListPosition) //removals from list are only relevant to currently processed position if they are on the left side of it, otherwise they do not alter order of processing
nextProcessingListPosition-- //adjust current position to compensate for removed thing
var/list/current_run = list()

/datum/controller/subsystem/processing/stat_entry()
..(processing.len)

/datum/controller/subsystem/processing/fire(resumed = 0)
if (!resumed)
src.nextProcessingListPosition = 1 //fresh start, otherwise from saved posisition

//localizations
var/times_fired = src.times_fired
var/list/local_list = processing
var/datum/thing
src.current_run = processing.Copy()
//cache for sanic speed (lists are references anyways)
var/list/current_run = src.current_run
var/wait = src.wait
var/nextProcessingListPosition = src.nextProcessingListPosition
if(!nextProcessingListPosition)
return

var/tickCheckPeriod = round(local_list.len/16+1) //pause process at most every 1/16th length of list
while(nextProcessingListPosition <= local_list.len) //until position is valid
thing = local_list[nextProcessingListPosition]
nextProcessingListPosition++
var/times_fired = src.times_fired

while(current_run.len)
var/datum/thing = current_run[1]
current_run.Cut(1, 2)
if(QDELETED(thing) || (call(thing, process_proc)(wait, times_fired, src) == PROCESS_KILL))
if(thing)
thing.is_processing = null
processing -= thing
nextProcessingListPosition-- //removing processed thing from list moves the queue to the left, adjust accordingly

if(!(nextProcessingListPosition%tickCheckPeriod)) //pauses only every tickCheckPeriod-th processed thing
if (MC_TICK_CHECK)
src.nextProcessingListPosition = nextProcessingListPosition
return

src.nextProcessingListPosition = 0 //entire list was processed
if (MC_TICK_CHECK)
return

/datum/controller/subsystem/processing/proc/toggle_debug()
if(!check_rights(R_DEBUG))
Expand Down