Re: NSMutableArray + NSEnumerator = No Memory
Re: NSMutableArray + NSEnumerator = No Memory
- Subject: Re: NSMutableArray + NSEnumerator = No Memory
- From: glenn andreas <email@hidden>
- Date: Sat, 22 Sep 2007 15:52:42 -0500
On Sep 22, 2007, at 3:20 PM, James Bucanek wrote:
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.
Let's just try an experiment:
#include <Foundation/Foundation.h>
#include <stdio.h>
int main(int argc, const char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *a = [NSMutableArray array];
for (int i=0;i<30000;i++) {
[a addObject: [NSNumber numberWithInt: i]];
}
NSLog(@"%d objects",[a count]);
NSEnumerator *e1 = [a objectEnumerator];
NSNumber *v1;
while ((v1 = [e1 nextObject]) != nil) {
NSAutoreleasePool *p2 = [[NSAutoreleasePool alloc] init];
BOOL show = ([v1 intValue] % 1000) == 0;
if (show) NSLog(@"%@",v1);
NSEnumerator *e2 = [a objectEnumerator];
NSNumber *v2;
while ((v2 = [e2 nextObject]) != nil) {
if ([v1 isEqualTo: v2]) {
if (show) NSLog(@"%@ = %@", v1, v2);
break;
}
}
[p2 release];
}
NSLog(@"Enumerator %@, v1 = %@",e1,v1);
return 0;
}
If I compile and run this, here's what top says:
PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD
RSIZE VSIZE
16881 a.out 88.5% 0:04.88 1 13 31 1.23M 624K
4.00M 36.7M
It does take a while to fully execute, but memory usage never goes
above this.
If p2 is created _after_ e2 (so e2 is in the outer pool), memory
skyrockets, everything comes to a screeching halt.
So the behavior might be a bit surprising, but the solution is simple.
(For the record, it doesn't seem to matter if the array is mutable or
not - making an immutable copy of the array appears to have the same
problem)
Glenn Andreas email@hidden
<http://www.gandreas.com/> wicked fun!
quadrium | flame : flame fractals & strange attractors : build,
mutate, evolve, animate
_______________________________________________
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