iOS 9 [UIImage ImageNamed:] poor performance

Prior to iOS 9, loading images from your bundle using [UIImage imageNamed:] was quite fast, and appeared to be coming from a cache. Now on iOS 9, that same call is an order of magnitude slower. I noticed this because a variable height cell TableView of mine is performing poorly on iOS 9, and I tracked it down to the loading of some images during cell height calculations. UIImage imageNamed is now slow enough that it should not be called in preparations for TableView cells. My temporary workaround is to statically load the images I need once. Attached is a sample project used to get the following performance numbers:

iPhone 6 running iOS 8.4 0.042 seconds to load 4 images 100 times

iPhone 6 running iOS 9 GM 0.83 seconds to load 4 images 100 times


Interestingly, running this same test on an iPad2 has radically different results:

iPad 2 running iOS 8.4 0.11 seconds to load 4 images 100 times

iPad 2 running iOS 9 GM 0.13 seconds to load 4 images 100 times



So, for some reason, loading images on an iPhone 6 using UIImage imageNamed: is 8x slower than it is on a iPad 2!?


I logged bug 22218487 which was closed as a duplicate of 21825629 which is also closed with no further information. Looks like this problem still exists in iOS 9 GM. Does anyone have any further information on this issue (perhaps you were the submitter of 21825629) I would like to know what Apple said on the other bug.

Accepted Reply

Good news folks. Looks like this is fixed in iOS 9.1 I'm still seeing a small advanage in performace when calling [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] which is surprising, but 9.1 is back to the fast cached performance that we had in iOS 8.4

Replies

i have same issues.

I have the same issue with this too. The performance is extremely bad and it just can not be ignored.

Not tested what I'm thinking, but I ran in a similar issue with UIFont fontWithName a time ago.

The problem in that case was about case sensitiviness. When not specified the name exactly as it appears (uppercase or lowercase), the loading process took 10x time.


Maybe it can be something similar...

I got the same issue...I am seeing with Instruments a 10x perf regression... Anyone has a clue?

Much to my surprise, I experienced huge performance regression when calling


[UIImage imageNamed:imageName];


on iOS 9.0.


However, switching the code to

[UIImage imageNamed:imageName inBundle:nil compatibleWithTraitCollection:nil];


improved the performance of my UICollectionView back to normal.


It sounds crazy, but it really worked for me. Please check if it works for you.

Interesting workaround. Changing to [UIImage imageNamed: inBundle: compatibleWithTraitCollection:] does improve performace, but it isn't back to where it was with iOS 8.4. My test gave me a time of 0.235 seconds with [UIImage imageNamed: inBundle: compatibleWithTraitCollection:] To those that are also experiancing this problem, can you please log bugs with Apple?

I'm experiencing the same thing here. Difference from iOS 8 and iOS 9 is huge.


Filed bug under radar #22745204.

Just curious, do you have all of the images set (1x, 2x, 3x, etc.) in the asset catalog?

Any updates on that one? I have the exact same issue 😟 Horrible performance using iOS9 which was super snappy in iOS8...

Did Apple react to any of the radars?

I experience the same issue. TableViews with images stutter, even on iPhone 6S. We never had such issues on iOS 8. I tracked this down to loading with [UIImage imageNamed:] from an asset catalog. It does not have a performance hit if you load the image directly from the bundle. My workaround is to either cache the images myself or to remove them from the asset catalog and load from the bundle instead. This seems to be a serious bug in my opinion, Apple is really letting it slip recently...

Yes, 1x, 2x and 3x. Try to remove the images from the asset catalog and put them in the bundle. This results in regular performance in my case. Seems to me the caching is broken in iOS 9 when loading from the catalog.

I too see issues with [UIImage imageNamed:] and its caching. In my project, it keeps allocating way more memory than it should. I have several 3K images that the user can flip through, however with each call to [UIImage imageNamed:] I see a 3.5MB jump in memory that never gets releases. After 50 images my app is using over 175MB and I get a memory warning. I have tried moving the images out of an xcasset but that didn't help. So I then switched to using [UIImage imageWithContentsOfFile:] and at least now the memory isn't being retained but each image is still loading at 3.5MB instead of 3K.

Hey rp,


Most images are compressed (i.e.: very efficiently stored by encoding the image, not "made to look bad"), even in lossless formats. When you're opening image data, you need 4 channels (R, G, B, A) * 1 byte per channel * number of pixels in the image. For example: I have a PNG that is 0.258 KB in size, but it's 1200x1121 in resolution. When it's opened, it needs to store 1,345,200 pixels in memory, which means it needs ~5.3 MB of memory. This jives with the memory usage I've seen. The resolution of the images determines your memory needs, not the size in bytes (unless you're using uncompressed file formats). I'm not sure what you mean by "3K images". What are the resolutions of your images?


One other thing I've run into is using UIImageView's animatedImages. If you are using this property, iOS will retain the image data permanently, even if the image view is released.


Other than that, I haven't had problems with imageNamed: retaining memory unless I had objects that were being retained without my knowledge that had a hold on the data. I'd take a second look and make sure your objects are being properly nil-ed out when you aren't using them.

Hi MWRGeorge,


Thanks for the feedback. Yes, I did take into account the image size once expanded but the odd thing was that it wasn't releasing the memory (using Instruments to track memory usage). I know using [UIImage imageNamed:] will cache images but it should also release when necessary and this wasn't the case. After switcing to [UIImage imageWithContentsOfFile:] and taking the images out of the xcasset, the memory is at about half, 1.8MB, and it is not being retained. So, I'm still not sure what was happening but I seem to have resolved my issue for now.

Thanks for that information. I did some testing with the sample app I used to submit my radar on this, and there is deffinately a difference between loading an Image from an asset catalog vs from the Bundle. Here are the timings I got on an iPhone 6 running iOS 9.0.2. This is loading 4 small images 100 times in a loop:


From Asset Catalog with [UIImage imageNamed:] 0.81

From Asset Catalog with [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] 0.21


From Bundle with [UIImage imageNamed:] 0.35

From Bundle with [UIImage imageNamed:inBundle:compatibleWithTraitCollection:] 0.1


All of those times are still quite a bit slower than on iOS 8.4. I'm going to submit a new Radar with this additional information.