How expensive is it to create an NSAutoreleasePool
I have a method which needs to run in its own thread 88 times per second (it's a callback for an audio unit.) Should I avoid cr开发者_如何转开发eating an NSAutoreleasePool each time it's called?
Creating the NSAutoReleasePool itself shouldn't be too slow, but if there are a lot of objects to be dealloc'ed when you 'drain' the pool, that could start get slow. It's probably worth profiling how long the pool drains are taking.
Assuming that you've just come back from Instruments or Shark with concrete evidence that autorelease pools really are a performance concern in your app…
Creating your own autorelease pools is an answer to a dilemma. You do it when you are creating a lot of objects, in order to not create too many at once and either enter paging hell (on the Mac) or get a memory warning and/or termination (iPhone OS).
But autorelease pools are objects, too. They aren't free. The expense of a single autorelease pool is tiny, but in a loop where you're creating lots of objects, you're probably creating one pool every X objects, draining it, and creating another one for the next X objects.
Even then, the autorelease pools probably aren't that many and so won't add up to much. You should see this in your Instruments or Shark profile: Most of the time spent in -[NSAutoreleasePool drain]
is, in turn, spent in -[NSObject release]
. That's time you'll be spending whether you use an autorelease pool or not.
[EDIT: As of December 2011, autorelease pools can now be created without an object, with the @autoreleasepool
statement. They probably are still not free (at least without ARC), but now they are even cheaper than before.]
So the real solution in such cases is simply to create fewer objects. This can mean:
- Using and reusing buffers whenever possible, reallocating a previously-used buffer when the size needed changes. You may want to use the
malloc_good_size
function to round up the size, to make it less likely that you'll need to reallocate (you can skip reallocating if the old needed size and new needed size both round up to the same number). You may also consider only growing the buffer, never shrinking it. - Using and reusing mutable objects. For example, if you build up a string and then write it out to a document, instead of releasing it and creating a new one, delete its entire contents, or replace the entire old contents with the first portion of the “new” string.
- Adjusting the value of X (your pool-disposal threshold). Higher X means more momentary memory consumption, but fewer pools created and thrown away. Lower X means more pools, but less risk of paging out or getting a memory warning. This is unlikely to make much of a difference except when you raise X too far, or lower it from being too high.
Please see Mike Ash's Performance Comparisons of Common Operations. When he tested in 10.5, creating and destroying an autorelease pool took 0.0003577 milliseconds.
If you can avoid it, do that. If you can’t, there’s no need to worry about it, autorelease pools are created and released quite quickly. If you need a precise answer, set up a simple test and measure (which is always a good idea when speaking about performance).
精彩评论