iOS 5 has garbage collection. Here comes MacRuby/iOS?
pogodan.com
pogodan.com
(I don't think I'm violating any NDAs here, since ARC was up pretty big on one of the slides at the keynote. In any case, anybody who cares about this stuff is either at WWDC or at least has a dev account and has been pouring over the beta docs since they've gone online.)
Once you're familiar with the manual memory management conventions, it's not difficult, but this should make iOS development more approachable.
But how about looking at the docs yourself?
But yes, I think this feature really slipped through the cracks in the announcements I've seen so far (even Ars seemed confused about it)
(And MacRuby's AOT compilation works pretty well from what I've seen.)
If not then it's just what COM had.
Assuming that ARC works reliably and consistently, it'll be nice to lose some boilerplate, but the worst facet of reference counting -- object graph cycles -- still isn't fixed.
[1] There is support for zeroing weak references, but this is a very manual solution to the cycle problem.
edit: ah, now I get it. Cute.
http://docs.python.org/library/gc.html
Since the collector supplements the reference counting already used in Python, you can disable the collector if you are sure your program does not create reference cycles. Automatic collection can be disabled by calling gc.disable().Because it isn't. Garbage collection is something that happens at run time by a garbage collector via an algorithm like mark-and-sweep, tri-colour marking, etc, and as a block of code that's called at runtime it A) has a lot of information about your program and B) has a nontrivial performance impact.
Unfortunately I can't talk specifics (stupid NDA), but schrototo has said that it's a compiler-level feature, which would automatically disqualify it as being a bona fide garbage collector.
Speaking generically, any static feature is going to a great deal less powerful than its dynamic equivalent. Thinking of compile-time memory management as garbage collection is not just a leaky abstraction, it's a broken water main flooding into the street.
Think less "auto pilot" and more "cruise control". You still have to understand the accelerator and the break, you just don't have to use them as much.
Automatic garbage collection doesn't even require a garbage collector -- the monolithic piece of code that performs the scanning and reclamation of objects -- it simply requires freeing the programmer from the task of managing the storage of an object. Fancy collector algorithms are meant to improve throughput and latency -- you could definitely create an implementation of Java that uses automatic reference counting but you'd be searching for something faster really quickly.
If I have a language where I create a number of managed objects and the compiler's escape analysis determines that these objects never leave the function's scope and so changes them to be an alloca then you would have garbage collection without involving a garbage collector.
Again, if that's what automatic reference counting is as sold by Apple then I'd consider it to be garbage collection.
(I haven't done any Mac OS programming with GC, so I really don't know anything about it, but I've always heard people say the GC is not all that great. So my own uneducated guess is that while GC is messy and complicated, ARC is simple & doesn't have any runtime overhead (they say in the docs that retain/release is now much faster, as is autorelease using the new syntax).)
Can you back that up? I'd like to see a source that disconnects garbage collection the feature from a runtime garbage collector the implementation of that feature.
Independent of the semantic dispute, I don't think you understand what ARC, the iOS 5 feature, actually is. It's not a technology that "frees the programmer from the task of managing the storage for an object". Just to start with, that is a decision that can only be made at runtime, and as has been discussed ARC is a static-time feature.
These two things unfortunately share a name, but absolutely nothing else. The iOS 5 feature is not, and has no relationship to, and does nothing remotely like, the garbage collection algorithm with the same name.
(The same logic applies to longer "cycles" of references --- if A refers to B refers to C refers to D refers to A, then none of the objects in the cycle can be collected first, and they all stick around.)
In CPython, by the way, there is a separate garbage collector, which runs periodically to detect and mop up cyclic structures. Other implementations --- Jython and PyPy --- don't use reference counting to begin with.
(This is a point of definition independent of the subject at hand. Refcounting simply is a form of GC. Imperfect for most languages and many datatypes but GC all the same.)
It seems as though the groundwork has been laid, and from an aesthetic perspective, Ruby seems like a nice fit for Apple. Plus, it's not Python, which is arguably Google's baby.
If Apple was looking for a language that moved away from the low level C, what benefit would an "Objective" language bring over MacRuby, which is already using the native Objective-C system frameworks?
First class familiar Objective-C-style messaging and block syntax.
Stable, mature, well defined language invariants on par with Apple's requirements for its own APIs and languages.
"Objective-C without the C" would look more like Smalltalk or Strongtalk with a near identical syntax, not Ruby.
When you remove the C bits, Objective-C and Ruby use the same type system, conceptually speaking. They are both descendant from Smalltalk; the main feature differences really come down to the syntax alone.
I really like the idea of a higher level Objective-C-based language, I just don't necessarily see the business appeal of creating and maintaining a brand new language that only brings a more familiar, to Objective-C developers at least, syntax. Especially given the amount of effort Apple has been putting into MacRuby.
Objective-C is typed -- not just the C part, but the 'Objective' part too. You can cast around type system, but it's there.
The new compiler even uses inference of those types in order to implement ARC.
Especially given the amount of effort Apple has been putting into MacRuby.
Not Apple, just a few people that also work for Apple.
The article says that MacRuby is bundled with Lion as a private framework. Surely they wouldn't bundle it if they weren't using it? And being a private framework, it is not there for the benefit of third-party developers.
id something = nil;
[something countForObject: nil];
Completely valid, won't crash your program, and only enough type information to satisfy the compiler (but largely meaningless for anything but the most basic static analysis). The only requirement for the above to compile is that countForObject: is a selector defined somewhere in the include path for the file. Even that is a relatively soft requirement since you can pass arbitrary selectors to any object.And none of this has anything to do with ARC, as far as I can tell.
There was a first class language on Mac OS X which was fully statically typed. It was deprecated with Leopard and never introduced on iOS. The dual nature of Objective-C is one of its attractive properties.
The support for 'id' is only intended to serve as a mechanism to get around the lack of parameterized types, and as part of ARC, the compiler does now infer the types for alloc/init.
Did you even try my example? No compiler warnings are generated (nor should the be). What do you mean by defined method types? It is simply looking for any selector which matches on any class because there is not enough statically available information to know any different. Messages are always passed dynamically.
Are we talking about Objective-C? Are you familiar with NSInvocation? Or performSelector:, performSelector:withObject:, performSelector:withObject:withObject:? Or NSNotificationCenter's addObserver:selector:name:object:? This is all done at runtime. No special type information is available to the compiler when using these. Objective-C messagse are always sent dynamically, so the only ABI concerns are how the stack is prepared, and not the interface of the class of an object. You can define methods and swap them out at runtime, this feature would be useless if everything had to be known at compile time.
ARC needs to know that the types of Objective-C objects, id still works fine, beyond that it needs to know no other type information from what I can tell.
It seems we are talking past each other. Objective-C is not like C++, though. All methods are virtual, always. The runtime goes through great pains to make that efficient and still allow complete dynamism. This is orthogonal from ARC.
Only because it managed to match on a defined method type. If a class declaration hadn't been found at compile time with the given declared method, it would have issued a warning.
If the match was ambiguous and the types incorrect, it would have emitted incorrect code, and possibly a warning (or always, with -Wstrict-selector-match).
> What do you mean by defined method types? It is simply looking for any selector which matches on any class because there is not enough statically available information to know any different.
By 'defined method types', I mean methods declared on visible classes that match the given selector.
If it matches on the wrong one, the wrong dispatch function and/or the wrong function call epilogue will be emitted.
Method calls are ABSOLUTELY NOT ABI identical for all possible types. I can't possibly emphasize this enough.
For example:
- (void) performWithObject: (NSObject *) object;
- (void) performWithObject: (NSObject *) firstObj, ...;
The instructions emitted for a vararg dispatch ARE NOT the same as the non-vararg dispatch on all platforms, and incorrect method selection will result in undefined behavior on dispatch.> Are you familiar with NSInvocation? Or performSelector:, performSelector:withObject:, performSelector:withObject:withObject:? Or NSNotificationCenter's addObserver:selector:name:object:? This is all done at runtime.
> No special type information is available to the compiler when using these.
Yes, it is. Methods have associated type encodings that describe the return and argument types, and that's used to perform runtime dispatch with NSInvocation. This is why NSInvocation is so slow -- similar to libffi, it must evaluate the types and construct the call frame at runtime. It does this by evaluating the type data associated with method implementations by the compiler.
Methods such as performSelector rely on specific type conventions (such as void return, optional single object argument) and will fail if used with targets that do not match the expected convention.
Of course IMPs aren't identical if they take different parameters. This doesn't affect interchanging Objective-C types though. Yes, the arity and order are important, but the compiler doesn't enforce anything beyond that a pointer is passed for id types.
> This doesn't affect interchanging Objective-C types though. Yes, the arity and order are important, but the compiler doesn't enforce anything beyond that a pointer is passed for id types.
This is true prior to ARC: all ObjC pointers are the same size, and hence ABI-compatible given equivalent arity/order. It's theoretically possible that a future ABI could be incompatible between two methods returning void vs pointer return value, but currently, all supported ABIs return pointer-sized values in a register.
However, with ARC, this changes. The type system has been effectively extended to denote the required referencing behavior for calling code. This means that for a given arity/order, you must also have equivalent referencing attributes.
Thanks for the update, though! :)
Thanks for clarifying this solidly, though.
Would the Ruby developers who are considering building HTML5 apps go for native Ruby instead if given the option?
And would ruby developers use ruby if given the option? Somehow, I think so.
More important though is how performant and tight the app is, I think most developers who are wanting to have the best performance will choose native.
Unless they're doing some pretty strong analysis to remove redundant reference operations.
GC is still supported on MacOS X.
If a bus lock degrades your performance too much, either change your algorithm, or isolate that section of code and do it in another language that doesn't suffer the same performance issues.
It doesn't know that the object is only used in a thread-local context, so in many cases (eg, function args) it might not be able to assume that there is no concurrent refcounting action going on elsewhere, which eliminates other optimizations.
By definition, compilers have to be conservative about what callers can do, when humans can simply say "This function is not thread safe", or similar.
This is one reason that "real" GC is generally used instead of reference counting in all high performance garbage collected language. (In throughput-oriented systems, the GC is even a stop-the-world GC, since that removes quite a bit of concurrency/atomic operation overhead).
The other big one is that you need a garbage collector anyways if you want things to work in the presence of cycles.
EDIT: Perhaps someone with a Mac and access to this compiler can post some output of code with this feature enabled. I'd be curious to see what sort of output the compiler actually gives.
This speculation is annoying :)
It may not need to do any kind of complicated proving or cross-unit analysis, and instead opt to simply rely on the fact that every good Objective-C citizen follows the same social naming conventions. Things coming back from methods with "alloc", "copy", or "new" in the name are owned by the current method and need to be disposed of properly (release it at the end of the method, or if it escapes this method, add it to the autorelease pool). Everything else can be assumed to be taken care of and we need only bump the retain count if it's getting assigned to something with a scope larger than the current method.
It wouldn't catch everything, but it could be made predictable in behavior and eliminate a large percentage of the boilerplate.
self.blueView = [[BlueView alloc] init];
[self.blueView release];
etcIt's quite likely that whoever gets notified of the property change will attempt to access your object, but now your object is in a half-destroyed state.
self.blueView = [[BlueView alloc] init];
[self.blueView release];
When you allocate to get the proper retain count; I can demonstrate why by using a temporary variable: BlueView* bv = [[BlueView alloc] init];
//Retaincount = 1
self.blueView = bv;
//Reaincount = 2
[self.blueView release];
//retainCount = 1
And then in dealloc [self.blueView release];
//retainCount =0;
So in dealloc I could call your function, but there are things in various object packing schemes (KVO most importantly) where calling the setter like that screws stuff up. It's better to just call the getter (which should be side effect free) and release the returned object.So looking at retain counts in the original example:
self.blueView = [[BlueView alloc] init];
//Retain count 2
[self.blueView release];
//Retain count 1
and in dealloc [self.blueView release];
//Retain count 0
If I just did what you said, I'd get: self.blueView = [[BlueView alloc] init];
//Retain count 2
and in dealloc self.blueView=nil;
//Retain count 1, rut ro, memory leak