Kjuly / ALAssetsLibrary-CustomPhotoAlbum

A nice ALAssetsLibrary category for saving images & videos into custom photo album.
http://www.touch-code-magazine.com/ios5-saving-photos-in-custom-photo-album-category-for-download/
MIT License
405 stars 101 forks source link

Performance issues with lots of Memory Warnings #10

Open ShadeApps opened 11 years ago

ShadeApps commented 11 years ago

Having downloaded the latest version of the library I'm seeing horrible performance even in the provided Demo App. In my own app I'm getting Memory Warnings regularly. while saving the image. What can be causing them? Attached are 2 profile logs, first of your demo app and second - of my own app implementing your library. Tested on the latest iOS 6 version on iPhone 4S. 01 02

Kjuly commented 11 years ago

Yes, you're right, the saving process will cost much memory. I just did a testing and confirmed that the part that drains huge memory is CG Image (maybe you can see it in Instruments as VM: CG raster data). The related code snippet (Demo: PhotosTableViewController.m L240) is:

CGSize sizeToSave = CGSizeMake(imageToSave.size.width, imageToSave.size.height);
UIGraphicsBeginImageContextWithOptions(sizeToSave, NO, 0.f);
[imageToSave drawInRect:CGRectMake(0.f, 0.f, sizeToSave.width, sizeToSave.height)];
finalImageToSave = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

This part is for resizing the picture to save. We can scale the image smaller or clip it in square like Instagram App does. However, the demo I offered here still use the original image's size, it's very big cause a high quality picture, {2448, 3264} as an example for my device. Actually this part is useless for saving an original image, cause we can just use the imageToSave and no need to do drawing process anymore. So I just modified the demo to comment out this part just in case someone else need it. ;)

Please let me know if you've any question for it, or any suggestion for the performance enhancement. Thanks!

B.t.w., this lib's original author is @MarinTodorov, I just did some modification based on it. If you're interested in the original one, you can refer it HERE. :)

Kjuly commented 11 years ago

Hi, I'll close this issue. Please reopen it if you've any question, thx! :)

ShadeApps commented 11 years ago

It turns out things only got worse with the next version of the library.I am now getting Memory warning at a rate of about 5 per second. You can clearly see this in the attached screenshot. And moreover, the app now uses about 45 mb of memory (I'm talking about the demo app you provide with the library). At the current state it makes the library literally unusable. ssp_temp_capture And the first time I save a photo I get this - 40 MB of memory! iamge Testing on iPhone 4S with iOS 7.0

Kjuly commented 11 years ago

Um.. That's weird, I'll take a look at it, thanks!

Kjuly commented 11 years ago

And got several leaks, but seems not the reason that cause your memory warning. Well, I'll look deeper when I'm free. :)


Created a new issue #12 for these leaks.

ShadeApps commented 11 years ago

Great, thanks!

Kjuly commented 11 years ago

After debugged for a while, I find that this issue exists only on iOS 7.0. Before iOS 7.0, memory will increase when save the photo, but not that much, it's okay. I located the ALAssetsLibrary's instance method -writeImageToSavedPhotosAlbum:orientation:completionBlock: that might leads the high memory usage. You can test the code below:

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  // Dismiss image picker view
  [self dismissModalViewControllerAnimated:YES];

  // Manage the media (photo)
  NSString * mediaType = [info objectForKey:UIImagePickerControllerMediaType];
  // Handle a still image capture
  CFStringRef mediaTypeRef = (__bridge CFStringRef)mediaType;
  if (CFStringCompare(mediaTypeRef,
                      kUTTypeImage,
                      kCFCompareCaseInsensitive) != kCFCompareEqualTo)
  {
    CFRelease(mediaTypeRef);
    return;
  }
  CFRelease(mediaTypeRef);

  // Manage tasks in background thread
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImage * imageToSave = nil;
    UIImage * editedImage = (UIImage *)[info objectForKey:UIImagePickerControllerEditedImage];
    if (editedImage) imageToSave = editedImage;
    else imageToSave = (UIImage *)[info objectForKey:UIImagePickerControllerOriginalImage];

    UIImage * finalImageToSave = imageToSave;

    ALAssetsLibrary * assetsLibrary = [[ALAssetsLibrary alloc] init];
    [assetsLibrary writeImageToSavedPhotosAlbum:finalImageToSave.CGImage
                                    orientation:(ALAssetOrientation)finalImageToSave.imageOrientation
                                completionBlock:nil];
  });
}

This code snippet just save the photo to album after take & use the photo. I've modified the size of finalImageToSave to very small, but still the same. You can set a breakpoint at ALAssetsLibrary * assetsLibrary = [[ALAssetsLibrary alloc] init];, you'll find all are fine except for writeImageToSavedPhotosAlbum step.

I just fired a bug report to Apple (ID: 15050428), hope we can be satisfied with the response. ;)


Above are all I can do right now, but for _"getting Memory warning at a rate of about 5 per second"_, um.. actually I cannot reproduce it. I receive the memory warning only on step of saving the photo, but not every time.


My environment: Xcode 5 with iOS 7.0 SDK. Device: iPhone 5 with iOS 7.0 GM installed.

ShadeApps commented 11 years ago

OK, great, I'll try to look into the problem more myself, thanks!

Kjuly commented 11 years ago

@ShadeApps pleasure, I'll do more research on it either :)