The in operator performs poorly compared to list.Find when used against datum.vars, with increasing penalty as the var name to find falls later in the list (or worst case, isn't present).
That is:
if ("foo" in some_datum.vars)
is dramatically slower than
if (some_datum.vars.Find("foo"))
For the code snippet, runs on my hardware (bigger is better) were
test_find_type 156 test_find_type 162 test_find_type 164 test_in_type 84 test_in_type 82 test_in_type 81 test_find_pixel_y 161 test_find_pixel_y 165 test_find_pixel_y 162 test_in_pixel_y 6 test_in_pixel_y 6 test_in_pixel_y 6 test_find_hogwash 157 test_find_hogwash 163 test_find_hogwash 155 test_in_hogwash 3 test_in_hogwash 3 test_in_hogwash 3
(with the last actually being closer to 2, but the test format will always round up)
Code Snippet (if applicable) to Reproduce Problem:
/world/loop_checks = FALSE
var/list/mobs = new (1000)
/world/New()
..()
for (var/i in 1 to 1000)
mobs[i] = new /mob
/mob/Login()
..()
// Mob vars order dump. type is first, pixel_y is middle-ish
//usr << "[json_encode(src.vars)]"
/mob/verb/test_find_type()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = entry.vars.Find("type")
++count
usr << "test_find_type [count]"
/mob/verb/test_find_pixel_y()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = entry.vars.Find("pixel_y")
++count
usr << "test_find_pixel_y [count]"
/mob/verb/test_find_hogwash()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = entry.vars.Find("hogwash")
++count
usr << "test_find_hogwash [count]"
/mob/verb/test_in_type()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = ("type" in entry.vars)
++count
usr << "test_in_type [count]"
/mob/verb/test_in_pixel_y()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = ("pixel_y" in entry.vars)
++count
usr << "test_in_pixel_y [count]"
/mob/verb/test_in_hogwash()
var/temp
var/count = 0
var/done = world.timeofday + 10
while (world.timeofday < done)
for (var/mob/entry as anything in mobs)
temp = ("hogwash" in entry.vars)
++count
usr << "test_in_hogwash [count]"
Expected Results:
I would hope for ("name" in datum.vars) to match or beat datum.vars.Find("name")
Actual Results:
I managed to turn a 2 second unit test into a 7 minute unit test by changing Find to in.
For a best case scenario ("type", as above), about half as good.
Does the problem occur:
Every time? Or how often? Y
In other games? Y
In other user accounts? Y
On other computers? Y
When does the problem NOT occur?
N
Did the problem NOT occur in any earlier versions? If so, what was the last version that worked?
It's observable in the latest 516, 515. I didn't try earlier.
Workarounds:
Use datum.vars.Find("name") instead of ("name" in datum.vars)
Adding this after I was poked to try, just because the . accessor isn't involved.