6 ms·
Can you elaborate on the cognitive overhead vs a GC language like golang or java? (With regards to memory) To me sure there is things you think about but gener
by spotman 10y ago
Can you elaborate on the cognitive overhead vs a GC language like golang or java? (With regards to memory)
To me sure there is things you think about but generally memory performance is less of a mental burden.
Also, swift 4 is supposed to support a rust like memory model. Not sure if it's opt in or how it will work but my impression is that it's memory model is about to support some new use cases to make it appropriate for more memory critical tasks.
- mikeash 10y agoSpeaking only for myself, avoiding or breaking retain cycles is a noticeable problem in Swift code that simply isn't there in languages with a proper garbage collector. Among newer iOS programmers, it's a big point of confusion to figure out when a callback closure should use [weak self] versus capturing self strongly, for example. I've seen a lot of people struggle to understand, completely fail, and end up dogmatically using [weak self] everywhere whether it's needed or not (and sometimes where it's actually harmful).
- pjmlp 10y agoIt is much easier than in either C++ or Rust.
- mikeash 10y agoDon't C++ and Rust offer the same facilities? C++ has std::weak_ptr and Rust has std::rc::Weak.
- pjmlp 10y agoYes, but they are library calls without any help from the compiler.
- mikeash 10y agoHow does that make them any more difficult to use?
- fauigerzigerk 10y agoYou have to manually optimize away unnecessary reference counting without help from the compiler.
- mikeash 10y agoThat is true, but a totally different issue from breaking or avoiding retain cycles.
- pcwalton 10y agoI have never seen unnecessary reference counting be a problem in Rust. That's because not manipulating the reference count requires an explicit action—.clone()—and borrowing is so expressive that you rarely need to manipulate the counts.
- fauigerzigerk 10y agoI guess that's because in Rust you never need defensive reference counting thanks to the borrow checker.
- Rusky 10y agoRust's borrow checker actually helps with this a lot- you can hand out references to the Rc-ed data without modifying the count, and the compiler will enforce that the count is not decremented until the references are dead. Combined with the fact that plain references are more idiomatic than Rc/Arc, this leads to pretty similar results.
- pjmlp 10y agoThe compiler can provide better error messages and guide the user, whereas with library types, at least on C++'s case it requires help from external tooling. With Rust, while you can make use of the type system, it is harder for the compiler to provide such guidance, unless the types are somehow blessed.
- pcwalton 10y agoTechnically true, but very misleading in Rust's case. In Rust you rarely have to break retain cycles in the first place, simply because you don't use reference counting much. Things like "weak self" are not a problem, because closures aren't reference counted unless you explicitly make them so (and in fact I don't think I've ever seen a reference counted closure in practice).
- pjmlp 10y agoI agree. I only mentioned Rust, because of ergonomics, since the compiler cannot guide the user unless the types are known. Or is already something in place to make use of intrisics for better error messages in such cases, instead of just giving a type error?
- stepanhruda 10y agoWith @nonescaping becoming the default, this might become a bit simpler. Not too much, but a bit.
- fauigerzigerk 10y agoReference counting has upsides and downsides. If you look at the lengths that some Java based projects like Spark have to go to in order tame the GC, then you have to question whether tracing GC is the right choice in the age of hundereds of GBs of memory. On the other hand reference counting is extremely slow. So slow that it puts a lot of restrictions on API design and that is definitely a mental burden. Swift's own collection interface changed massively between 2.x and 3 and I believe the main reason for the redesign was that the old design required too much reference counting. (I'm not completely sure this is an accurate reflection of their thinking though)
- zzzcpan 10y ago> On the other hand reference counting is extremely slow. So slow that it puts a lot of restrictions on API design and that is definitely a mental burden. This is very wrong on both points. Reference counting has a lot less mental burden compared to GC, because it's predictable. You can rely on destructors to actually work and be useful. For example, you don't have to keep track of whether you closed your file descriptor or not, but in GCd languages you have to do that manually, sometimes even with the same reference counting, but hand-written and explicit. Reference counting is also very fast, with the exception of concurrent decades old implementations, that are irrelevant today.
- fauigerzigerk 10y agoI don't disagree on the benefits of RAII at all. I love it. It's a much cleaner and more general resource management idea than a tracing GC. But incrementing/decrementing an atomic value in a tight loop apparently creates a performance problem that is severe enough for the Swift team to redesign their API. That wasn't decades ago: "Code that handles indices has to perform atomic reference counting, which has significant overhead and can prevent the optimizer from making other improvements." https://github.com/apple/swift-evolution/blob/master/proposals/0065-collections-move-indices.md https://github.com/apple/swift-evolution/blob/master/proposa...