There are certainly classes of mobile apps that need the guarantees of lower/deterministic memory usage. In my experience, that is not the common app being written however. These concerns seem largely like fantasies not backed up by any concrete evidence for your every-day twitter client/mail app/weather/whatever. Generic list-based apps simply do not need to be acting as if you need to squeeze every ounce out of the processor/ram anymore. They would instead benefit much more from not having to worry about whether self in the closure you're creating should be weak or not. Especially when you consider that many (most?) of the apps on the App Store that are actually pushing things to the limit -- games -- are running in a (old) GC environment (C# in Unity).
I would be quite surprised if most App Store games were created with Unity - it's expensive and (comparatively) cumbersome to develop in, especially if you're just using 2D graphics (even with the fancy new Unity2D stuff). I can't find any stats on mobile game engine use though, which is a shame because I think it would be interesting to know.
When creating Unity3D games, you have to be reasonably careful about garbage collection - lots of nasty performance dips result if you assume that it just works. Generally you have to cobble together a mixture of object pools and statements attempting to force collection at a convenient point in the game flow amongst other things. It would be quite nice if you could turn it off for specific portions of code :)
Unity uses an older Mono (2.10 I believe) which has a poor GC that's not even deterministic, so you can easily suffer memory leaks. It is also not generational. Newer versions of Mono come with a much better GC.
Ref counting is not deterministic. First of all because while looping on an atomic reference is non blocking, it is not wait free. Malloc/free are not deterministic either, can be quite expensive and while real-time implementations exist, that's not the malloc/free you end up using. With a generational GC allocating new objects involves just incrementing a pointer, deallocating short lived objects happens in bulk, so the cost for short-lived objects is similar to stack allocation. With ref counting memory gets fragmented, apps like Firefox have been suffering for years from fragmentation and for Firefox there was a sustained and very significant effort to fix it.
This can only be solved by either doing stack allocation or by building object pools. And this is for people that know what they are doing.
Rust is the only language (I know) that tries solving this with the ownership concept in the language, but then Rust will have problems in implementing immutable data structures that can be shared amongst threads, data structures which are doing structural sharing, so people will expect reads to scale, except there will be non-obvious contention happening due to usage of reference counting.
The latency in state of the art mainstream GCs is also NOT variable. Good garbage collectors allow you to control the max latency and frequency of STW pauses. That is not the issue for real-time requirements - the issue with real-time being that STW is unacceptable. But so is reference counting.
On the memory requirements, I don't buy it. My Android phone has more memory and more CPU capacity than my computer did 7 years ago. And I'm not seeing a difference in behavior to my iPad. Surely for games it pretty bad to drop frames, but most apps are not games and games are using highly optimized engines built in C++anyway.
I do agree with this critique. Object allocation patterns that suck down space in a GC'ed system equally abuse a refcounting system, just you're paying in CPU time rather than memory.
What algorithm are you referring to when you say "better throughput at the expense of significantly increased memory usage"?
Also, why is unpredictable latency acceptable for you on servers but not phones? Wouldn't a latency spike on remote requests from an application degrade user experience just as much as if that latency were localized to the phone?
> What algorithm are you referring to when you say "better throughput at the expense of significantly increased memory usage"?
Here's a discussion of the particular paper behind that statement: [1]
I'd also like to recommend the paper "A Unified Theory of Garbage Collection" [2] that breaks down the divide between GC and refcounting. There is a lot of gray area between tracing GC and refcounting. You can make different tradeoff decisions in different parts of your collection algorithm. But fundamentally it breaks down to time-space tradeoffs—you want to save time and get throughput, you're gonna eat some extra space.
> Also, why is unpredictable latency acceptable for you on servers but not phones? Wouldn't a latency spike on remote requests from an application degrade user experience just as much as if that latency were localized to the phone?
We as developers make UI efforts to mitigate network unreliability (fallacy #1 of distributed computing: the network is reliable) so it's ok if a server is being temporarily shitty. It's a lot harder to keep responsive, smooth UI behavior in the face of dropped frames and long GC pauses.
On servers, that's fine.
On my phone, I'll take lower memory usage and predictable latency any day.
Yay refcounting.