Losing my memory - a caching problem?
Losing my memory - a caching problem?
- Subject: Losing my memory - a caching problem?
- From: Stuart Rogers <email@hidden>
- Date: Tue, 17 Aug 2010 11:10:45 +0100
I'm having enormous difficulty keeping tabs on memory usage in my current
project. I'm happy that I'm not leaking anything - Build & Analyse reports no
issues, and neither does Instruments (Object Allocations and Leaks). And yet,
when watching bulk memory usage I see my free RAM dropping like a stone
(at the expense of my inactive RAM) and within seconds it has chewed through
8GB and starts kicking off extra page files. The active RAM usage is fairly
modest, and nearer to what I would expect.
My app is a neural network that uses signature data based upon image files.
The above symptoms are most apparent during the testing phase, which
consists of the following, repeated for several thousand image files:
1. Read in an image from file (720x576px)
2. Create a signature from the image (~7kB)
3. Discard the image
4. Apply the signature to the network.
If I doctor my code to repeatedly use the same image file then the problem
doesn't arise, which suggests to me that my code is fine but that the system
is aggressively caching image data. Image caching is not welcome on this
occasion - I use each image file once only.
Any suggestions on how to tame this beast would be extremely welcome.
Here's the code I use to read in my images (error handling snipped for
clarity):
- (ImageSignature *)signatureForPath:(NSString *)path
{
ImageSignature *sig = nil;
NSURL *url = [NSURL fileURLWithPath:path];
NSDictionary *opts = [NSDictionary dictionaryWithObject:(id)kCFBooleanFalse
forKey:(NSString*)kCGImageSourceShouldCache];
CGImageSourceRef src = CGImageSourceCreateWithURL((CFURLRef)url,(CFDictionaryRef)opts);
if (src)
{
CGImageRef img = CGImageSourceCreateImageAtIndex(src,0,(CFDictionaryRef)opts);
CFRelease(src);
if (img)
{
sig = [self signatureForImage:img];
CGImageRelease(img);
}
}
return sig;
}
// Here's the signature creation code...
- (ImageSignature*)signatureForImage:(CGImageRef)img
{
// Create a CIImage by passing the image through our filter chain.
CIImage *ciImage = [self filteredImage:(CGImageRef)img];
// Create a bitmap and paint our CIImage into it.
NSBitmapImageRep *inBmpImgRep = [[[NSBitmapImageRep alloc] initWithCIImage:ciImage] autorelease];
NSInteger pixelsWide = [inBmpImgRep size].width;
NSInteger pixelsHigh = [inBmpImgRep size].height;
NSInteger samplesPerPixel = 4;
NSBitmapImageRep *bmpImgRep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:pixelsWide pixelsHigh:pixelsHigh bitsPerSample:8
samplesPerPixel:samplesPerPixel hasAlpha:YES isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace bitmapFormat:0
bytesPerRow:0 bitsPerPixel:0] autorelease];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bmpImgRep]];
[inBmpImgRep draw];
[NSGraphicsContext restoreGraphicsState];
// Create an ImageSignature and paint our bitmap into it.
ImageSignature *sig = [[[ImageSignature alloc] initWithSize:[bmpImgRep size]] autorelease];
float *buffer = [sig allItems];
// Signature creation snipped - it's a simple mapping of pixels to a float array
return sig;
}
// The images are pre-processed via some CIFilters...
- (CIImage *)filteredImage:(CGImageRef)img
{
// This method takes a CGImage and creates a filtered/scaled CIImage from it.
NSInteger srcWide = CGImageGetWidth(img);
NSInteger srcHigh = CGImageGetHeight(img);
CIImage *ciImage = [CIImage imageWithCGImage:(CGImageRef)img];
// Blur the image to smooth out the repeating noise from electronic interference.
CIFilter *discBlur = [CIFilter filterWithName:@"CIDiscBlur"];
[discBlur setDefaults];
[discBlur setValue:ciImage forKey:@"inputImage"];
[discBlur setValue:[NSNumber numberWithFloat:blurRadius] forKey:@"inputRadius"];
ciImage = [discBlur valueForKey:@"outputImage"];
// Other filters (scaling, edge detection, etc) snipped...
// We don't need pixels around the periphery, crop it.
CIFilter *cropROI = [CIFilter filterWithName:@"CICrop"];
[cropROI setDefaults];
[cropROI setValue:ciImage forKey:@"inputImage"];
CIVector *roiVector = [CIVector vectorWithX:roi.origin.x Y:roi.origin.y Z:roi.size.width W:roi.size.height];
[cropROI setValue:roiVector forKey:@"inputRectangle"];
ciImage = [cropROI valueForKey:@"outputImage"];
return ciImage;
}
Have I set up my caching policy (kCGImageSourceShouldCache) incorrectly?
I tried supplying a BOOL wrapped in an NSNumber but that made no difference.
This project is for Mac OS X 10.6 - I have no need to support anything earlier.
Stuart
_______________________________________________
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