• 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: Excessive NSImage caching (or leaking)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Excessive NSImage caching (or leaking)


  • Subject: Re: Excessive NSImage caching (or leaking)
  • From: David Remahl <email@hidden>
  • Date: Sat, 26 Apr 2003 01:00:19 +0200

After creating a very simple test case, I have found that the leak is indeed dependent on wether the work is done on the main or the secondary thread. There is no leak if the work is done on the main thread, but if I detach a new thread, there is massive leakage.

According to Using the AppKit from Multiple Threads <http://developer.apple.com/techpubs/macosx/Cocoa/TasksAndConcepts/ ProgrammingTopics/Multithreading/Tasks/appkit.html#//apple_ref/doc/uid/ 20000743/BAJJDIHH> creating views and windows on non-main threads is allowed, but "There is some possibility that window objects may leak in an application that deals with a lot of windows concurrently".

Does anyone know of a trick to make the leak stop? Some cleanup method to call every now and then to let the graphics system release stuff? Otherwise I will have to redesign and have the program do the work on the main thread.

If someone is interested in having a look, here is the test case:

<http://ittpoi.com/IconImageBug.tgz> (17 kB)

/ Rgds, David

On Wednesday, April 23, 2003, at 09:10 PM, David Remahl wrote:

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.
_______________________________________________
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.

References: 
 >Excessive NSImage caching (or leaking) (From: David Remahl <email@hidden>)

  • Prev by Date: Re: NSOpenGLContext and window re-opening
  • Next by Date: Re: NSOpenGLContext and window re-opening
  • Previous by thread: Excessive NSImage caching (or leaking)
  • Next by thread: Can a ScreenSaverView quit itself?
  • Index(es):
    • Date
    • Thread