I have a function which uses dispatch_async:
- (IBAction)action:(id)sender {
int i=10000;
NSString * data;
dispatch_queue_t queue = dispatch_queue_create("com.wang.queue", NULL);
__weak ViewController* weakSelf = self;
while(i>0)
{
@autoreleasepool {
data = [[NSString alloc]initWithFormat:@"%i",i];
NSString * str = data;
dispatch_async(queue, ^{{
[weakSelf print:str];
}});
i--;
}
}
}
-(void) print:(NSString*)str
{
NSLog(@"%@",str);
str = nil;
}
And then I press the button for five times continuously. After it was run complately,the memory didn't reduce. So I use Instrument to analyza where the memory was occupied. like this:
It showed that the memory of "data" was freed. It is "VM:performance tool data" who occupied the memory. The detail is :
I think something about "dispatch_async" was never freed.
Who can tell me what make the memory performed like this? Appreciate !
A couple of thoughts:
You are using
NSString
objects, but there are all sorts of caching/optimizations ofNSString
that can skew this sort of analysis. You should generally be wary of doing memory analysis withNSString
objects. You might want to repeat this withNSObject
or some custom class. I don't think it's the problem here, but something to always be cognizant of when debugging memory allocations.You're using
@autoreleasepool
but you have no autorelease objects. I presume you put that pool in just to be cautious, but your maindata
/str
object is not autoreleased, so this pool probably doesn't buy you anything. Also, FYI, GCD employs its own autorelease pools, anyway.Even if you did have
autorelease
object, thedata
variable is defined outside of the scope of your@autoreleasepool
and you're never eliminating that final strong reference inside the pool, so the pool would not accomplish anything. You should use the narrowest possible scope possible for your variables. In this case, I'd simply retire thedata
variable and just use your localstr
variable.It was suggested that you might have a retain cycle (a.k.a. a strong reference cycle). There is no such cycle, at least not in the code shared with us thus far.
Having said all of that, the "performance tool data" seems, to me, to be unrelated to the 10,000 objects you are creating. You have 347 objects accounting for 180 mb.
I wonder if this "performance data" is something that Instruments, itself, is creating (e.g. snapshotting, stack traces, etc.). I've done some experimentation and have been unable to reproduce the behavior you describe. I have tried changing the Xcode scheme to turn on a bunch of logging options (e.g. zombies, memory checks, logging, etc.) and I have tried changing Instruments to record the maximum amount of information (e.g. frequent snapshots, etc., keeping discarded items, recording reference counts, etc.). All of this was to no avail.
Perhaps you can share what Instruments settings you might have turned on (or try turning off a few). Likewise with the scheme for your app (making sure you've turned off unnecessary logging). Also, please edit your question, providing us details regarding what version of Xcode/Instruments you are using, as well as the target OS version, etc.