Performance degredation with lists with a large amount of items whether adding to, removing from, or just looping through.
Numbered Steps to Reproduce Problem:
make a large list, profile a loop through it, split said list up into chunks and profile the loops.
Code Snippet (if applicable) to Reproduce Problem:
world
loop_checks = 0
var/global/list/one = list()
var/global/list/two = list()
var/global/list/three = list()
var/global/list/four = list()
var/global/list/five = list()
var/global/list/six = list()
var/global/list/seven = list()
var/global/list/eight = list()
var/global/list/nine = list()
var/global/list/ten = list()
var/global/list/eleven = list()
var/global/list/listone = list()
var/global/list/listtwo = list()
var/global/list/listthree = list()
var/global/list/listfour = list()
var/global/list/listfive = list()
var/global/list/listsix = list()
var/global/list/listseven = list()
var/global/list/listeight = list()
var/global/list/listnine = list()
var/global/list/listten = list()
var/global/list/listeleven = list()
verb/test_list()
var/start = world.timeofday
//world << "starting at [start]"
var/n = 1
for(var/i = 1 to 2600000)
listone += i
if(n != 10 && !(i % 260000))
//world << "Hit milestone [i] in [((world.timeofday - start)/10)] second\s"
n++
switch(n)
if(1)
listtwo += i
if(2)
listthree += i
if(3)
listfour += i
if(4)
listfive += i
if(5)
listsix += i
if(6)
listseven += i
if(7)
listeight += i
if(8)
listnine += i
if(9)
listten += i
if(10)
listeleven += i
var/startone = world.timeofday
//world << "starting processing of list one at [startone] total of [((world.timeofday - start)/10)] second\s have passed"
process_list_one()
//world << "finished list one in [((world.timeofday - startone)/10)] second\s; total of [((world.timeofday - start)/10)] second\s have passed"
startone = world.timeofday
//world << "starting processing of list one at [startone] total of [((world.timeofday - start)/10)] second\s have passed"
process_list_two()
//world << "finished list two in [((world.timeofday - startone)/10)] second\s; total of [((world.timeofday - start)/10)] second\s have passed"
/proc/process_list_one()
for(var/ii in listone)
one += ii
/proc/process_list_two()
var/starttime = world.timeofday
var/i
var/substart = world.timeofday
for(i in listtwo)
two += i
//world << "finished sub list one in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listthree)
three += i
//world << "finished sub list two in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listfour)
four += i
//world << "finished sub list three in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listfive)
five += i
//world << "finished sub list four in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listsix)
six += i
//world << "finished sub list five in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listseven)
seven += i
//world << "finished sub list six in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listeight)
eight += i
//world << "finished sub list seven in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listnine)
nine += i
//world << "finished sub list eight in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listten)
ten += i
//world << "finished sub list nine in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
substart = world.timeofday
for(i in listeleven)
eleven += i
//world << "finished sub list ten in [((world.timeofday - substart)/10)] second\s; total of [((world.timeofday - starttime)/10)] second\s have passed"
Expected Results:
similar performance
Actual Results:
Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
---------------------- --------- --------- --------- ---------
/mob/verb/test_list 20.202 39.803 39.803 1
/proc/process_list_one 17.912 17.912 17.913 1
/proc/process_list_two 1.689 1.689 1.690 1
Does the problem occur:
every time with large lists
When does the problem NOT occur?
When the list is split up into smaller chunks
Workarounds:
make a lot of smaller lists.
Reason i bothered testing for this is we are wanting to increase map size to 500x500x6 but looping through turfs causes infinite loop errors resulting in poor performance and eventually a non working proc.
edit: processing only the list chunks in the example, IE commenting out the references to listone and process_list_one(), i get this
Profile results (total time)
Proc Name Self CPU Total CPU Real Time Calls
---------------------- --------- --------- --------- ---------
/mob/verb/test_list 2.164 3.713 3.713 1
/proc/process_list_two 1.549 1.549 1.549 1