4

I was reading about memory management for various languages and the fact that Objective-C doesn't have managed memory because it causes stutters in the UX of the mobile apps.

I know ARC doesn't deal with circular reference, while Python's GC does.

I know that ARC is not a garbage collector at all and so it does not stop the execution of the main program to perform the memory management.

Could Python use a hybrid approach? Take some of the advantages of ARC and at the same time run the GC less often (or for a shorter period of time) so that it can still deal with circular references?

Or as anything like that being attempted within the Python community?

EDIT: I know Python uses reference counting, but as far as I know the objects whose reference drops to 0 are not immediately removed from memory (which ARC does). I am wondering if an immediate release of the memory occupied by that object could make Python more suitable in low memory environments, and because in that case the GC would possibly run less often, it would cause less threads interruptions. Both things would be ideal for a mobile application as far as UX.

Gabriel
  • 1,078
  • 1
  • 8
  • 15
  • Please see http://stackoverflow.com/questions/9062209/why-does-python-use-both-reference-counting-and-mark-and-sweep-for-gc – dstromberg Jul 20 '13 at 00:26
  • That link doesn't help. I know it uses RC and mark-and-sweep, but the objects are not released as soon as the reference count goes to 0 right? – Gabriel Jul 23 '13 at 00:43

1 Answers1

7

As far as I can tell, Objective-C's ARC gives, in the end, the same thing as CPython's reference counting, minus the circular reference handling. ARC is merely a fancy new name that was (re)invented to mean that the Objective-C compiler, rather than the programmer, inserts the reference counting code automatically.

Let us assume for the purpose of this answer that CPython could be rewritten in Objective-C (which is unrealistic). What you'd get by using ARC over explicit reference counting is:

  • Simpler code.

  • No cyclic collection.

  • Guaranteed correct code. There are a few known, and probably some unknown, issues with reference counting in CPython that can lead to crashes in some extremely unlikely cases; some of Lib/test/crashers/ are based on this.

  • Slightly slower code. Indeed, a compiler is usually not as smart as a human in finding cases where we don't actually need to manipulate the reference counter.

As a PyPy developer, I can report my own experience: we tried at some point in the past to do the same, i.e. have reference counting code inserted automatically during compilation. However we abandoned this approach because without advanced optimizations you get seriously slower code. Instead we use some simple "real" garbage collection (GC) system now; it gives better performance than even CPython's reference counting. So my own advice for compiler-makers would be that if you want a compiler that can insert the necessary code automatically, you'd be much better off using any of a number of better GCs. Last I checked however, LLVM's support was still almost null in this regard.

Armin Rigo
  • 12,048
  • 37
  • 48
  • Correct in all but the performance assessment. Pure ARC code results in fewer retain/release/autorelease calls than correctly written MRR code. – bbum Jul 20 '13 at 13:41
  • Magic. Unless you provide a reference explaining this, I believe this to be impossible. :-) – Armin Rigo Jul 21 '13 at 07:34
  • In MRR, a factory method is required to return an `autorelease`d object, which the caller `retain`s (if necessary). In ARC, that `autorelease` isn't necessary and the compiler emits a `release` on the caller side if the object isn't kept around. But one of many examples of how the compiler can optimize ARC code way beyond MRR and without the overhead of GC. Note that the Objective-C garbage collector in OS X yields a faster runtime environment than MRR, as well (I never compared GC with ARC, but GC -- at the moment -- is likely to still be faster in most real world apps... for now). – bbum Jul 21 '13 at 16:27
  • Note also that the GC environment was faster in real world apps because of the thread local collector. On allocation, no locks were needed because an object would be considered "thread local". When it escaped the thread's scope, it would be added to the global memory pool (requiring a synchronization barrier). If it never escaped, it would be deallocated without requiring a lock. Important point; this and the above are very specific claims about OS X's implementation. It is not a general claim about GC vs. non-GC performance across all environs. – bbum Jul 21 '13 at 16:32
  • @bbum: unsure what you mean by MRR, but it might be something specific and different from CPython's manual reference counting. The latter is not expressed in terms of "autorelease" and "retain". Anyway, I fail to see why it's impossible for a human to encode manually the same behavior as the one generated by an ARC compiler (and then be more clever in some cases). I'll remain at my "reference needed" comment. – Armin Rigo Jul 21 '13 at 20:28
  • MRR is Manual-Retain-Release and, yes, it is different than CPython's implementation. A human cannot write code that is *both* compatible with the memory management requirements of ObjC on OS X / iOS *and* faster than what the compiler and runtime can collude to produce under ARC. One specific example is that a factory method *must* return an autoreleased object under MRR. This is not true under ARC; 2 less methods calls and no autorelease overhead which *cannot* be avoided under MRR. As for references, the source for the compiler & runtime are available. – bbum Jul 21 '13 at 21:30
  • Then you are off-topic. – Armin Rigo Jul 22 '13 at 09:10
  • I was responding to *As far as I can tell, Objective-C's ARC gives, in the end, the same thing as CPython's reference counting* and *Slightly slower code..*. Both of which are claims that are incorrect (same thing? yes. Same way? no.); ARC leverages autorelease pools, there is no GC at all, and, no, a human cannot write *correct* code that is faster than the compiler. None of which answers OP's question, assuredly, but all of which should provide additional context to your answer that other's might refine to address OP's question? – bbum Jul 22 '13 at 14:51
  • But the objects are not released in Python as soon as the RC goes to 0 right? they are just marked for cleanup for later when the GC comes in, correct? – Gabriel Jul 23 '13 at 00:42
  • Also the supposed difference between ARC and GC is that it does not create interruptions in the running thread and it works better in low memory devices. – Gabriel Jul 23 '13 at 00:51
  • @Gabriel The same as ObjC; objects are reaped as soon as their RC reaches 0. *But* there is the design pattern of the autoreleasepool and the corresponding delayed release implied by `autorelease` (along with runloops). End result is that ObjC's reference counting is a bit different than CPython's *and* the compiler/runtime *can* write more efficient code under ARC than a human can while remaining definitively correct. Certainly, some important and applicable patterns! – bbum Jul 23 '13 at 02:44