> If you wrap everything in Rc<RefCell> or Arc<Mutex> ... performance profile better than tracing GC
I seriously doubt it. Naively incrementing Ref counters is extremely expensive. Tracing GCs in modern languages are very advanced. The least you could do is try to elide some of the ref increments - but you can't do that in Rust. Also boxing every object is very unpleasant. If you're gonna do that, use a language with reference semantics, like Java or C#
> significant chunks of the runtime are still in C/C++
Means absolutely nothing about the safety of the languages themselves. Just because C# has a runtime written in C++ does not mean that you can now magically compile and run use after frees or whatever.
> Means absolutely nothing about the safety of the languages themselves. Just because C# has a runtime written in C++ does not mean that you can now magically compile and run use after frees or whatever.
As security experts like to repeat, it’s a numbers game. You only have to make a mistake once to result in an insecure system. And C++ encourages you to make those mistakes.
Same with JIT - because the compilation happens at runtime, a common attack mechanism is to exploit a particular bug in the JIT implementation so that the generated code violates some assumption and results in unsafe execution. This happens all the time with V8 and a large part of that problem comes from having to implement the language twice (once in the interpreter and once in the JIT and any deviation between the two implementations is an opportunity to exploit a vulnerability). This isn’t something I made up. This is from talking to people who are familiar with this and reading analyses by people who know what they’re talking about.
Compilers btw also have miscompilation bugs all over the place. The reason it’s less of a problem is because the code being executed isn’t “malicious” - it’s your code and you’re not going out of your way to structure code to find bugs in the compiler. This also protects most JIT and why most C# programs don’t have this problem - they’re not loading arbitrary code at runtime to execute. It is a particular problem for V8 though where that’s an expected behavior.
I don’t fundamentally disagree with your points but I do want to point out that in Rust, you have far less recount traffic than in a language that uses reference counting as a GC strategy, because you only increment and decrement on new owners, and not on every access. You can take a regular old &T to the interior of an Rc<T> at any time.
I didn't know this, that's pretty cool. Definitely more manual than what Swift is trying to do with RC elision since you have to then deal with runtimes, but also, I'd imagine much more performant due to a finer-grained nature.
Yes, and beyond that, you also have the Rc<T> vs Arc<T> split, so if you're not doing multi-threaded, it's not even an atomic increment/decrement.
That said, this is just my intuition here, I've never seen a good benchmark trying to do the comparison, so I don't want to over sell it either. But a lot of times, it's like, "okay I have four threads so I need the refcount to go to four" and then it's just using normal references to actually use the value inside.
Rc is cheap to the point of free unless it frees - it’s literally just an addition or subtraction with no data dependency in the path. Your CPU can do > 6 billion of these per second on a 6Ghz CPU (if I recall correctly you could do 3 per clock cycle in a micro benchmark due to out-of-order but at a minimum you should be able to do 1 per cycle).
Arc is quite expensive, particularly on x86 because of its memory model. You can maybe do a few million of them per second. But as you said, you shouldn’t be incrementing ownership once you’ve sent it to a new thread and instead using references directly or using something Rc-like to track the lifetime (i.e. when the current thread’s Rc count hits 0, release your Arc reference).
> Means absolutely nothing about the safety of the languages themselves. Just because C# has a runtime written in C++ does not mean that you can now magically compile and run use after frees or whatever.
Runtime bugs are potentially exploitable, even from within the language implemented by the runtime. But I don't think anyone's suggested that they'd present as simply as you suggest. Many such bugs have been found in runtimes of many languages.
Compiler bugs can be similarly exploitable, with the caveat that any code eliminated at compile time won't be accessible at runtime, so compiled languages will tend to have a smaller surface area for exploitation in general.
I seriously doubt it. Naively incrementing Ref counters is extremely expensive. Tracing GCs in modern languages are very advanced. The least you could do is try to elide some of the ref increments - but you can't do that in Rust. Also boxing every object is very unpleasant. If you're gonna do that, use a language with reference semantics, like Java or C#
> significant chunks of the runtime are still in C/C++
Means absolutely nothing about the safety of the languages themselves. Just because C# has a runtime written in C++ does not mean that you can now magically compile and run use after frees or whatever.