Re: ObjC in time-critical parts of the code
Re: ObjC in time-critical parts of the code
- Subject: Re: ObjC in time-critical parts of the code
- From: Michael Ash <email@hidden>
- Date: Sat, 17 Jan 2009 16:51:58 -0500
On Sat, Jan 17, 2009 at 2:02 AM, Justin Carlson
<email@hidden> wrote:
>
> Michael Ash wrote:
>>
>> Note that dispatch is not mandatory in ObjC either. It is possible
>> (you get little help from the compiler, but it's not hard) to use
>> either a vtable approach or a straight function call for method
>> invocation, as long as you don't mind the loss in functionality that
>> this implies.
>
> Hi Michael,
> If you prefer that route, that is your choice. Given the choice, I would
> (personally) rather avoid caching selectors and debugging/maintaining a
> program that used that behaviour when a well tested alternatives are built
> into another language's model. Regarding the model, I would not want to
> reinvent the messaging within my sources. Typical objc class design
> significantly reduces an optimizer's abilities to do its job.
I agree that it's ugly, but it's good to have the option. My preferred
approach is to use plain ObjC without such ugly optimizations, and
then add in such optimizations later if they become necessary. So far
they have almost never been necessary. Where they have been necessary,
I've found them to be quite clean, at least from my perspective as a
long-time C programmer. Here's one example of using dynamic-sized
public ivars to store per-thread per-object data structures instead of
storing everything in a dictionary:
http://www.mikeash.com/svn/ChemicalBurn/ChemicalBurnNode.h
This is a bit ugly but IMO not terribly so, and the speed gain was
impressive. The point here is that there's no reason to be afraid that
using ObjC will get you stuck in some performance hole that you can't
dig out of without a rewrite. Just like any other language, do good
high-level design and otherwise write the simplest thing that will
work, then come back later and make the hotspots faster.
>> I must object to this on two points.
>>
>> First of all, the speed difference is only in messaging and in object
>> allocation (ObjC not having stack objects means more reliance on the
>> heap allocator). There is absolutely nothing else to it. If you are
>> finding differences in speeds for similar operations it's almost
>> certainly because of differences in the implementations of the
>> libraries. For example, you'll find that std::string blows the pants
>> off NSString. It's not because NSString is hobbled by Objective-C,
>> it's because NSString is vastly more complex and capable. As another
>> example, a std::vector<int> will blow the pants off an NSMutableArray
>> of NSNumber. Nothing to do with messaging (or allocation), and
>> everything to do with the fact that the C++ version is working with
>> primitives while the ObjC version is not.
>
> This is not actually the case. Foundation -> CoreFoundation types were one
> significant category of changes. In the aforementioned rewrites, Foundation
> types were replaced with CoreFoundation types as opposed to std types.
> Specifically, this _does_ mean that autorelease overhead was reduced in the
> process, though I consider that a part of the language that cannot be
> avoided (in using Apple's implementation/libraries) and thus valid to
> include in the differences. I never tried to hide that fact when I said
> "when converting class families/libraries to C++ for standard application
> code". GC was not used, figures came from optimized builds. In fact, the stl
> was rarely used. There *is* more to it, and much of that difference takes
> place during compilation.
I would place autorelease in with "object allocation", which I already
mentioned. Autoreleasing an object just somewhat increases its
allocation costs. There's the question of memory pressure, but if you
encounter that, it's easily dealt with by adding inner autorelease
pools, so it's not inevitable.
I'd be really surprised if you turned up a speed difference between
otherwise identical code using NSString and CFString or other
toll-free-bridged Foundation/CF classes. They use the same
implementation underneath, after all, so the only difference is
messaging and autorelease, neither of which are going to be
significant compared to the real work going on underneath in most
cases.
>> Second, I disagree that C/C++ will be slower only in exceptional
>> circumstances. Each language has its strengths and weaknesses, and
>> ObjC's strength is having a wicked fast general dispatcher.
>> (Considering the decisions going on behind the scenes to figure out
>> what to invoke, the ~12 CPU cycles spent on each dispatch is a
>> ridiculously small number.) If your problem happens to map to dispatch
>> well, then ObjC will be faster for you.
>>
>> Now, I'm certainly not going to argue that you want to involve ObjC
>> dispatch in intensive numerical code or anything of the sort. C or C++
>> clearly win there.
>
> So we are in agreement on that. When I was speaking of 'exceptional
> circumstances', I was speaking of performance critical code (i.e. numerical)
> specifically.
Not sure how numerical code gets a monopoly on performance critical
code here.... There's a whole universe of performance critical code
out there which doesn't involve straight-up number crunching.
>> It's simply that they're not good at it, which is fine, they're not
>> supposed to be.
>
> I'd say: Not good at it as a general byproduct of implementation or poor
> design choices and careless maintenance/evolution, but not specifically due
> to the underlying runtime/dispatcher. In other words, the improper
> implementation of some form of an 'intermediate' dispatcher within the
> libraries used. We already know that C++ dispatch is faster than Objective C
> (correct?).
I'm afraid I don't really understand most of this paragraph. Yes, C++
dispatch is faster than Objective-C dispatch, roughly 3 cycles for a
virtual function versus roughly 13 cycles for objc_msgSend when I
tested it. It's also vastly less capable. The part I don't understand
is everything before that point. What do you mean by "not specifically
due to the underlying runtime/dispatcher", and "the improper
implementation of some form of an 'intermediate' dispatcher"?
>> When I've seen C/C++ code try to
>> replicate this kind of decision-making, it tends to involve a lot of C
>> strings, tons of linear searches, binary searches, or maybe a nice
>> hash table, and you're lucky to get within a couple orders of
>> magnitude of objc_msgSend.
>
> Returning to my stance that they (C/C++/Objective-C) are very different
> tools with different mechanisms, and inherent pros and cons. Again, I would
> rather leave this task to Apple (in the case of implementing the ObjC
> runtime/dispatch), who have invested more energy into it than I ever could.
Right, that's basically all I'm saying here. Dispatch is important in
the sorts of programs that the people on this list usually write, and
by using ObjC you get to let Apple write a really good, fast
implementation of it instead of writing a bad, slow implementation of
it the way you might in a different language.
> Respectfully, there is clearly more than dispatch involved. I would agree
> that this is unrelated to the original post. It *is* (IMO) related to the
> observation Jens had along the way, that changing the implementation to
> plain C solved the issue.
I must again disagree. If he was seeing frequent multi-millisecond
spikes from calling an empty ObjC method then I think it's pretty
clear that he is essentially an unreliable narrator in this story, and
if the conversion to C made his problem go away, we still have no idea
what particular part of that conversion was responsible. Since using
ObjC simply could not cause the symptom he observed, the fact that he
eliminated it by switching languages would tend to imply that
something else, whatever was actually responsible for the problem, got
changed as well.
Mike
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden