Mission Control - Om has a problem.

Published January 05, 2017
Advertisement

I realised today why JavaScript doesn't have deterministic destruction. Thought I was so smart basing Om around it.

Cycles.

If one object A references an object B and B references A, Om will never release the entities when they go out of scope. Memory leaks.

This is a well enough studied problem to assume there is no available solution. So where does this leave Om?

It is hardly worth turning it into a garbage collected language. That defeats the whole point of the language in the first place.

Equally, it is too easy to accidentally create cycles, especially with long chains of objects or lists, to just say "Don't do this in Om or you leak memory". I would lose all heart in the project then.

So we are in a quandary. Maybe have to toast an interesting project goodbye and move on.

What really hurts is whenever I go online to research this, everyone is describing the approach I have been using for the last few years as naive :)

To be fair, most of the recent work on Om has been copy-pasting code from version 3 into version 4, so in a way it is nice to have a new problem to think about. Toying with the idea of a hybrid system that does strict reference counting unless it (somehow) detects cycles then falls back on asynchronous garbage collection. I see other languages have accepted this. A real shame though. But I'm unlikely to be the first living human to find a better solution, frankly. I'm good enough at what I do to be sure of that much.

Any suggestions from the floor?

[EDIT] It is even worse than I thought, with lists.

var o = [ ];var n = [ o ];o.push(n);When I try to output the state at the end of the program now, we get an infinitely recursive loop going on until Om runs out of stack space.

This is pretty much impossible to detect. Easy enough in a silly example like this, but a general solution just doesn't exist I don't think.

I'm pretty much starting to lean towards just making it a rule that circular references can cause memory leaks or infinite loops and leaving it at that at the moment. Leaves a bad taste in my mouth but I'm not sure what else I can do.

0 likes 5 comments

Comments

ApochPiQ
I feel like this can be solved with judicious use of weak-reference semantics, but I'm a little fuzzy on the specifics off the top of my head.

I know deterministic destruction in the presence of cycles is possible because I've used languages that do it. There are undoubtedly tradeoffs, but they can be well worth it for many types of programs.
January 05, 2017 09:35 PM
Aardvajk

I feel like this can be solved with judicious use of weak-reference semantics, but I'm a little fuzzy on the specifics off the top of my head.

I know deterministic destruction in the presence of cycles is possible because I've used languages that do it. There are undoubtedly tradeoffs, but they can be well worth it for many types of programs.


Cheers ApochPiQ, I was thinking about weak references earlier on, but I'm not sure how to apply it in the context of my language.
January 05, 2017 09:45 PM
Aardvajk

Hmm, this looks interesting:

http://www.arctrix.com/nas/python/gc/

This will clearly be the way to go if I decide to carry on with a hybrid system. Guess that as long as non-cyclic objects are destroyed in a deterministic way, I can live with it. The rule would just be that if you do create cycles, you cannot guarantee deterministic destruction for the objects involved in the cycles.

Need to sleep on this one.

January 05, 2017 10:21 PM
dmatter

For breaking reference cycles the classic solution is weak references. Swift does that using the 'weak' keyword: weak var x

Of course, it's up to the coder to get that right, otherwise they leak memory.

The only other alternative I can think of (that doesn't involve a GC) is that when you decrement a reference count you have to BFS crawl the reference graph outwards from that object until you find a reference that's held by a var on the stack. If there is no such var then the whole thing is now an unowned 'island' and you release the whole lot.

January 05, 2017 10:42 PM
Aardvajk

Hey dmatter. Thanks for the post.

The problem with your second point is that, in Om, an entity can also be held by a C++-side Om::Value, so would need to check to see if any of those existed as well. That would involve storing a list of all the created Om::Values in the State somewhere - pretty yucky.

I just don't know.

January 06, 2017 07:18 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement