Memory IO memory is growing

I ran my application in Tools with VM Tracker and discovered the growing memory consumption of Image IO.

Instruments with initWithContentsOfFile:

In fact, the application did quite a bit of reading images from disk using initWithContentsOfFile: I read once that this method was Satan's caviar, so I replaced it with the following:

 NSData *data = [NSData dataWithContentsOfFile:path]; UIImage *image = [UIImage imageWithData:data]; 

This reduced virtual memory significantly (about 60%), as shown below:

Instruments with imageWithData:

But why does the Image IO virtual memory grow over time when there are no leaks, and my application just uses 15 MB of live memory?

Is there something I can do to ensure that this IO image memory is freed?

Basically, reading an image from a disk is as follows:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) { NSData *data = [NSData dataWithContentsOfFile:path]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ imageView.image = image; }); }); 

I also tried the following without any significant changes:

  • Use [NSData dataWithContentsOfFile:path options:NSDataReadingUncached error:nil] instead
  • Move UIImage *image = [UIImage imageWithData:data]; primarily
  • Make everything in the main line

Which makes me think that the problem may be elsewhere.

+4
source share
2 answers

Thanks to Heapshot Analysis, I discovered that the images were saved using NSCache .

The problem was that NSCache did not issue any memory error warnings. Solution: make it observe UIApplicationDidReceiveMemoryWarningNotification and delete all its objects when this happens. Here's what the tool looks like now:

Instruments with memory warning draining

The tools are awesome. Thanks to @NikolaiRuhe and @nielsbot for making me dig deeper.

In addition, I must add that memory consumption decreased when using NSData , because dataWithContentsOfFile does not account for retina files (d'uh). Thus, imageWithContentsOfFile: may still be Satan's spawn, but that was not his mistake.

+1
source

You should at least wrap the background processing in an autoplay pool:

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) { @autoreleasepool { NSData *data = [NSData dataWithContentsOfFile:path]; UIImage *image = [UIImage imageWithData:data]; dispatch_async(dispatch_get_main_queue(), ^{ imageView.image = image; }); } }); 

This way you will make sure that any objects with auto-implementation on the background thread go away as quickly as possible.

+2
source

Source: https://habr.com/ru/post/1497271/


All Articles