Descriptive Problem Summary:
When used on /area, locate() takes significantly longer than expected to locate objects when the area is relatively full (one object per turf in a 50x50 area is more than enough). It locates them correctly, it merely takes a long time to do so. Defining a proc to loop over all turfs in an area, calling locate() on each, executes faster.
Numbered Steps to Reproduce Problem:
Create an area with at least ~250 objects in, and at least one of a specific type of object.
Call locate(TYPE) in AREA, observe that it takes potentially several seconds to execute.
Call locate(TYPE) in world, observe that it takes almost no time.
Call the below proc_locate(TYPE, AREA), observe that it also takes almost no time.
Code Snippet (if applicable) to Reproduce Problem:
/world
maxx=50
maxy=50
maxz=1
/world/New()
for(var/x = 1 to world.maxx)
for(var/y = 1 to world.maxy)
for(var/z = 1 to world.maxz)
new /obj(locate(x,y,z))
/obj/find
/proc/proc_locate(type, area/A)
for(var/turf/T in A)
. = locate(type) in T
if(.) return
/client/verb/test()
var/area/A = locate(/area)
var/obj/find
var/x = 1
var/y = 1
var/z = 1
for(var/i = 0 to 7)
if(i&1) x=world.maxx; else x=1
if(i&2) y=world.maxy; else y=1
if(i&4) z=world.maxz; else z=1
find = new /obj/find(locate(x,y,z))
var/start = world.timeofday
var/t = locate(/obj/find) in A
var/end = world.timeofday
world << "locate at [x],[y],[z] took [end-start] ds (found [t])"
start = world.timeofday
t = proc_locate(/obj/find, A)
end = world.timeofday
world << "proc_locate at [x],[y],[z] took [end-start] ds (found [t])"
del(find)
Output of the above code on my machine (with the duplicate min-z and max-z results removed):
locate at 1,1,1 took 0 ds (found the find)
proc_locate at 1,1,1 took 0 ds (found the find)
locate at 50,1,1 took 4 ds (found the find)
proc_locate at 50,1,1 took 0 ds (found the find)
locate at 1,50,1 took 228 ds (found the find)
proc_locate at 1,50,1 took 0 ds (found the find)
locate at 50,50,1 took 233 ds (found the find)
proc_locate at 50,50,1 took 0 ds (found the find)
In a table:
x | y | locate() (seconds) | proc_locate() (seconds) |
1 | 1 | 0 | 0 |
max | 1 | 0.4 | 0 |
1 | max | 22.8 | 0 |
max | max | 23.3 | 0 |
Expected Results: locate() in area would be as fast as if not faster than an equivalent proc that loops over turfs in the area and calls locate() in turf on them
Actual Results: locate() in area is incredibly slow.
Does the problem occur:
Every time? Or how often? Every time
In other games? Not relevant
In other user accounts? Unknown
On other computers? Unknown
When does the problem NOT occur? When using proc_locate(), or when not using locate() to search areas
Did the problem NOT occur in any earlier versions? If so, what was the last version that worked? Unknown
Workarounds: Use proc_locate() for searching areas.
I would however recommend retesting this in a way that runs tests on the same object and proc multiple times through a loop and accumulates the results, because the timer resolution is not very high.