Question

I need to create thousands of CGImage objects using CGImageSourceCreateThumbnailAtIndex(...).

The problem is that when using the simple CGDataProviderCreateWithURL(...) followed by CGImageSourceCreateThumbnailAtIndex(...), the system caches the contents of the file (in the inactive memory), which leads to significant performance loss.

The closest solution:

Here, it was suggested to use [NSData dataWithContentsOfURL:inURL options:NSUncachedRead error:nil] and then CGImageSourceCreateWithData(...) to prevent caching files by the system.

The problem with the closest solution

This solution requires to read the ENTIRE file to the memory before creating the thumbnail, which leads to another significant performance loss.

Things that I already tried:

  1. Using [NSData dataWithContentsOfURL:inURL options:NSUncachedRead|NSDataReadingMappedAlways error:nil]; but it seems to ignore the NSUncachedRead option (files being cached to the inactive memory).

  2. Using CGDataProviderCreateWithURL, but it also caches files.

  3. Edit: Using a custom CGDataProvider created with CGDataProviderCreateSequential(...) as @justin suggested, however CGImageSourceCreateWithDataProvider calls CGDataProviderCopyData which first copy the entire image data from my custom data provider (I want to read only the thumbnail), even before I call to CGImageSourceCreateThumbnailAtIndex.

Any suggestion of how to get the thumbnail without loading the entire file to the memory and without caching it?

P.S. I already set kCGImageSourceShouldCache to kCFBooleanFalse when creating the image source and the thumbnail, but it seems to relate only to the decoded data, and not to the raw data that is cached when reading the file.

Edit: I use 10.8. The implementation of functions such as CGImageSourceCreateWithDataProvider may be different on other platforms/versions.

No correct solution

OTHER TIPS

I urge you to make sure you understand how mapped memory, virtual memory, and disk caching actually work on your targeted systems (note: the implementations vary across OS X releases). I say this because the majority of Cocoa developers do not understand disk caching and memory mapping on OS X very well because it just doesn't get in the way of most people's work (yes, that is my own assumption). Nevertheless, I am one of the very small percentage who has spent a lot of time fighting it (and even filing bugs); opening and closing literally thousands of media assets is one of those qualifying cases where caching can become a real showstopper or at minimum a performance impediment.

To step around the cache: create a data provider using CGDataProviderCreateSequential and implement your own reader implementation which opens the file (e.g. using fopen), then disable the cache using the F_NOCACHE option of fcntl before reading. Then you can either run to disk every time you need data or implement your own caching strategy which is optimized for the data you read (e.g. cache the header in memory while the file is being read, but read the image data directly from disk). Life's easier when you ensure the file cannot be altered behind your back. Looks good in theory, anyways.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top