• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Monster memory leak and I can't figure out why
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Monster memory leak and I can't figure out why


  • Subject: Re: Monster memory leak and I can't figure out why
  • From: Jeff Schilling <email@hidden>
  • Date: Wed, 2 Jun 2010 23:28:23 -0400

Are you running with NSZombieEnabled=YES?  many an hour has been spent tracking down 'memory leaks' - I have some firsthand experience with this :-)
On Jun 2, 2010, at 9:51 AM, Ken Tozier wrote:

> Thanks all for the replies
>
> Re point #1: I was using Activity Monitor and both the "Real Memory" and "Virtual Memory" columns showed this 100+ MB leak every 5-10 seconds. After a minute or so of running, My app had gobbled up almost 2 gigs of memory.
>
> Re point #2: All the thumbnail conversion code is contained within this one method, so once it enters the loop, it doesn't exit till it's done.
>
> I tried using [[NSGarbageCollector defaultCollector] collectExhaustively], as Jonathan suggested, tried [image setCacheMode: NSImageCacheNever], but neither of those slowed the ferocious gobbling of memory.
>
> I finally resorted to using CGxxx functions and the problem disappeared. My App now hums along generating 12 to 15 thumbnails per second with a memory footprint in the 20 to 30 MB range. Here's what worked:
>
> - (NSString *) createJPEGThumbnail:(NSString *) inPath
> 			site:(NSString *) inSite
> {
> 	NSDictionary			*siteRecord,
> 							*pubRecord;
>
> 	NSString				*sourceName		= [inPath lastPathComponent],
> 							*sourceRoot			= [sourceName stringByDeletingPathExtension],
> 							*destName			= [[sourceRoot stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] stringByAppendingPathExtension: @"jpg"],
> 							*pubCode			= [self pubCodeFromPath: inPath],
> 							*thumbPath;
>
> 	NSFileManager			*manager			= [NSFileManager defaultManager];
>
> 	siteRecord				= [thumbDirectories objectForKey: inSite];
>
> 	pubRecord				= [[siteRecord objectForKey: @"publications"] objectForKey: pubCode];
>
> 	if (pubRecord == nil)
> 		pubRecord			= [[siteRecord objectForKey: @"publications"] objectForKey: @"~MISCELLANEOUS"];
>
> 	thumbPath				= [[pubRecord objectForKey: @"thumb_path"] stringByAppendingPathComponent: destName];
>
> 	if (![manager fileExistsAtPath: thumbPath])
> 	{
> 		NSURL						*sourceURL		= [NSURL fileURLWithPath: inPath],
> 									*destURL		= [NSURL fileURLWithPath: thumbPath];
>
> 		NSString					*imageType		= UtilPreferredUTIForFile(inPath);
> 		NSNumber					*maxPixels		= [NSNumber numberWithInt: maxDimension];
> 		NSDictionary				*sourceOptions	= [NSDictionary dictionaryWithObjectsAndKeys:
> 															imageType, kCGImageSourceTypeIdentifierHint,
> 															kCFBooleanFalse, kCGImageSourceShouldCache,
> 															kCFBooleanTrue, kCGImageSourceCreateThumbnailFromImageAlways,
> 															maxPixels, kCGImageSourceThumbnailMaxPixelSize,
> 															nil];
>
> 		CGImageSourceRef			imageSourceCG	= CGImageSourceCreateWithURL((CFURLRef) sourceURL, (CFDictionaryRef) sourceOptions );
> 		if (imageSourceCG != NULL)
> 		{
> 			NSDictionary			*imageProps		= (NSDictionary *) CGImageSourceCopyPropertiesAtIndex(imageSourceCG, 0, NULL);
> 			int						w				= [[imageProps objectForKey: @"PixelWidth"] intValue],
> 									h				= [[imageProps objectForKey: @"PixelHeight"] intValue];
>
> 			NSRect				thumbRect			= [self thumbRectWithSize: NSMakeSize(w, h)];
>
> 			NSDictionary		*destOptions			= [NSDictionary dictionaryWithObjectsAndKeys:
> 														[NSNumber numberWithInt: thumbRect.size.width], kCGImagePropertyPixelWidth,
> 														[NSNumber numberWithInt: thumbRect.size.height], kCGImagePropertyPixelHeight,
> 														nil];
>
> 			CGImageRef			imageRefCG			= CGImageSourceCreateThumbnailAtIndex(imageSourceCG, 0,  (CFDictionaryRef) sourceOptions);
> 			if (imageRefCG != NULL)
> 			{
> 				CGImageDestinationRef	destRef		= CGImageDestinationCreateWithURL((CFURLRef) destURL, kUTTypeJPEG, 1, NULL);
> 				if (destRef != NULL)
> 				{
> 					CGImageDestinationAddImage(destRef, imageRefCG, (CFDictionaryRef) destOptions);
> 					CGImageDestinationFinalize(destRef);
> 					CFRelease(destRef);
> 				}
> 				CFRelease(imageRefCG);
> 			}
>
> 			CFRelease(imageSourceCG);
> 		}
> 	}
>
> 	// make sure it worked
> 	if ([manager fileExistsAtPath: thumbPath])
> 		return thumbPath;
> 	else
> 		return nil;
> }
>
>
>
> On Jun 1, 2010, at 6:47 PM, Tony Romano wrote:
>
>> Hi Ken,
>>
>> This code by itself should not be causing a leak.  Couple of questions:
>>
>> 1.  How do you know you have a memory leak?  Sound like a silly question but you didn't tell us anything about what you are using to detect leaks.
>> 2.  Who is calling this code, how many times?  If you are passing the image to something else in the sections you have commented out and you are calling this many times, your memory usage may grow senza any cache'ing that maybe happening.
>>
>> I would suggest putting a NSLog statement at the beginning and look at your output window to make sure the code is not called more than you think.
>>
>> -Tony Romano
>>
>> On May 31, 2010, at 6:41 PM, Ken Tozier wrote:
>>
>>> Hi
>>>
>>> I'm trying to write a thumbnailer class that takes a path to a photo and creates a thumbnail at a user specified size. The code creates the thumbnails OK, but there's this monster memory leak, to the tune of about 100 MB every 3-4 seconds, that seems to be related to NSImage.
>>>
>>> What's happening is that if I comment out the line that initializes a new image, the memory leak disappears. I've tried forcibly releasing the images, tried autoreleasing them, tried creating a fixed size buffer into which all the images are read, nothing seems to work.
>>>
>>> I'm using garbage collection, so that along with the deliberate releasing of the images, makes me wonder why the collector isn't getting the hint, that it's ok to release the memory for these photos. Could someone point out what I'm doing in the following code that prevents the images from getting released?
>>>
>>> Thanks for any help
>>>
>>> - (NSString *) createJPEGThumbnail:(NSString *) inPath
>>> 			site:(NSString *) inSite
>>> {
>>> 	NSDictionary			*siteRecord,
>>> 							*pubRecord;
>>>
>>> 	NSString				*sourceName		= [inPath lastPathComponent],
>>> 							*sourceRoot			= [sourceName stringByDeletingPathExtension],
>>> 							*destName			= [[sourceRoot stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] stringByAppendingPathExtension: @"jpg"],
>>> 							*pubCode			= [self pubCodeFromPath: inPath],
>>> 							*thumbPath;
>>>
>>> 	NSFileManager			*manager			= [NSFileManager defaultManager];
>>>
>>> 	siteRecord				= [thumbDirectories objectForKey: inSite];
>>> 	pubRecord				= [[siteRecord objectForKey: @"publications"] objectForKey: pubCode];
>>>
>>> 	if (pubRecord == nil)
>>> 		pubRecord			= [[siteRecord objectForKey: @"publications"] objectForKey: @"~MISCELLANEOUS"];
>>>
>>> 	thumbPath				= [[pubRecord objectForKey: @"thumb_path"] stringByAppendingPathComponent: destName];
>>>
>>> 	if (![manager fileExistsAtPath: thumbPath])
>>> 	{
>>> 		// I've tried both of these, didn't make the slightest difference.
>>> 		// Both leaked memory at a furious pace
>>>
>>> 		// Option 1:
>>> 		NSImage						*image			= [[[NSImage alloc] initWithContentsOfFile: inPath] autorelease];
>>>
>>> 		/* do some stuff */
>>>
>>>
>>> 		// Option 2
>>> 		NSImage						*image			= [[NSImage alloc] initWithContentsOfFile: inPath];
>>>
>>> 		/* do some stuff */
>>>
>>> 		[image release];
>>> 	}
>>>
>>> 	// make sure it worked
>>> 	if ([manager fileExistsAtPath: thumbPath])
>>> 		return thumbPath;
>>> 	else
>>> 		return nil;
>>> }
>>> _______________________________________________
>>>
>>> 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
>>>
>>
>> -Tony
>>
>
> _______________________________________________
>
> 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

_______________________________________________

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

  • Follow-Ups:
    • Re: Monster memory leak and I can't figure out why
      • From: "Sean McBride" <email@hidden>
References: 
 >Monster memory leak and I can't figure out why (From: Ken Tozier <email@hidden>)
 >Re: Monster memory leak and I can't figure out why (From: Tony Romano <email@hidden>)
 >Re: Monster memory leak and I can't figure out why (From: Ken Tozier <email@hidden>)

  • Prev by Date: Re: Mail Frameworks
  • Next by Date: Re: How to change color of text in webView
  • Previous by thread: Re: Monster memory leak and I can't figure out why
  • Next by thread: Re: Monster memory leak and I can't figure out why
  • Index(es):
    • Date
    • Thread