NSMutableArray + NSEnumerator = No Memory
NSMutableArray + NSEnumerator = No Memory
- Subject: NSMutableArray + NSEnumerator = No Memory
- From: James Bucanek <email@hidden>
- Date: Sat, 22 Sep 2007 11:36:27 -0700
Greetings,
I've been tracking down a weird crash that only occurs for a
user in Germany.
I was eventually able to isolate the problem; My application is
running out of memory. The crash occurs at
NSMutableArray* files;
...
NSEnumerator* e = [files objectEnumerator]; <-- crashes in
CFArrayGetValues > __memcpy
It appears that -[NSArray objectEnumerator] is first making a
copy of the entire array!!!
I never noticed this before, because the collection were
reasonably small (5-100 items), but this user had 30,000 items.
The enumerator is used to search for a match (the match is
complicated, so isEquals/containsObject is not an option). This
will happen (you guessed it!) 30,000 times -- my application is
trying to allocate 900,000,000 temporary object pointers (30,000
x 30,000) and naturally runs out of memory.
I tried to write some test cases in order to reproduce this. I
turns out that this only seems to occur if other NSEnumerator
objects have been returned by this collection, and those
enumerators haven't finished enumerating through the entire
collection. Of course, since I'm using an enumerator to search
the collection for a match, this it the normal case.
I'm not happy with this development, and can't imagine why
NSArray/NSEnumerator would be doing this, but clearly I need to
develop some work around. (Not to mention that my faith in the
efficiency of the core Cocoa classes has been eroded.) I'll file
a bug report, but I clearly need a workaround.
Has anyone else run into this and is there a simple way to avoid
this problem? My options appear to be:
1 - Use objectAtIndex: to iterate through the array.
2 - Create an auto release pool and discard the NSEnumerator
during every search.
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.
--
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