7 ms·
At a given point it does look like ARC might be the easiest solution (sure it has problems, but they're a subset of GC's problems) Edit: this link posted by an
by raverbashing 4y ago
At a given point it does look like ARC might be the easiest solution (sure it has problems, but they're a subset of GC's problems)
Edit: this link posted by another commenter gives a nice overview of the tradeoffs between the methods and it has very nice graphs to boot https://spin.atomicobject.com/2014/09/03/visualizing-garbage-collection-algorithms/ https://spin.atomicobject.com/2014/09/03/visualizing-garbage...
- tsimionescu 4y agoARC's problems are orthogonal to tracing/copying GC's problems. They are fundamentally different paradigms, since ARC mostly pays a cost for memory which is no longer in use, while tracing/copying GC pay a cost for memory which is in use. That is, with ARC, the more garbage you generate, the more work will be spent on the GC vs normal program flow. In contrast, with tracing/copying, you can generate as much garbage as you want, without affecting GC time; but, the more memory you actually use, the more time you will spend in GC.
- kaba0 4y agoARC (if ‘A’ means atomic) is simply not a good fit for modern hardware. With traditional tracing GCs you get blazing fast allocation and get to amortize the cost of deallocation, while you pay a price for ref counting on every usage (or at best on almost every usage with a good compiler).
- magicalhippo 4y ago> ARC (if ‘A’ means atomic) A is for Automatic, as in the compiler adds the calls needed to manage the reference counting. If the language and compiler can guarantee a reference is strictly contained within a thread, it doesn't have to be atomic. Usually that is not the case, so atomic operations are used.
- rwmj 4y agoYou need more than that. Reference counting amplifies reads into writes. To ameliorate that (somewhat) you need to keep the references separate from the data (a particular problem with Rust). Otherwise you end up with lots of writes scattered all over memory, causing false sharing and lots of unnecessary communication over buses between your cores. One way to do this is to keep the references together in separate cache lines or pages, away from the data. And this only partly alleviates the problem.
- zarzavat 4y agoWhile this is true on a microscopic scale, the motivation for using RC is macroscopic: to release memory ASAP to get predictable, low memory usage. From the RC point of view the real enemy is swap and the memory management system's primary objective is to eliminate swap.
- rwmj 4y agoTo summarise: - your application is using close to 100% available RAM - you don't care about the impact of all those extra writes clogging up CPU caches and bouncing cache lines back and forth across internal buses - you can't afford to pay for a small amount of extra RAM In that case reference counting sounds ideal. Good luck!
- zarzavat 4y agoThis was exactly Apple's reasoning for using refcounting in Swift. Although, as I understand it they worked around problem (2) by building their own silicon. If you're on the server then just buy more RAM and use a GC, I agree. But if you're making consumer software then buying more RAM isn't an option. Additionally, RAM costs battery life even when it isn't in use.
- JonChesterfield 4y agoPrompt is even better than predictable. In particular, reliably knowing the refcount on immutable data (in the persistent structure sense) has reached one means you can mutate it undetectably.
- CyberDildonics 4y agoyou pay a price for ref counting on every usage What do you mean by 'usage'? References don't change when reading or writing the data being reference counted, they change when being passed to a function or returned from one. In C++ it's rare that you would even use reference counting, since that essentially means you don't know the lifetime of your value. Most variables are going to be on the stack and the vast majority of dynamic allocation is going to be referenced from a single scope at one time. The reality is that it takes gross incompetence to have a speed impact from reference counting.
- kaba0 4y agoYeah I meant usage as “getting it into/out of scope”. > In C++ it's rare that you would even use reference counting, since that essentially means you don't know the lifetime of your value Sure, because it is a manual memory managed language with RC being an escape hatch only. But there are plenty of problems/programs where you simply can’t know the lifetime of your objects, e.g. Chrome uses a proper GC for C++ as well.
- CyberDildonics 4y agowith RC being an escape hatch only I don't know what you mean by escape hatch, but it generally just isn't necessary and memory is managed automatically by scope. The bigger point here is that it just isn't a significant part of execution time. But there are plenty of problems/programs where you simply can’t know the lifetime of your objects Like what? I can only think of one, which is passing memory allocated in one thread to another thread. Chrome uses a proper GC for C++ as well This is an anecdote, it doesn't prove or disprove anything in the bigger picture.
- kaba0 4y ago> managed automatically by scope That’s just an implementation detail. The point is that the object’s lifetime is only known at runtime and will be reclaimed when a counter reaches zero, this is reference counting. Whether you have to manually inc/dec that counter, or the language does it for you through some abstraction is besides the point, it is automatic memory management either way, as it.. manages memory automatically. > Like what? I can only think of one, which is passing memory allocated in one thread to another thread Any programming language, both parsing into an AST, AST manipulations, interpretation (and that is a very wide category, not only for things you would think of as proper languages). But even some games may want to use GC for some in-game objects, as the lifetime of those is fundamentally dependent on user action. Would the litany of managed languages and their widespread usage be less anecdotal?
- avgcorrection 4y agoI presume that “arc” means “automatic rc”. What’s manual rc like?
- simiones 4y agoLike using std::shared_ptr<T> in C++ or Rc<T> (or Arc<T>, which in that case stands for atomic, not automatic) in Rust. That is, you as a programmer choose for which variables to use reference counting.
- nt591 4y agoYou can manually increment and decrement reference counts with retain/release: https://stackoverflow.com/questions/6578/understanding-reference-counting-with-cocoa-and-objective-c https://stackoverflow.com/questions/6578/understanding-refer...
- aidenn0 4y agohttps://docs.gtk.org/glib/reference-counting.html https://docs.gtk.org/glib/reference-counting.html
- deathanatos 4y agoNormally I'd read "arc" as "atomic reference count", i.e., a refcount system where the increment and decrement operations are done with atomic increments/decrements. This permits the refcounted objects to be shared across threads that might mutate the refcount: they need to not corrupt the refcount, or UB ensues. E.g., the Arc type in Rust. Rust, for example, has a separate Rc type. Rc should outperform Arc, but cannot be shared across threads.