• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Using performSelector: on super
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Using performSelector: on super


  • Subject: Re: Using performSelector: on super
  • From: Wade Tregaskis <email@hidden>
  • Date: Wed, 06 Aug 2008 00:57:04 -0700

The try/catch setup is well optimized and introduces very little overhead. So in the nominal case, where there is no exception, there's almost no overhead at all. Even if an exception was thrown, NSException is fairly lightweight.

This is not particularly accurate.

There, I'll beg to differ.

Exception handlers are cheap ("zero-cost") to set up in C++ and in the
64-bit Objective-C runtime. They are unfortunately kind of expensive
to set up in 32-bit Objective-C. They are based on setjmp/longjmp.

setjmp/longjmp is very fast. Or at least it used to. I understand that setjmp has slowed down over the years as more and more state information needs to be saved to make it work. During my career I've implemented setjmp/longjmp a few times and it used to take only about a dozen machine instructions to squirrel away the current stack pointers into a local structure, return, and perform a conditional test. Probably faster than objc_msgSend.


I haven't measured it in ages, but I suspect that it's still reasonably fast. I have several performance intensive applications that I profile regularly, and my code uses exceptions and try/catch blocks a lot. I've never seen setjmp or longjmp show up in Shark as a hot spot. So from casual observation, I'd say that try/catch blocks don't slow things down too much.

Let me say straight up that I hate exceptions, and code that uses them. So, I am biased, though I've tried not to be with my experimentation.


A quick and dirty test program - one which simply throws exceptions as fast as possible in a fixed-iteration-count loop, measured using the 'time' utility - shows me that the whole exception shebang is about three or four times more expensive in 64-bit than 32, and that it's at least three orders of magnitude slower than returning an int. (all on Intel) I use that as a somewhat relevant counter-example given the traditional argument between error codes and exceptions as prevailing models, and given that the original case was using instancesRespondToSelector:, which while notably more complex ultimately boils down to returning a scalar, rather than creating an entire object as with exceptions. [[ admittedly I'm not considering additional messaging overhead ]]

And I quickly discovered the gotcha that since NSExceptions are autoreleased, if you happen to be triggering lots of them in a loop without explicit pool flushes, you'll unnecessarily enlarge your memory footprint.

I'm not presenting numbers since these tests are so primitive, and I don't want to go into unnecessary details; the point is well enough made. If anyone wants to do a full analysis with appropriate controls and timing and some Shark profiles, be my guest, by all means.

The prevailing wisdom has always been that exceptions are for exceptional cases. Maybe they would more appropriately titled as unexpecteds. Intentionally using them as the foundation for determining whether some class supports some optional or unofficial interface, or anything of that nature, is a gross abuse of them. And while, granted, you can happily throw thousands, perhaps tens of thousands of exceptions a second without a meaningful performance impact for most programs, it seems simply a bad and unnecessary habit to get into.

The comment that actually riled me enough to jump in on this thread was the ever-popular "premature optimisation" card being played. This card is almost always misplayed in discussions like this. Premature optimisation is making a design or implementation choice, on the basis of performance, without sufficient facts. It does not apply universally as a wildcard whenever you wish to override someone else's approach - arbitrary or not - with your own. In this case, it is well demonstrated and well documented that exceptions are expensive. Relying on them for normal control flow is a bad idea, and against common wisdom.

It does not need to be proven that it will definitely impact the final performance; there is a choice in this case between two functional equivalents for which once is clearly more appropriate and less likely to become an actual performance issue. This is not premature optimisation, it is simply mindful design.

Wade
_______________________________________________

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


References: 
 >Re: Using performSelector: on super (From: James Bucanek <email@hidden>)

  • Prev by Date: Re: "backporting" nibs question / Rhapsody license anyone?
  • Next by Date: Re: handling idle events
  • Previous by thread: Re: Using performSelector: on super
  • Next by thread: Re: Using performSelector: on super
  • Index(es):
    • Date
    • Thread