Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
There are some procs in DM which add hidden internal references to objects, and said references in turn prevent graceful garbage collection. Specifically this applies to walk procs and perhaps some others that I'm not aware of. This little tidbit is not mentioned anywhere relevant and on large worlds, where a mishandled Del() call can take up to 3 seconds to complete, is a pain to deal with manually.

As such, it might be worth having these internal references clean themselves up properly. It would require 1 pointer per atom/movable (actor to subject) and 1 pointer per atom (subject to actor). Or, to save space, two associative lists for this. The latter would probably be much more memory optimal, as walk is not used that often, when speaking relatively.

As to why specifically handle these procs, instead of just adding better GC everywhere? Because it's easier and this is a very snide issue in my opinion. If their creation and handling is abstracted behind walk and other procs, then their clean-up should also be abstracted. It's also kind of silly, having to write MSVC/modern C style wrappers for old, unsafe functions (think sprintf_s).
In the internal deletion routine, walker references are cleared out.

When you refer to a mishandled Del(), do you mean a Del() override when the programmer doesn't call ..()? Because that's always going to cause issues.
mishandled Del() means where all references aren't cleared by the time ..() is called.

The lag from finding references to null out can hit the seconds range per del() call on big projects.

In response to Lummox JR
Lummox JR wrote:
In the internal deletion routine, walker references are cleared out.

Are they cleared out in the way all other dangling references are cleared out, or in a more specific, faster way? Because the former is the issue in question: as MSO stated, large projects can see upwards of 3 and more seconds of stalling due to BYOND's GC going through all potential references in the game world in order to locate what's left to null.

Specifically, there was a point where mobs did not gracefully delete on Aurora. One of the sources that we identified as a potential issue was the usage of walk() and friends in our AI mobs. So we started poking walk(src, null) into the delete chains.

Though, if they're already handled differently, then disregard this request.
Probably the simplest example of why this is needed is the 5-minute unclearable reference to anything that was the argument of a verb (or had one of its verbs? I forget now). I'm sure there's lots of other hidden references floating around. Just exposing these references would be enough if the autoclear idea wouldn't feasibly cover all use cases.
Walker references are cleared out long before any garbage scanning is done. In fact they're cleared before the obj or mob is even moved to a null location.

I don't know what you mean by a 5-minute unclearable reference to something that was used in an argument. That's not a thing on the server.
In response to MrStonedOne
Ohh. Sheesh, it's been so long since I ran across that that I completely forgot about it.

I can see what's involved in changing that behavior so those AddClientRef() references get deleted before searching vars.
I was looking at where the refs from AddClientRef() are stored, and I think that's a possible dead end too.

After the garbage collector scans through some world vars (e.g., world.status, etc.), it looks at the clients as the very first thing. It scans some of the built-in vars, then the soft vars, more built-ins, then the owned_refs list (a linked list), then more built-ins. So it looks at all the clients before it starts exhaustively looking through the world for references.

The only way I can picture this being a problem is if owned_refs gets really, really large. I grant that's a possibility in SS13, but it seems kind of unlikely that it would explain any serious performance hit.

From my examination of owned_refs, however, it could probably use some retooling. Linked lists really aren't ideal if the size of this list gets large, and also AddClientRef() itself can be slow to add data because it has to scan the whole list for current values. That might also explain some issues that have been reported with right-click menus.
I went looking in my notes on this, and the only hint I have to a nonoptimal bit of del is a note about how a thing with alot of contents that wasn't getting cleared out before being deleted took forever to delete (47 seconds) but to be fair this was a minigun that held 1000 bullets in it's inventory for some fucking reason so i don't know what the coder who coded that was expecting.