1

I have discovered a weird thing - CCTexture2D object gets retained when it is loaded asynchronously either by usage of addImageAsync:(NSString*)path withBlock:(void(^)(CCTexture2D *tex))block or -(void) addImageAsync: (NSString*)path target:(id)target selector:(SEL)selector.

In order to verify this i have created a very simple project. Actually this is cocos2d template. I have two buttons, a png file mytexture.png and a function which prints memory being consumed in megabytes. This is the function:

void report_memory(void) {
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
                               TASK_BASIC_INFO,
                               (task_info_t)&info,
                               &size);
if( kerr == KERN_SUCCESS ) {
    NSLog(@"Memory : %f", info.resident_size / 1024.0f / 1024.0f);
} else {
    NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
}

While nothing happens and just cocos2d layer is displayed the memory is around 8 mb (on iPad). Let's click first button:

 [[CCTextureCache sharedTextureCache] addImageAsync:@"mytexture.png" withBlock:^(CCTexture2D *text){

            NSLog(@"Cache %@", [CCTextureCache sharedTextureCache]);

        }];

now the memory is around 24 mb. ok. let's click the second one:

[[CCTextureCache sharedTextureCache] removeTextureForKey:@"mytexture.png"];
 NSLog(@"Cache %@", [CCTextureCache sharedTextureCache]);

and the memory is still 24 mb!!! Why??? The only object which had reference to the texture was the cache, but it has removed it. Why is it still in memory? What referencing it? If i add a texture by using addImage: method it gets removed as i expect it to. So how to work it out? How to unload it from memory?

If you think that memory check function can give false data then i want to say that i have profiled the app with Instruments and it showed the same result.

Andrey Chernukha
  • 21,488
  • 17
  • 97
  • 161
  • are you interested in underlying stuff or do you want just to free memory? so second one - do you try to call + (void) purgeSharedTextureCache for CCTextureCache? – in.disee Nov 15 '13 at 17:27
  • @СергейМалетин make it an answer so i could accept it cause indeed it worked!!! you're my saver! thanks! if you explain the underlying stuff that would be just great – Andrey Chernukha Nov 15 '13 at 17:33
  • How are you checking the memory usage? – Guy Kogus Nov 15 '13 at 17:41
  • @СергейМалетин can you please explain the underlying stuff ??? so that we can have better idea, thanks. – lionserdar Nov 15 '13 at 17:42
  • @GuyKogus there's a function in my question. take a closer look – Andrey Chernukha Nov 15 '13 at 17:43
  • Why don't you use Instruments and make sure that it's correct? – Guy Kogus Nov 15 '13 at 17:55
  • @GuyKogus i used Instruments and i also mentioned it in my question))) – Andrey Chernukha Nov 15 '13 at 17:56
  • i've just checked closely for purgeSharedTextureCache method, and looks like it not really what you mean - it just clears CCTextureCache fully, so that's not what you want, if you add few textures to cache and then call purgeSharedTextureCache all of them will be freed, so do not use it) – in.disee Nov 15 '13 at 18:09
  • try one thing (would it free memory?) : [[CCTextureCache sharedTextureCache] removeTextureForKey:@"mytexture.png"]; double delayInSeconds = .0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ NSLog(@"Cache %@", [CCTextureCache sharedTextureCache]); }); – in.disee Nov 15 '13 at 18:15
  • @СергейМалетин no, removeTextureForKey won't work while purgeSharedTextureCache does exactly what i need. come on, you deserve your reputation, make it an answer – Andrey Chernukha Nov 15 '13 at 18:18
  • @GuyKogus ... my general take on instruments is that it is by and large incorrect, inaccurate and incomplete. Hardly ever use it anymore. – YvesLeBorg Nov 15 '13 at 18:19
  • @AndreyChernukha Using the mach_*() APIs to try and understand memory usage is about as productive as using `retainCount` to try and understand object leaks. There are far too many implementation details and moving parts to make the results usefully precise. – bbum Nov 15 '13 at 21:25

1 Answers1

1

Prefer to measure memory usage with Instruments.

As for the actual issue:

  • any sprite or sprite frame will also retain the texture
  • it may take some time before memory is freed, ie when the autoreleasepool is purged which means measuring memory usage directly after purge gives you the wrong impression (hence use Instruments)
CodeSmile
  • 64,284
  • 20
  • 132
  • 217