TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Reference count, don't garbage collect

189 pointsby kclalmost 3 years ago

44 comments

shwestrickalmost 3 years ago
This debate has gone round and round for decades. There are no hard lines; this is about performance tradeoffs, and always will be.<p>Perhaps the biggest misconception about reference counting is that people believe it avoids GC pauses. That&#x27;s not true. Essentially, whereas tracing GC has pauses while tracing live data, reference counting has pauses while tracing garbage.<p>Reference counting is really just another kind of GC. I&#x27;d highly recommend perusing this paper for more details: A Unifying Theory of Garbage Collection. <a href="https:&#x2F;&#x2F;web.eecs.umich.edu&#x2F;~weimerw&#x2F;2012-4610&#x2F;reading&#x2F;bacon-garbage.pdf" rel="nofollow">https:&#x2F;&#x2F;web.eecs.umich.edu&#x2F;~weimerw&#x2F;2012-4610&#x2F;reading&#x2F;bacon-...</a><p>One of the biggest issues with reference counting, from a performance perspective, is that it turns reads into writes: if you read a heap-object out of a data structure, you have to increment the object&#x27;s reference count. Modern memory architectures have much higher read bandwidth than write bandwidth, so reference counting typically has much lower throughput than tracing GC does.
评论 #32283392 未加载
评论 #32282754 未加载
评论 #32279770 未加载
评论 #32282717 未加载
评论 #32282707 未加载
评论 #32286094 未加载
评论 #32282435 未加载
评论 #32282423 未加载
评论 #32284520 未加载
评论 #32285155 未加载
评论 #32282502 未加载
评论 #32284435 未加载
评论 #32295530 未加载
评论 #32282410 未加载
评论 #32283307 未加载
评论 #32283905 未加载
jerfalmost 3 years ago
From what I can see, the myth that needs to be debunked isn&#x27;t that garbage collection is super fast and easy with no consequences, it&#x27;s the myth that garbage collection always automatically means your program is going to be spending 80% of its time doing it and freezing for a second every five seconds the instant you use a language with garbage collection. I see far more &quot;I&#x27;m writing a web server that&#x27;s going to handle six requests every hour but I&#x27;m afraid the garbage collector is going to trash my performance&quot; than people who believe it&#x27;s magically free.<p>It&#x27;s just another engineering decision. On modern systems, and especially with any runtime that can do the majority of the GC threaded and on an otherwise-unused core, you need to have some pretty serious performance requirements for GC to ever get to being your biggest problem. You should almost always know when you&#x27;re setting out to write such a system, and then, sure, think about the GC strategy and its costs. However for the vast bulk of programs the correct solution is to spend on the order of 10 seconds thinking about it and realizing that the performance costs of <i>any</i> memory management solution are trivial and irrelevant and the only issue in the conversation is what benefits you get from the various options and what the non-performance costs are.<p>It is in some sense as big a mistake (proportional to the program size) to write every little program like it&#x27;s a AAA game as it is to write a AAA game as if it&#x27;s just some tiny little project, but by the sheer overwhelming preponderance of programming problems that are less complicated than AAA games, the former happens overwhelmingly more often than the latter.<p>Edit: I can be specific. I just greased up one of my production systems with Go memstats. It periodically scans XML files via network requests and parses them with a parser that cross-links parents, siblings, and children using pointers and then runs a lot of XPath on them, so, it&#x27;s kinda pessimal behavior for a GC. I tortured it far out of its normal CPU range by calling the &quot;give me all your data&quot; JSON dump a 100 times. I&#x27;ve clicked around on the website it serves to put load on it a good 10x what it would normally see in an hour, minimum. In 15 minutes of this way-above-normal use, it has so far paused my program for 14.6 milliseconds total. If you straight-up added 14.6 milliseconds of latency to every page it scanned, every processing operation, and every web page I loaded, I literally wouldn&#x27;t be able to notice, and of course that&#x27;s not what actually happened. Every second worrying about GC on this system would be wasted.
评论 #32277315 未加载
评论 #32277041 未加载
评论 #32285080 未加载
flohofwoealmost 3 years ago
Such a claim really needs hard data to back it up. Reference counting can be <i>very</i> expensive, especially if the refcount update is an atomic operation. It&#x27;s hard to capture in profiling tools because the performance overhead is smeared all over the code base instead of centralized in a few hot spots, so most of the time you don&#x27;t actually know how much performance you&#x27;re losing because of refcounting overhead.<p>The most performant approach is still manual memory management with specialized allocators tuned for specific situations, and then still only use memory allocation when actually needed.
评论 #32282441 未加载
评论 #32282507 未加载
jsnellalmost 3 years ago
&gt; Basically, you attach the reference to the object graph once, and then free it when you&#x27;re done with it.<p>So reference counting works by the programmer knowing the lifetime of each object allowing them to only increment &#x2F; decrement the refcount once, and trusting that the raw uncounted pointers they use elsewhere are always valid? There&#x27;s another word we have for this: manual memory management. It&#x27;s unsafe and unergonomic, and it&#x27;s pretty telling that the author needs to this pattern to make RC appear competitive. It&#x27;s because actually doing reference counting safely is really expensive.<p>&gt; If GC is so good, why wouldn&#x27;t Python just garbage collect everything, which they already did once and could trivially do, instead of going through the hassle of implementing reference counting for everything but the one case I mentioned?<p>Because they&#x27;ve made reference counting a part of their C extension API and ABI. If they wanted to use a GC, they&#x27;d instead need a very different API, and then migrate all the modules to the new API. (I.e. a way for those native extension to register&#x2F;unregister memory addresses containing pointers to Python objects for the GC to see.)<p>Early on the deterministic deallocation given by reference counting would also have been treated by programmers as a language level feature, making it so that a migration would have broken working code. But I don&#x27;t think that was ever actually guaranteed in the language spec, and anyway this was not carried over to various alternative Python implementations.
评论 #32283848 未加载
评论 #32283139 未加载
评论 #32285165 未加载
yyykalmost 3 years ago
Reference counting <i>is</i> garbage collection, just a different strategy - and all these strategies tend to blur to the same methods eventually, eventually offering a latency-optimized GC or a throughput-optimized GC.<p>Swift is inferior here because it uses reference counting GC without much work towards mitigating its drawbacks like cycles (judging by some recent posts, some of its fans apparently aren&#x27;t even aware RC has drawbacks), while more established GC languages had much more time to mitigate their GC drawbacks - e.g. Java&#x27;s ZGC mitigates latency by being concurrent.
评论 #32283265 未加载
评论 #32284598 未加载
评论 #32283040 未加载
评论 #32284989 未加载
smasher164almost 3 years ago
For how strongly worded this article is, you&#x27;d think the author would provide some substance in their reasoning. Reference counting, even atomic, is quite expensive. Not only because it can invalidate the cache line, but depending on the architecture (looking at you x86), the memory model will deter reordering of instructions. On top of this, reference counting has a cascading effect, where one destructor causes another destructor to run, and so on. This chain of destructor calls is more or less comparable to a GC pause.
评论 #32283434 未加载
评论 #32283227 未加载
bjournealmost 3 years ago
Time to tout my own horn. I made a project comparing different types of garbage collectors (I still prefer the original terminology; both ref-counting and <i>tracing</i> garbage collection collects garbage, so they are both garbage collectors) a few years ago: <a href="https:&#x2F;&#x2F;github.com&#x2F;bjourne&#x2F;c-examples" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;bjourne&#x2F;c-examples</a><p>Run .&#x2F;waf configure build &amp;&amp; .&#x2F;build&#x2F;tests&#x2F;collectors&#x2F;collectors and it will spit out benchmark results. On my machine (Phenom II X6 1090), they are as follows:<p><pre><code> Copying Collector 8.9 Reference Counting Collector 21.9 Cycle-collecting Reference Counting Collector 28.7 Mark &amp; Sweep Collector 10.1 Mark &amp; Sweep (separate mark bits) Collector 9.6 Optimized Copying Collector 9.0 </code></pre> I.e for total runtime it is not even close; tracing gc smokes ref-counting out of the water. Other metrics such as number of pauses and maximum pause times may still tip the balance in favor of ref-counting, but those are much harder to measure. Though note the abysmal runtime of the cycle-collecting ref-counter. It suggests that cycle collection could introduce the exact same pause times ref-counting was supposed to eliminate. This is because in practice cycles are very difficult to track and collect efficiently.<p>In any case, it clearly is about trade-offs; claiming tracing gc always beats ref-counting gc or vice versa is naive.
评论 #32285581 未加载
nemothekidalmost 3 years ago
It&#x27;s my theory that Java, unintentionally, did a lot of damage to P&amp;L research. I write a lot of Rust, and while the borrow checker is great, I&#x27;ve come to really admire the work that was put in the Go GC even if it&#x27;s not as fast Java.<p>There is a whole generation of programmers that have come to equate GC with Java&#x27;s 10 second pauses or generics&#x2F;typed variables with Java&#x27;s implementation of them. Even the return to typed systems (Sorbel, pythons&#x27; typing, typescript) could be seen as typed languages are great, what we really hated was Java&#x27;s verbose semantics.
评论 #32284067 未加载
评论 #32283029 未加载
评论 #32282990 未加载
评论 #32284640 未加载
评论 #32282964 未加载
slavbojalmost 3 years ago
People have been managing garbage collection schedules for decades now. It&#x27;s quite possible for many systems to have completely deterministic performance, with the allocation&#x2F;deallocation performance made extremely fast, gc restricted to certain times or a known constant overhead, etc. Ironically, from a programming perspective it&#x27;s incredibly easy in a language like Java to see exactly what allocates and bound those cases.<p>Conversely, it&#x27;s also possible for reference counting to have perverse performance cases over a truly arbitrary reference graph with frequent increments and decrements. You&#x27;re not just doing atomic inc&#x2F;dec, you&#x27;re traversing an arbitrary number of pointers on every reference update, and it can be remarkably difficult to avoid de&#x2F;allocations in something like Python where there&#x27;s not really a builtin notion of a primitive non-object type.<p>Generally speaking, memory de&#x2F;allocation patterns are the issue, not the specific choice of reference counting vs gc.
imtringuedalmost 3 years ago
Not only does the author ignore the huge progress in conventional garbage collected languages like Java, he also dismisses GC as inherently flawed despite the fact that the common strategy of only having one heap per application has nothing to do with garbage collection. In Pony each actor has its own isolated heap which means the garbage collector will only interrupt a tiny portion of the program for a much shorter period of time. Hence the concept of a stop the world pause is orthogonal to whether you have a GC or not. One could build a stop the world pause into an RC system through cycle detection if desired.
评论 #32283387 未加载
评论 #32285148 未加载
ridiculous_fishalmost 3 years ago
There&#x27;s a lot of discussion of comparative performance, but most software isn&#x27;t performance sensitive so it just doesn&#x27;t matter. But there&#x27;s another major facet: FFIs. The choice of memory management has huge implications for how you structure your FFI.<p>JavaScriptCore uses a conservative GC: the C stack is scanned, and any word which points at a heap object will act as a root. v8 is different, it uses a moving collector: references to heap objects are held behind a double-redirection so the GC may move them. Both collectors are highly tuned and extremely fast, but their FFIs look very different because of their choice of memory management.<p>Read and write barriers also come into play. If your GC strategy requires that reads&#x2F;writes go through a barrier, then this affects your FFI. This is part of what sunk Apple&#x27;s ObjC GC effort: there was just a lot of C&#x2F;C++ code which manipulated references which was subtly broken under GC; the &quot;rules&quot; for the FFI became overbearing.<p>Java&#x27;s JNI also illustrates this. See the restrictions around e.g. GetPrimitiveArrayCritical. It&#x27;s hard to know if you&#x27;re doing the right thing, especially bugs may only manifest if the GC runs which it might not in your test.<p>One of the under-appreciated virtues of RC is the interoperability ease. I know std::sort only rearranges, doesn&#x27;t add or remove references, so I can just call it. But if my host language has a GC then std::sort may mess up the card marking and cause a live object to be prematurely collected; but it&#x27;s hard to know for sure!
评论 #32284503 未加载
评论 #32284836 未加载
knomealmost 3 years ago
Reference counting can also have unpredictable hits if you release any large data structures. Whoever drops the last reference suddenly gets to sit through the entire deep set of items to release ( unless you can hand off the release cascade to a background thread ).<p>I&#x27;ve never heard of a reference counting implementation that can handle memory compaction.<p>Every time you update a reference count, which is every time you touch any object, you&#x27;re going to have to write to that RAM, which means stealing it from any other threads using it on any other processors. If you share large trees of data between threads, traversing that tree in different threads will always end up with your threads constantly fighting with each other since there&#x27;s no such thing as read only memory in reference counting.<p>When releasing something like a huge list in reference counting, how does the release avoid blowing the stack with recursive releasing? My guess is this just a &quot;don&#x27;t use a large list whose release may blow the stack with recursive releasing&quot; situation.
评论 #32283887 未加载
评论 #32277534 未加载
umanwizardalmost 3 years ago
Case 3.: You don’t “want” the constraints of Case 2, but are in practice forced into them due to a huge, poorly-educated developer base being incapable of writing correct refcounted code or even knowing what a weak pointer is.<p>When I worked at Facebook, which is structurally and politically incapable of building high-quality client software, I was on a small team of people tasked with making heroic technical fixes to keep the iOS app running despite literally hundreds of engineers working on the same binary incentivized to dump shoddy code to launch their product features that nobody would use as fast as possible (did you know that at one point you could order food through the Facebook app, and that a whole two digit number of people per day used this feature? Etc.)<p>Objective-C has ARC (automated reference counting) — every pointer is a refcounted strong reference by default unless special annotations are used. What makes it worse is that large, deep hierarchies are common, making reference cycles leaking huge amounts of memory easy to create.<p>For example, the view controller for a large and complicated page (referencing decoded bitmap images and other large objects) is the root of a large tree of sub-objects, some of whom want to keep a reference to the root. Now imagine the user navigates away and the reference to the view controller goes away, but nothing in the tree is deallocated due to the backlink — congratulations, you just leaked 10 MB of RAM!<p>It’s possible to do this correctly if you actually read the docs and understand what you’re doing, using tools like weak pointers, but when you have hundreds of developers, many of whom got their job either by transferring from an android team or by just memorizing pat answers to all the “Ninja” algorithms interview questions (practically all of which have leaked on Leetcode and various forums), you can be sure that enough of them will fail to do so to create major issues with OOMs.<p>To mitigate this, we created a “retain cycle detector” — basically a rudimentary tracing GC — that periodically traced the heap to detect these issues at runtime and phone home with a stack trace, which we would then automatically (based on git blame) triage to the offending team.<p>It was totally egregious undefined behavior, one thread tracing the heap with no synchronization with respect to the application threads that were mutating it, but the segfaults this UB caused were so much rarer than the crashes due to OOMs that it prevented that we decided to continue running it.
评论 #32285193 未加载
carry_bitalmost 3 years ago
You can optimize reference counting: <a href="https:&#x2F;&#x2F;citeseerx.ist.psu.edu&#x2F;viewdoc&#x2F;download?doi=10.1.1.231.4763&amp;rep=rep1&amp;type=pdf" rel="nofollow">https:&#x2F;&#x2F;citeseerx.ist.psu.edu&#x2F;viewdoc&#x2F;download?doi=10.1.1.23...</a><p>With allocating as dead, you&#x27;re basically turning it into a tracing collector for the young generation.
评论 #32283091 未加载
agentultraalmost 3 years ago
A paper I quite enjoyed on automatic reference counting for pure, immutable functional programming: <a href="https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1908.05647" rel="nofollow">https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1908.05647</a><p>It can be quite &quot;fast.&quot;
评论 #32277132 未加载
评论 #32283925 未加载
dprydenalmost 3 years ago
This article is naive to the point of being flat-out wrong, since it makes extremely naive assumptions about how a garbage collector works. This is basically another C++-centric programmer saying that smart pointers work better than the Boehm GC -- which is completely true but also completely misleading.<p>I&#x27;m not saying that GC is <i>always</i> the best choice, but this article gets the most important argument wrong:<p>&gt; 1. Updating reference counts is quite expensive. &gt; &gt; No, it isn&#x27;t. It&#x27;s an atomic increment, perhaps with overflow checks for small integer widths. This is about as minimal as you can get short of nothing at all.<p>Yes, it is. Even an atomic increment is a <i>write</i> to memory. That is not &quot;about as minimal as you can get short of nothing at all&quot;.<p>Additionally, every modern GC does generational collection, so for the vast majority of objects, <i>the GC literally does &quot;nothing at all&quot;</i>. No matter how little work it does, a RC solution has to do O(garbage) work, while a copying GC can do O(not garbage) work.<p>Now, that&#x27;s not to say that GC is automatically better. There are trade-offs here. It depends on the workload, the amount of garbage being created, and the ratio of read to write operations.<p>The article says:<p>&gt; I&#x27;ve already stated I&#x27;m not going to do benchmarks. I am aware of two orgs who&#x27;ve already run extensive and far-reaching experiments on this: Apple, for use in their mobile phones, and the Python project.<p>I can counterpoint that anecdata: Google extensively uses Java in high-performance systems, and <i>invented a new GC-only language</i> (Go) as a replacement for (their uses of) Python.<p>The right answer is to do benchmarks. Or even better yet, don&#x27;t worry about this and just write your code! Outside of a vanishingly small number of specialized use cases, by the time GC vs RC becomes relevant in any meaningful way to your performance, you&#x27;ve already succeeded, and now you&#x27;re dealing with scaling effects.
评论 #32283942 未加载
评论 #32284465 未加载
samatmanalmost 3 years ago
Definitely use reference counting, it&#x27;s better! Now you&#x27;re avoiding cyclic data structures and it sucks, so maybe just for a few objects we&#x27;ll put them on a linked list, maybe mark them, definitely sweep from time to time to see if anything is unreachable. I&#x27;m told there&#x27;s an algorithm by Boehm.<p>Well, ok, let&#x27;s go whole hog, we&#x27;re collecting garbage again, and it sucks, we get all these baby objects, let&#x27;s try and optimize the GC: we can keep, I dunno, a count of references to new objects, do some allocation sinking to see if we can avoid making them, put the babies in an orphanage, hey look, RC is GC, QED.
habiburalmost 3 years ago
It&#x27;s interesting how we have come full circle from &quot;Reference counting is the worst of two worlds [manual and GC] and will always be slower&quot; to now &quot;Well, we all know it&#x27;s actually faster.&quot; in like 10 years.
评论 #32277442 未加载
评论 #32276827 未加载
spullaraalmost 3 years ago
This is a modern GC:<p><a href="https:&#x2F;&#x2F;kstefanj.github.io&#x2F;2021&#x2F;11&#x2F;24&#x2F;gc-progress-8-17.html" rel="nofollow">https:&#x2F;&#x2F;kstefanj.github.io&#x2F;2021&#x2F;11&#x2F;24&#x2F;gc-progress-8-17.html</a><p>Way better than RC.
评论 #32285312 未加载
danybittelalmost 3 years ago
He fails to mention that Apple added support for ref counting in silicon.<p>And.. often GC will be able to use area allocators, before falling back to &quot;proper&quot; GC allocation. Which will be a lot faster than ref counting everything.<p>And atomics can get very slow, I&#x27;ve had atmics show up regularly in the profiler.<p>For my project, the combination that works great so far: unbox all types, use area allocators if the compiler can guarantee the value doesn&#x27;t escape, use GC for data that changes often and ref counting for data that hardly ever changes. (luckily cycles are not possible)
assbuttbuttassalmost 3 years ago
In practice, I don&#x27;t see any reference counting approaches that do cycle detection.<p>I have an example from early in my career where I accidentally created a memory leak in Python from a cyclic reference between a closure and a function argument<p><a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;54726363&#x2F;python-not-deleting-variable-when-it-goes-out-of-scope" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;54726363&#x2F;python-not-dele...</a>
malkiaalmost 3 years ago
Clearly this person hasn&#x27;t tried how this works on NUMA cpus. it&#x27;s quite expensive to do these atomic inc&#x2F;decs there, or even without NUMA... caches must be synced and flushed because of this.
评论 #32285386 未加载
Jweb_Gurualmost 3 years ago
I&#x27;m sorry, but this is a very poorly reasoned article that does not engage with any of the serious work that&#x27;s been underway to get reference counting competitive with tracing GC. This is evident from the very first point:<p>&gt; 1. Updating reference counts is quite expensive.<p>&gt; No, it isn&#x27;t. It&#x27;s an atomic increment, perhaps with overflow checks for small integer widths. This is about as minimal as you can get short of nothing at all. The comparison is the ongoing garbage collection routine, which is going to be more expensive and occur unpredictably.<p>First off, updating the reference count invalidates the entire cache line in which the reference count lives. For naive reference counting (which I&#x27;m assuming the author is talking about since they give no indication they&#x27;re familiar with anything else), this generally means invalidating the <i>object&#x27;s</i> cache line (and with an atomic RMW, to boot, meaning you need a bus lock or LL&#x2F;SC on most systems). So right away, you have created a potentially significant cacheline contention problem between readers in multiple threads, even though you didn&#x27;t intend to actually write anything. RC Immix, for example, tries to mitigate this in many creative ways, including deferring the actual reference count updates and falling back to tracing for reclamation when the count gets too high (to avoid using too many bits in the header or creating too many spurious updates).<p>Secondly, you know what&#x27;s cheaper than an atomic increment or decrement? <i>Not doing anything at all.</i> The vast majority of garbage in most production tracing garbage collectors (which are, with the exception of Go&#x27;s, almost exclusively generational) dies young, and never needs to be updated, copied, or deallocated (so no calling destructors and no walking a tree of children, which usually involves slow pointer chasing). Even where the object itself doesn&#x27;t die young, any temporary references to the object between collections don&#x27;t have to do any work at all compared to just copying a raw pointer, C style. This and bump allocation (which the author also does not engage with) are the two biggest performance wins that tracing garbage collectors typically have over reference counting ones, and solutions like RC Immix must implement similar mechanisms to even become competitive. You don&#x27;t even need to go into stuff like the potential benefits of compaction, or a reduction in garbage managing code on the hot path (which are more dubious and harder to show) to understand why tracing has some formidable theoretical advantages over reference counting!<p>But what about in practice? Surely, the overhead of having to periodically run the tracing GC negates all these benefits? Well, bluntly--no, not even close. At least, not unless you care only about GC latency to the exclusion of everything else, or are using something fancier (like deferred RC). You can&#x27;t reason backwards from &quot;Rust and C++ are generally faster than languages with tracing GCs on optimized workloads&quot; to conclude that reference counting is better than tracing GC--Rust and C++ both go out of their way to avoid using reference counting at all wherever possible.<p>None of this is secret information, incidentally. It is very easy to find. The fact that the author is apparently so incurious that they never once bothered to find out <i>why</i> academics talk about tracing GC&#x27;s performance being superior--and the fact that it was so dismissive about it!--makes me pretty doubtful that people are going to find useful insights in the rest of the article, either.
评论 #32285563 未加载
benibelaalmost 3 years ago
An advantage of RC is that you can also use it to verify ownership.<p>When the counter is 1, you can do anything with the object without affecting any other references.<p>Like the object could be mutable for a counter=1, and copy-on-write otherwise. Then you can make a (lazy) deep copy by just increasing the counter.
dganalmost 3 years ago
&gt;&gt; &quot;The Python case is more inarguable. If GC is so good, why wouldn&#x27;t Python just garbage collect everything,... ? It is because RC outperforms garbage collecting in all these standard cases&quot;<p>Pretty weird argument for one of the slowest languages out there ...
cosmoticalmost 3 years ago
&gt; This is about as minimal as you can get short of nothing at all.<p>With GC, you <i>can</i> do nothing at all. In a system with lots of garbage, you can do a GC by copying everything accessible from the GC root, then de-allocating all the garbage in a single free.
pizlonatoralmost 3 years ago
Atomic inc&#x2F;dec is hella expensive relative to not doing it. It’s true that CPUs optimize it, but not enough to make it free. RC as a replacement for GC means doing a lot more of this expensive operation - which the GC will do basically zero of in steady state - so this means RC just costs more. Like 2x slowdown more.<p>The atomic inc&#x2F;dec also have some nasty effects on parallel code. The cpu ends up thinking you mutated lines you didn’t mean to mutate.<p>So, GC is usually faster. RC has other benefits (more predictable behavior and timing, uses less memory, plays nicer with OS APIs).
评论 #32285712 未加载
pjmlpalmost 3 years ago
Another RC advocate that misses the point about RC being a GC algorithm from CS point of view.<p><a href="https:&#x2F;&#x2F;gchandbook.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;gchandbook.org&#x2F;</a>
byefruitalmost 3 years ago
This article provides very little evidence for it&#x27;s claims and seems to only have a superficial understanding of modern GCs.<p>&quot;Increments and decrements happen once and at a predictable time. The GC is running all the time and traversing the universe of GC objects. Probably with bad locality, polluting the cache, etc.&quot;<p>This is only the case with a mark-sweep collector, usually most of your allocations die young in the nursery. With reference counting you pay the counting cost for everything.<p>&quot;In object-oriented languages, where you can literally have a pointer to something, you simply mark a reference as a weak reference if it might create a cycle.&quot;<p>As someone who has tried to identify memory leaks in production where someone has forgotten to &quot;simply&quot; mark a reference in some deep object graph as weak, this is naive.<p>&quot;With an 8-byte counter you will never overflow. So...you know...just expand up to 8-bytes as needed? Usually you can get by with a few bits.&quot;<p>So now my &quot;about as minimal as you can get short of nothing at all&quot; check as an unpredictable branch in it?<p>&quot;If you must overflow, e.g., you cannot afford an 8-byte counter and you need to overflow a 4-byte counter with billions of references, if you can copy it, you create a shallow copy.&quot;<p>I don&#x27;t even know where to begin with this.<p>&quot;If GC is so good, why wouldn&#x27;t Python just garbage collect everything, which they already did once and could trivially do, instead of going through the hassle of implementing reference counting for everything but the one case I mentioned?&quot;<p>This probably has more to do with finalising resources and deterministic destruction than anything else.<p>--<p>Anyone who is interested in actually studying this area would probably find <a href="https:&#x2F;&#x2F;courses.cs.washington.edu&#x2F;courses&#x2F;cse590p&#x2F;05au&#x2F;p50-bacon.pdf" rel="nofollow">https:&#x2F;&#x2F;courses.cs.washington.edu&#x2F;courses&#x2F;cse590p&#x2F;05au&#x2F;p50-b...</a> interesting. Also <a href="https:&#x2F;&#x2F;gchandbook.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;gchandbook.org&#x2F;</a>
评论 #32277677 未加载
omginternetsalmost 3 years ago
Whenever I read someting like this, I wonder what kind of programming the author is doing. I’m getting a strong whiff of embedded and&#x2F;or real-time systems.
UltraViolencealmost 3 years ago
Reference counting forces the developer to think about memory management.<p>Apple has a nice talk on ARC [1] but it got me thinking: if I have to think about reference counting this much I might just as well manage memory all by myself.<p>The true joy of Garbage Collection is that you can just create objects left and right and let the computer figure out when to clean them up. It&#x27;s a much more natural way of doing things and lets computers do what they&#x27;re best at: taking tedious tasks out of the hands of humans.<p>[1]: <a href="https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2021&#x2F;10216&#x2F;" rel="nofollow">https:&#x2F;&#x2F;developer.apple.com&#x2F;videos&#x2F;play&#x2F;wwdc2021&#x2F;10216&#x2F;</a>
dfoxalmost 3 years ago
One great advantage of garbage collection is that it removes need for thread synchronization in cases where is it only needed to make sure that object jou are going to call free&#x2F;decref on is not in use in another thread. Corollaly to that GC is the thing that you need for many lock-free data structures to be practical and not of only theoretical interest.<p>It might seem that it is simply about pushing your synchronizations problems onto the GC, but the synchronization issue that GC solves internally is different and usually more coarse-grained, so in the end you have significantly smaller synchronization overhead.
melonyalmost 3 years ago
You are in for a fun time when you need to make circular data structures with ARC.
freecodyxalmost 3 years ago
What if programming languages start offering both? In my opinion RC is GC in disguise. At least for example Golang GC has the merit to run in a separate thread(still has to stop the world when reclaiming memory back, and the memory allocator model is helping achieve great GC perfs).
评论 #32283954 未加载
samsquirealmost 3 years ago
My understanding of Python&#x27;s Global Interpreter Lock is that reference counting cannot be done efficiently between threads, so we cannot remove the GIL with reference counting<p>Java&#x27;s GC is concurrent and runs at safe points and stops the world so it avoids this problem.
nikolayalmost 3 years ago
When I wrote a Lisp interpreter in the &#x27;90s, that&#x27;s how I did it and I&#x27;m ashamed to admit that I have no idea how modern GC is done - I&#x27;ve always assumed (naively!) that it was like Lisp&#x27;s!
评论 #32283949 未加载
badrabbitalmost 3 years ago
Pardon the ignorance but I thought refcount was a GC strategy?
评论 #32285378 未加载
exabrialalmost 3 years ago
&gt; I&#x27;ve already stated I&#x27;m not going to do benchmarks.<p>Yikes
glouwbugalmost 3 years ago
Isn’t garbage collection needed to solve circular reference counts?
评论 #32282493 未加载
amiga1200almost 3 years ago
Just allocate then deallocate manually, use neither auto methods.
评论 #32283958 未加载
mirekrusinalmost 3 years ago
What about - garbage collect by reference counting, like Python?
评论 #32283974 未加载
jayd16almost 3 years ago
Is there such a thing as a compacting RC?
评论 #32283172 未加载
评论 #32283251 未加载
titzeralmost 3 years ago
I read most the article and it&#x27;s just a lot of the same tired old arguments and an extremely simplified worldview of both GC and reference counting. I wish I had the author&#x27;s address, because I&#x27;d like to mail them a copy of the Garbage Collection Handbook. They clearly have a very naive view of both garbage collection and reference counting. And there isn&#x27;t a single dang measurement anywhere, so this can be completely dismissed IMHO.
评论 #32277751 未加载
bitwizealmost 3 years ago
Boy, I can&#x27;t wait for theangeryemacsshibe (posts here as hayley-patton) to tear into this one.<p>But yeah, the correct way to handle resources (not just memory!) is with value semantics and RAII. Because then you know the object will be cleaned up as soon as it goes out of scope with zero additional effort on your part. In places where this is not appropriate, a simple reference counting scheme may be used, but the idea is to keep the number of rc&#x27;d objects small. Do not use cyclical data structures. Enforce a constraint: zero cycles. For data structures like arbitrary graphs, keep an array of vertices and an array of edges that reference vertices by index.<p>If you use a language with GC, you&#x27;re probably just contributing to global warming.
评论 #32281365 未加载
评论 #32283978 未加载