4 ms·
I think more languages should adopt Swift and Objective-C's automatic reference counting. The only downside to ARC is retain cycle's which rarely happen in my e
by youngthugger 12y ago
I think more languages should adopt Swift and Objective-C's automatic reference counting. The only downside to ARC is retain cycle's which rarely happen in my experiance. A deterministic object life cycle just feels right.
- ezy 12y agoI prefer well known memory lifetimes, but I'm undecided about ARC (or somewhat equivalently: std::shared_ptr, etc.). It can be a little confusing and overwrought at times, and I don't think the lifetimes are as clear as they could be. 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.).
- mamcx 12y agoYou are talking about a arena collector? Like this: http://wiki.luajit.org/New-Garbage-Collector http://wiki.luajit.org/New-Garbage-Collector Exist some pre-madethat can be used for a new project, for use with LLVM or luajit?
- Dewie 12y ago> , but I haven't seen a way to swap out the memory allocator in various contexts. You mean something like this? https://github.com/rust-lang/rfcs/pull/244 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.
- ezy 12y agoYup. That's excellent. Rust changes so fast, I can hardly keep up. :-)
- Dewie 12y agoSadly though I haven't been able to find any mention of if and when it will be realized. But the sentiment - from what I've gleaned from discussions on it - seems to be that something like that should/need to happen.
- kevinnk 12y agoMaybe you're referring to something else, but std::allocator was in c++98
- ezy 12y agoYes, but (according to the spec) it was stateless -- which made it worthless for the purposes I'm describing. The original purpose was to support custom static strategies for allocation (e.g. i86 near/far pointers or one memory pool for one kind of object for the whole program), not dynamic memory pools and arenas. C++11 fixed that, which is why I mentioned it. 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.
- chrisseaton 12y ago"The only downside to ARC is retain cycles" 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.
- Dewie 12y ago> The only downside to ARC Doesn't reference counting typically have a worse throughput than garbage collection? That's what I've read anyway.
- lumpypua 12y agoGC has better throughput at the expense of significantly increased memory usage, and variable latency for any individual task. On servers, that's fine. On my phone, I'll take lower memory usage and predictable latency any day. Yay refcounting.
- nraynaud 12y agoit's not really "significant" if you don't optimise it that way. It's only the first generation scavenger that needs space for breathing.
- lumpypua 12y agoI do agree with this critique. Object allocation patterns that suck down space in a GC'ed system equally abuse a refcounting system, just you're paying in CPU time rather than memory.
- adrianm 12y agoAll GC algorithms are not created equal. 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?
- lumpypua 12y ago> What algorithm are you referring to when you say "better throughput at the expense of significantly increased memory usage"? 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-performance-of-garbage-collection-vs-explicit-memory-management http://stackoverflow.com/questions/2982325/quantifying-the-p... [2] http://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf http://www.cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
- nraynaud 12y agoI had big troubles with cycles, the trick is that you don't know that you are leaking until it's too late. Another trouble is the cache pollution.
- ltta 12y agoAs far as I know ARC (like manual memory managenent) can lead to release cascades that can also cause application delays in games eg. Something you have to watch for. Malloc() and free() and equivalents do quite a bit of work under the hood (check today's linked tcmalloc article for example) that takes time.
- psykotic 12y agoRelease cascades can be a big problem even with plain old RAII in C++. I once diagnosed a performance issue in a C++ network server where the server listening thread would sometimes temporarily hang when clients disconnected. The culprit turned out to be the destructor of a large std::map that directly and indirectly accounted for tens of millions of heap-allocated objects that had to be individually destructed and freed. It's very rare for destructors to have intentional global side effects, so this kind of work could almost always have been done asynchronously, at least in principle. 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.
- mamcx 12y agoSo, what do? Perhapsh mark a object as "kill me without mercy?"
- psykotic 12y agoIf the mass objects have trivial (ignorable) destructors and don't own any heap-allocated subobjects then it's not a problem. You can have top-level objects like levels or documents or sessions own everything directly and indirectly under them and allocate those things out of a private heap that can ideally be reused but otherwise be bulk freed in a few calls. Unfortunately, the standard C++ philosophy around RAII and value semantics works against this. Since there is something to be said for the elegance and upfront convenience of the value semantics approach, it comes down to a trade-off.
- ltta 12y agoAnd also check out this paper comparing reference counting and GC, and the accompanying discussion on LtU. http://lambda-the-ultimate.org/node/2552 http://lambda-the-ultimate.org/node/2552 (Although I think the paper has problems and bias)
- rayiner 12y agoAutomatic reference counting has its own issues: 1) allocating short-lived objects is not cheap, because they call down into an underlying malloc/free; 2) as a consequence of (1), throughput is lower; 3) getting acceptable overhead for manipulating references in the heap/stack requires compiler optimizations to elide those reference counts, which adds a layer of complexity to your mental model of the program; 4) implementing the reference-count operating in a multi-core system requires pretty heavy-weight atomic primitives, and race conditions can result in incorrect reference counts.[1] 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-oopsla-2013.pdf 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#optimization http://clang.llvm.org/docs/AutomaticReferenceCounting.html#o....
- gkuan 12y agoThere is also this paper by Bacon et al that develops a framework that shows the relationship between refcount and tracing GC (duals of each other) plus the various optimizations of the two: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143.6619 http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.143....