ID:2173365
 
Applies to:Dream Daemon
Status: Open

Issue hasn't been assigned a status value.
I had quite possibly the worst experience in all my time coding for byond about a week ago. To put a long story short, I spent three whole, full, days trying to discover why my code wasn't working, as the list seemed to disappear for some reason. I got closer and closer, adding logs, recompiling. I even created a backup list, to no avail - it would disappear at the same time. I created a test environment to reproduce it - nothing. I tried a lot of things (including commenting out our error handler to see the raw runtime data), and none of them worked.

It turns out byond ran out of lists. Now, I'm sure there's perfectly reasonable explanations for this. Personally, after three days straight, I'd have accepted Lummox saying the moons weren't aligned right as an explanation.

But, in order to save people in the future from experiencing the pain I suffered, can you please have a warning come in dream daemon when you run out of something? Even the simplest "You have ran out of lists!" would do. Because the cacophany of list related errors such as "bad list" and such did not get that point across at all.
Running out of lists isn't something that should even be readily achievable, given the sheer number of them allowed now. But DD does in fact have an overflow warning when you run out.

Far more likely is that you ran out of memory, and although DD has various warnings for that, it's possible to miss cases here and there. (Also pretty much every program in history has behaved erratically under those circumstances, for the same reason.) That's especially likely in SS13, especially in certain branches like tg that are known for being mondo ginormous.
Unless there's a memory overhead for creating lists, I'm certain a) I ran out and b) there was no warning, it just started to delete old lists

The issue was that every movable atom on our codebase for whatever god forsaken reason has three lists created on New() for an atom locking system, even if there's no conceivable way to lock on to it. I was creating a lot of movable atoms - procedurally generating a terrestrial map, but the test environments I created to reproduce it were capable of generating nearly three times more objects so I ruled out memory loss.

Furthermore, after removing the list creation on those objects it now works perfectly well.

Once I ran out, the only warning I got was "bad list" as far as I can remember.
In response to DrCelt
DrCelt wrote:
Unless there's a memory overhead for creating lists, I'm certain a) I ran out and b) there was no warning, it just started to delete old lists

Yes, there is always a memory overhead for creating lists. Even an empty list will still have to allocate a structure.

The issue was that every movable atom on our codebase for whatever god forsaken reason has three lists created on New() for an atom locking system, even if there's no conceivable way to lock on to it.

Good gads.
In response to Lummox JR
Yes, there is always a memory overhead for creating lists. Even an empty list will still have to allocate a structure.

Even so, would that explain the runtime errors I was getting such as "bad list" and such? The game would run afterwards, dream daemon wouldn't crash, but nothing would work which involved using lists afterwards. Plus, evven if that were the case, I still didn't get an error message saying dream daemon had run out of lists or out of memory or whatever.

Good gads.

I was understandably horrified when I discovered that.
In response to DrCelt
I assume you looked into lazy-loading those lists?
On /tg/ we've had a large push recently to lazy load as many lists as possible (great improvements to world loading times and memory usage)

our (ported from bay, but updated) buckling, similar to your generic locking system lazy loads it's list, because as above, having even one list on all movable atoms, that the vast majority won't ever even use it just disgusting.
More so for you poor guys having 3!
In response to CrimsonVision
I'm surprised you guys didn't push that a lot sooner. atom/New() and init procs are absoulte load time killers, and in a game like SS13 that's ruled by reboots, I would've expected nixing those to be first priority.
In response to Lummox JR
Well I'm with /tg/, and we've got some of (if not the) best server hardware out of the SS13 servers, so memory for us was less of a concern (still a concern however, gains to be made all round)

We've prioritised CPU over Memory in quite a few cases.
One such example would be something I call a "typecache",
a typecache is just a fancy name for an associative list where the keys are typepaths, and the values are TRUE.

this reduces something like:
/proc/is_type_in_list(atom/A, list/L)
for(var/path in L)
if(istype(A, L))
return TRUE
return FALSE

to
/proc/is_type_in_typecache(atom/A, list/T)
return T[A.type] //an invalid keylookup is null, and thus FALSE


This provides wonderful CPU benefits, since it reduces
N+1 proc calls down to 1 proc call (or none, if you were to make it a define) and an assoc lookup, the downside is that these can be quite big, given that they have to store a typepath and all its subtypes to work, usually with multiple "parent" paths in the same typecache.

Things like AI targeting benefited from this, as they frequently scan their environment for targets, being able to check if their target is valid or not quickly is beneficial.

tl;dr We neglected memory a bit due to our personal server circumstances and favoured CPU, but are now looking into lazy-loading lists wherever possible and such for memory gains.
In response to CrimsonVision
In a game like SS13, prioritizing CPU over memory is absolutely the right call.

My point is, though, avoiding the creation of unnecessary lists offers staggering benefits to both. SS13's startup time is poor, and in tg's case it's legendarily poor. Eliminating init procs and New() calls wherever possible offers drastic benefits to that problem, while also reducing memory at the same time.