Reference-counting garbage collection can be quite efficient

Keeping the allocation alive without the object sounds exactly like keeping a Weak before try_unwrap. On that topis, could one reuse a Weak that has no current strong owners?

impl Weak<T> {
    /// Reuse the allocation if there are no strong references to it.
    pub fn try_init(&self, val: T) -> Result<Rc<T>, T> {
        // or `Option<Rc<T>>` but avoids the drop of `T`
        …
    }
}

if reference-based garbage collection is good then why C# doesnt use it? i am sure they are doing their best to make the language as fast as possible

Is that an argument from authority?

2 Likes

It kind of is an argument-from-authority, but in any case, I think the question can be pretty easily answered.

The problem is that it's not as simple as "RC is good or bad". The OP said that it can be quite efficient, not that it necessarily is efficient, or efficient in all use cases.

Well-written Rust and C++ use reference counting selectively, both by allowing you to allocate objects with no reference count at all, and by manually eliding unnecessary bumps even when the object itself does have a reference count. In C#, on the other hand, all class instances are implicitly garbage collected, so if C# was using reference counting, it would be ubiquitous reference counting. Taking the existing C# design verbatim, but replacing the tracing GC with atomic RC, would probably make it slower (it would spend a bunch more time messing around with the reference counts). Taking the existing Rust design, but replacing Rc with a tracing garbage collector, would probably also make it slower (since it would no longer have deterministic destruction, and would have to be able to trace through all objects, a bunch of weird optimization shenanigans would suddenly become illegal).

All optimization is optimization to a niche, and Rust and C# target different niches.

8 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.