Baby's First Garbage Collector (2013)
journal.stuffwithstuff.com
journal.stuffwithstuff.com
Otherwise, looks pretty good. Interestingly, this doesn't contain any unsafe code, probably because Rc and RefCell are doing the actual memory/safety management. Still, the purpose of this exercise is to focus on the mark-and-sweep part, and that seems to have been done pretty well here!
Thanks for your feedback :) I'd had it sitting there for a while with no idea if it was any good or not.
> I think would be safe (only) if the application is single-threaded.
Unfortunately, it's not that easy: http://manishearth.github.io/blog/2015/05/17/the-problem-wit...RefCell and the "no mutable aliasing" isn't something to be "worked around", it's something to embrace, because safety and many other things come from it.
Now all those regions of code where "we can muck with this object before returning it because we know GC isn't running, because we don't call any allocation functions that can trigger GC" have to be locked down. (Among other problems to solve, like that a thread can be doing anything when you pause it.)
Basically, once we had a GC design that was "safe" (In Rust terms; i.e. can't be used in safe Rust to trigger memory or thread unsafety), making GCd objects passable between threads was a clean, logical extension of the existing model.
This is probably because Rust's safety model in a single threaded situation is very close to what you need for multithreaded safety too.
[1]: however it gets tricky again if you want to avoid pausing threads as much as possible (i.e. only pause on a GC mutation).
Are there any languages that gc every tick?
To allocate an object, you just increment the pointer by the size of the object being allocated and return the previous value. In other words, you just hand out some bytes and move the pointer just past them.
When the frame is done, to "free" all of those objects... just reset the pointer. Done.
But, to your original question, it's almost always a bad idea to run your GC every tick or some other high frequency like that. GCs spend a certain amount of time visiting objects that are still in use. Doing that work over and over and over again burns tons of cycles for no point. To get the best overall performance, you want to do as few GCs as possible to minimize that redundant work.
The problem then is that when you wait a long time, you end up having to a big, slow GC and long pauses like that are a problem. Incremental and concurrent GCs avoid long pauses and give you smoother results, at the expense of slightly lower overall performance. They get better latency but worse throughput.