One of the more interesting avenues of research, especially in mobile devices where you don't want to pay the power cost of having a 2x larger heap your live size, are various hybrids of garbage collection and reference counting. A neat, easy to understand one is: http://users.cecs.anu.edu.au/~steveb/downloads/pdf/rcix-oops....
Also interesting is what you can do when you have more information about what pointers can point to (as in Rust). It's not so much that reference counting in Rust is cheap, but that the language offers a lot of tools to let you avoid reference counted pointers in the first place, in favor of references with static lifetime guarantees.
[1] What Swift or Obj-C do when you overwrite a pointer-valued field is to do a objc_release() for the old pointer, and a objc_retain() for the new pointer. If two threads write to a field at the same time, you can corrupt the reference count (even if the objc_release()/objc_retain() operations are themselves atomic!) As far as I know, Apple's obj-c runtime does not attempt to handle this situation. See: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#o....
IMO, more languages shouldn't assume that there is a single memory allocator. That's one of the worst assumptions I see in systems languages -- even C++ (before C++11) got this entirely wrong. Swift gets this wrong, Go gets this wrong. Rust is probably a little better because it actually has a static idea of memory scope, but I haven't seen a way to swap out the memory allocator in various contexts.
Most projects I've been involved with have used region/arena allocators. Not only do you mostly avoid the non-determism of your average GC, but you avoid the hassle of fine grained reference counting (in most cases). This relies on you choosing the scopes for your regions appropriately, but there usually is a clear scope to attach things to (e.g. frames, iteration of an event loop, etc.).
http://wiki.luajit.org/New-Garbage-Collector
Exist some pre-madethat can be used for a new project, for use with LLVM or luajit?
You mean something like this?
https://github.com/rust-lang/rfcs/pull/244
I think part of it was inspired by something similar from C++. D-lang also seems to have something like this.
That said, by C++03, most STL implementations supported stateful allocators (and that's what I've used when I've had to use C++), but the standard took a while to catch up.
Does ARC allow moving? If not, what happens when your heap becomes fragmented? Isn't that a downside?
Another downside is that many lock-free data-structures require a GC.
An unfortunately common symptom of large C++ applications is that they take forever to shut down because they insist on calling destructors on everything in the known universe. In reality, most applications only have a tiny handful of resources that you truly have to release yourself at shut down, and memory certainly is not one of them.
Is not circular references the real problem? And what when the object reference a resource like a file/handle/database/etc?
So, could be good idea to mark objects like this (maybe in separated areas of memory?):
Instant kill: Ints, Strs, Bools, Array of all of this
Safe destructors: If it hold a resource (file, handle)
But don't know what to do for objects like Customer.Orders = List<Orders>[Order1.Customer]
You just have to be aware what happens in the destructor when you manually free an object. Libraries can make knowing this more difficult.
I guess you could build incremental alloc/release pools (even with reuse) or such things but it comes down to being aware of the problem as described and avoiding cascaded releases.
And to be honest this is not a super common problem but it can happen.
http://lambda-the-ultimate.org/node/2552
(Although I think the paper has problems and bias)
Another trouble is the cache pollution.
Doesn't reference counting typically have a worse throughput than garbage collection? That's what I've read anyway.
On servers, that's fine.
On my phone, I'll take lower memory usage and predictable latency any day.
Yay refcounting.
What algorithm are you referring to when you say "better throughput at the expense of significantly increased memory usage"?
Also, why is unpredictable latency acceptable for you on servers but not phones? Wouldn't a latency spike on remote requests from an application degrade user experience just as much as if that latency were localized to the phone?
Here's a discussion of the particular paper behind that statement: [1]
I'd also like to recommend the paper "A Unified Theory of Garbage Collection" [2] that breaks down the divide between GC and refcounting. There is a lot of gray area between tracing GC and refcounting. You can make different tradeoff decisions in different parts of your collection algorithm. But fundamentally it breaks down to time-space tradeoffs—you want to save time and get throughput, you're gonna eat some extra space.
> Also, why is unpredictable latency acceptable for you on servers but not phones? Wouldn't a latency spike on remote requests from an application degrade user experience just as much as if that latency were localized to the phone?
We as developers make UI efforts to mitigate network unreliability (fallacy #1 of distributed computing: the network is reliable) so it's ok if a server is being temporarily shitty. It's a lot harder to keep responsive, smooth UI behavior in the face of dropped frames and long GC pauses.
[1] http://stackoverflow.com/questions/2982325/quantifying-the-p...
[2] http://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
When creating Unity3D games, you have to be reasonably careful about garbage collection - lots of nasty performance dips result if you assume that it just works. Generally you have to cobble together a mixture of object pools and statements attempting to force collection at a convenient point in the game flow amongst other things. It would be quite nice if you could turn it off for specific portions of code :)
I suspect to get anything more detailed you may have to purchase a paid report from one of the various analytics companies.
Sorry, I've wandered rather off topic...
This can only be solved by either doing stack allocation or by building object pools. And this is for people that know what they are doing.
Rust is the only language (I know) that tries solving this with the ownership concept in the language, but then Rust will have problems in implementing immutable data structures that can be shared amongst threads, data structures which are doing structural sharing, so people will expect reads to scale, except there will be non-obvious contention happening due to usage of reference counting.
The latency in state of the art mainstream GCs is also NOT variable. Good garbage collectors allow you to control the max latency and frequency of STW pauses. That is not the issue for real-time requirements - the issue with real-time being that STW is unacceptable. But so is reference counting.
On the memory requirements, I don't buy it. My Android phone has more memory and more CPU capacity than my computer did 7 years ago. And I'm not seeing a difference in behavior to my iPad. Surely for games it pretty bad to drop frames, but most apps are not games and games are using highly optimized engines built in C++anyway.
Have a look at Cyclone, ATS and ParaSail.