[swift-evolution] What about garbage collection?
felixcca at yahoo.ca
Mon Feb 8 17:13:06 CST 2016
Chris, I appreciate that your reply covers the questions without simply stating an opinion.
>> It seems to me that the two principal upsides of reference counting are that destruction is (essentially) deterministic and performance is more easily predicted.
> Yes, deterministic destruction is a major feature. Not having to explain what finalizers are (and why they shouldn’t generally be used) is a pretty huge. Keep in mind that Swift interops with C, so deinit is unavoidable for certain types.
> More pointedly, not relying on GC enables Swift to be used in domains that don’t want it - think boot loaders, kernels, real time systems like audio processing, etc.
I agree that you don't want a GC in these, but on the other hand, from what I know of the current RC implementation, I find it hard to believe that it would be much more acceptable. Beyond any cycle efficiency concerns, interrupting a retain/release operation could cause a real carnage, and disabling interrupts while it happens won't necessarily be acceptable either. (Which begs the question: how well does Swift react to signals right now?)
If I wanted to use Swift today in these environments, I'd probably stick to UnsafePointers and structs. It wouldn't really matter if classes were managed with a reference count or a mark-and-sweep collector since I wouldn't have any.
> We have discussed in the passed using hybrid approaches like introducing a cycle collector, which runs less frequently than a GC would. The problem with this is that if you introduce a cycle collector, code will start depending on it. In time you end up with some libraries/packages that works without GC, and others that leak without it (the D community has relevant experience here). As such, we have come to think that adding a cycle collector would be bad for the Swift community in the large.
Yes, I've heard about many problems with that and I wouldn't be in favor of a mix either.
>> object references cannot be atomically updated
> This is true, but Swift currently has no memory model and no concurrency model, so it isn’t clear that this is actually important (e.g. if you have no shared mutable state).
The fact that references can't be updated atomically will necessarily influence any decision that is taken regarding the concurrency model. The concurrency model pre-proposal <https://github.com/apple/swift/blob/master/docs/proposals/Concurrency.rst> already uses it as an argument to push a model that respects this limitation. I will be shocked if the same argument doesn't come up again when these talks actually start.
>> the closure capture syntax uses up an unreasonable amount of mindshare just because of [weak self]
> I think that this specific point is solvable in others ways, but I’ll interpret this bullet as saying that you don’t want to worry about weak/unowned pointers. I completely agree that we strive to provide a simple programming model, and I can see how "not having to think about memory management" seems appealing.
What I actually meant is that a lot of energy is being spent right now on how to address these issues, which wouldn't be issues at all if Swift relied on a garbage collector.
> On the other hand, there are major advantages to the Swift model. Unlike MRR, Swift doesn’t require you to micromanage memory: you think about it at the object graph level when you’re building out your types. Compared to MRR, ARC has moved memory management from being imperative to being declarative. Swift also puts an emphasis on value types, so certain problems that you’d see in languages like Java are reduced.
> That said, it is clear that it takes time and thought to use weak/unowned pointers correctly, so the question really becomes: does reasoning about your memory at the object graph level and expressing things in a declarative way contribute positively to your code?
> My opinion is yes: while I think it is silly to micromanage memory, I do think thinking about it some is useful. I think that expressing that intention directly in the code adds value in terms of maintenance of the code over time and communication to other people who work on it.
I don't agree with this. People will very often use `weak` or `unowned` only to break a cycle, not because it really doesn't matter if the object suddenly disappears. The whole weak self capture is a good example of that. The unpopularity of weak references in garbage-collected languages is generally a demonstration that most applications don't need to bother with that.
>> Since Swift doesn't expose memory management operations outside of `autoreleasepool`, it seems to me that you could just drop in a garbage collector instead of reference counting and it would work (for most purposes).
>> Has a GC been considered at all?
> GC also has several *huge* disadvantages that are usually glossed over: while it is true that modern GC's can provide high performance, they can only do that when they are granted *much* more memory than the process is actually using. Generally, unless you give the GC 3-4x more memory than is needed, you’ll get thrashing and incredibly poor performance. Additionally, since the sweep pass touches almost all RAM in the process, they tend to be very power inefficient (leading to reduced battery life).
> I’m personally not interested in requiring a model that requires us to throw away a ton of perfectly good RAM to get an “simpler" programming model - particularly on that adds so many tradeoffs.
The way I have to reason about cycles isn't my favorite part of Swift, but I'm not necessarily in favor of having a GC either. I was very surprised that it hadn't come up at all since RC causes actual issues that are currently discussed. (It's also nice that you can ask and have informed people reply to you.)
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution