ID:2489419
 
(See the best response by Kaiochao.)
Code:
atom/proc
Process_Environmentals() // main procedure to handle atmos
//set background = 1
spawn while(src)
if(block_air_calc || temp == DEFAULT_TEMP) // if block air calc is flagged, then do not simulate heat transfer
sleep(20)
continue
else
var/CONTROL=0 // this redundant block air calc check is contributing slightly to increased cpu usage
for(var/obj/A in src.loc)
if(A.block_air_calc)CONTROL=1
else continue

if(!CONTROL)
if(temp < DEFAULT_TEMP)
temp = DEFAULT_TEMP
else
temp-=0.10 // bleed off temp slowly, if no heat source is present, heat will dissipate over time
Thermal_Leak_Detect()
Heat_Transfer()
else
sleep(20)
continue
sleep(20)


Problem description:
Well my question is, when calling a loop like so spawn while(src), is there a way to include the delay in the same line, so that within the loop if a situation occurs where continue is called, i don't need to also call sleep() before hand?

Recently during some testing i noticed that with a large number of objects present in the world that have to calculate heat transfer, via the snippet above, there was high cpu usage. Right now im running the heat transfer calculations all the time just to test efficiency, once its all said and done the loop will only run while a player or players offline mob is in range, may also adjust delay and heat bleed off rate in favor of cpu usage.
this is a project i've been working on for roughly 6 years, finally pushed it to a alpha playable state and im really hoping to rent a server next month and host some public testing, just need to nail any possible high cpu situations that i haven't run into while solo testing with just a small test map.


I see no need to use continue in this entire snippet.

Even the for() should be breaking when CONTROL=1 happens, not continuing when it doesn't happen.

The first if() can just be inverted.

If you just let the code naturally fall out of the conditions, it'll reach the final sleep(20) and repeat as normal anyways.

Otherwise, you could just have the sleep(20) at the top, I guess.
In response to Kaiochao
Kaiochao wrote:
I see no need to use continue in this entire snippet.

Even the for() should be breaking when CONTROL=1 happens, not continuing when it doesn't happen.

The first if() can just be inverted.

If you just let the code naturally fall out of the conditions, it'll reach the final sleep(20) and repeat as normal anyways.

Otherwise, you could just have the sleep(20) at the top, I guess.

I actually had it fall out of conditions but for some reason i assumed that would use more cpu, i'll try rewriting my logic in the method you described and see what happens, thank you.
atom/proc
Process_Environmentals() // main procedure to handle atmos
//set background = 1
spawn while(src) // || !temp == DEFAULT_TEMP
if(!block_air_calc) // if block air calc is flagged, then do not simulate heat transfer
var/CONTROL=0 // this redundant block air calc check is contributing slightly to increased cpu usage
for(var/obj/A in src.loc)
if(A.block_air_calc)
CONTROL=1
break
if(!CONTROL)
if(temp < DEFAULT_TEMP)
temp = DEFAULT_TEMP
else
temp-=0.10 // bleed off temp slowly, if no heat source is present, heat will dissipate over time
Thermal_Leak_Detect()
Heat_Transfer()
sleep(20)

Would this be the correct way to invert my first if statement?

the || !temp == DEFAULT_TEMP is commented out of the first if() statement for now just to force a loaded situation during testing
!temp == DEFAULT_TEMP does not mean the same thing as temp != DEFAULT_TEMP. The ! operator binds tighter.
In response to MightyMonte88
Best response
It can help readability to split things into separate procs:
atom/proc
Process_Environmentals()
while(src)
if(CanAirCalc())
AirCalc()
sleep(20)

CanAirCalc()
if(temp < DEFAULT_TEMP)
return FALSE

for(var/obj/a in bounds())
if(a.block_air_calc)
return FALSE

return TRUE

AirCalc()
temp = max(temp - 0.10, DEFAULT_TEMP)
Thermal_Leak_Detect()
Heat_Transfer()

Some would tell you to avoid this because it's inefficient, but really you shouldn't worry about efficiency until you have something that works. In this case, the code flow is easier to see when it's split up in this way, I think.

Also, I believe spawn() should be used to call procs that take time, if you don't want the caller to wait for them; not inside the procs themselves. If you always follow this rule of thumb, then you'll always have the option of doing things in the caller, after the procs that take time are finished.
When it comes to something that's likely to run frequently or in a tight loop, though, the adage about not worrying about optimization too early doesn't always fly. Sometimes it's important to get it right, or at least right-ish, on the first try to avoid a painful refactor.
Thanks guys i really appreciate the input, was a big help.