Re: NSMutableArray + NSEnumerator = No Memory
Re: NSMutableArray + NSEnumerator = No Memory
- Subject: Re: NSMutableArray + NSEnumerator = No Memory
- From: James Bucanek <email@hidden>
- Date: Sat, 22 Sep 2007 13:20:06 -0700
Bill Bumgarner <mailto:email@hidden> wrote (Saturday, September
22, 2007 12:05 PM -0700):
On Sep 22, 2007, at 11:36 AM, James Bucanek wrote:
1 - Use objectAtIndex: to iterate through the array.
2 - Create an auto release pool and discard the NSEnumerator
during every search.
This is likely a good idea to do regardless of the rest of the
problem as it is likely that you are causing, directly or
indirectly, temporary objects to be created. Dumping 'em
every so often when doing lots of looping is generally a good idea.
I was doing that already (once per collection), but not
aggressively enough to avoid this problem. In fact, if the
NSEnumerator wasn't making whole copies of the entire array
every time a new enumerator was created, there wouldn't be any
problem at all. During the search loop, I really only expected
one object (the enumerator) to be created, so at most there
would have been N objects created per auto release pool.
3 - Abandon NSArray and roll my own collection.
I'm leaning towards (1) because it minimizes the code change
and shouldn't incur too much additional overhead. (2) will
keep me from running out of memory, but doesn't guarantee that
other calls to objectEnumerator won't make gratuitous copies
of the array.
(3) is ultimately the best solution, as I can increase the
speed and reduce the memory footprint of the collection
considerably by dropping NSArray altogether. But that's a lot
of coding and I'd rather not make any radical changes in my
application at the moment.
Are you sure that it is actually making a copy of the objects
and that, given the number of iterations, you are simply
exhausting memory by filling up the autorelease pool with
temporary objects that are created as a part of your matching algorithm?
The search routine is very careful not to create any objects.
(It gets called a *lot*.)
I would be surprised if the implementation of NSArray has any notion of a previously allocated NSEnumerator still being active on the array.
Something does. I can easily reproduce this problem with a
simple program. In the case where I let each enumerator run to
the end o the collection, no extra memory is allocated. When I
interrupt each enumerator before it gets to the end and start
again with a new enumerator, the memory allocation starts to eat
up RAM with a vengeance. I'll post the test application if
anyone cares (it's only a few dozen lines).
Mutation of the underlying array is always unsafe during iteration and, thus, doing so is unlikely to add any safety during execution.
Which is why I'm really surprised that -objectEnumerator would
be duplicating the array. I can see why it would want to do that
if it want to be thread safe or protect against modification,
but in Cocoa that's documented as not being supported and known
to be hazardous.
(3) sounds fairly futile. NSArray and friends have been quite
highly optimized over time. Certainly, there are likely more
optimizations possible, but they are unlikely to be simple to
implement. Unless you have a highly specific usage pattern
for which a non-general algorithm will be a significant
performance win, it is unlikely that re-engineering that which
already exists in the Foundation is going to be much of a win.
Well, I do have a fairly specific/simple usage pattern. Once the
array is built, just about the only thing I do with it is
iterate over it in various ways. So it could be easily replaced
with a static array allocated with malloc() or NSData.
--
James Bucanek
_______________________________________________
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