Excessive NSImage caching (or leaking)
Excessive NSImage caching (or leaking)
- Subject: Excessive NSImage caching (or leaking)
- From: David Remahl <email@hidden>
- Date: Wed, 23 Apr 2003 21:10:14 +0200
Dear list,
I have a problem with some code dealing with NSWorkspace / NSImage
leaking loads and loads (well, relatively speaking, anyway) of memory.
The code that leaks uses -[NSWorkspace iconForFile:(NSString*)file] to
retrieve the icon of a file at a certain place.
The code runs in a separate thread, rigged with three autorelease pools
that empty at certain levels.
Since I'm only interested in the biggest of the icon sizes present, I
extract the correct NSBitmapImageRep from the image. In essence, this
is the code I'm using:
- (void)thread
{
while( !quit )
{
NSAutoreleasePool *autoPool = [[NSAutoreleasePool alloc] init];
somePath = [self getAPath]; /* some path indicates a different file
for each pass through the loop. */
NSBitmapImageRep *largestRep = [self
getIconRepForFileAtPath:somePath];
unsigned char *bmpData = [lagestRep bitmapData];
// do whatever to bmpData;
[autoPool release];
}
}
- (NSBitmapImageRep *)getIconRepForFileAtPath:(NSString *)path
{
NSImage *icon= [[NSWorkspace sharedWorkspace] iconForFile:path];
NSArray *reps = [icon representations];
NSBitmapImageRep *rep = nil;
if( [reps count] )
rep = [reps objectAtIndex:0];
return rep;
}
Profiling and memory debugging using OmniObjectMeter (and ObjectAlloc)
reveal a lot of interesting things about this code.
One curious thing about the code is that while [[NSWorkspace
sharedWorkspace] iconForFile:path] executes in almost no time, the
thing that takes a lot of time is the [icon representations] message.
According to the profiling, most of the execution time is then spent to
actually read the icon data - ie, it is loaded lazily when needed.
My first question: Is there a way to avoid the lazy loading of _all_
the representations, when the only one I'm really interested in is
representation at index 0? There is no public NSImage way to get at
just a single representation, and the private interfaces are way too
contrived for me to even think of using them.
My other question concerns the actual memory leak. It turns out, that
for each loop in -thread, quite a few objects leak, even though
everyone can see that I have properly balanced everything. The
following objects leak more or less once per representation per loop:
NSView
NSWindowGraphicsContext
CFArray (multiple variable)
CFArray (store-deque)
Anonymous bytes (probably cached data related to the above classes)
Note that no NSImages leak, nor do any NSBitmapImageReps.
Analyzing the retain count history of the objects above (in OOM), I
find that they are one release short. They all came into existence in
[NSImage representations] and were all retained / released /
autoreleased a number of times.
I'm not sure wether this is a real bug, or if its just some aggressive
caching policy gone terribly wrong. Or if it perhaps is a side-effect
of me using it from a secondary thread.
But the end result is a massive leakage. It is a difficult bug to work
around, since I don't have any references to the objects that leak. It
should be noted that the problem seems to be in how icns images are
handled. If I replace the NSWorkspace call with something like this:
NSImage *icon = [[[NSImage alloc]
initWithContentsOfFile:@"/path/to/someIcon.icns"] autorelease];
the net result is the same.
I request suggestions as to how to solve this...Please don't suggest I
use the IconFamily class, since it uses initWithData: on the icns data
to implement its -imageWithAllReps method.
The only solution I can see, is to reimplement all of
NSWorkspace/NSImage's code to go from an IconRef to an icon image. That
is what is being done in [icon representations] by means of various
PlotIconRefTo* function calls (more or less private).
/ Sincerely, David Remahl
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.