Archive for January 2nd, 2009

Image memory

So our latest project — essentially an image viewer for a largish set of static images — which ran fine in the simulator, was in fairly short order throwing up memory warnings and then freezing on the device. Hmmm. That’s bad. So we resolved it, and our process might be useful for you too.

First off, we went to Run/Start With Performance Tool/Leaks in Xcode, to run it under Instruments. That didn’t produce any evident problems with allocation or release of objects. Hmmm, hmmm.

Next, we tried running it under the LLVM/Clang Static Analyzer. (If you haven’t heard of it before, there’s a couple good introductions here and here.) But wait, you say, that doesn’t work for iPhone development? Ah, but indeed it does! What it doesn’t work for is analyzing ARM binaries, so it’s not helpful for device builds no … but the simulator uses Intel binaries! Convenient, yes? Thanks to this post for explaining to us

My workflow after I’ve really worked on the codebase is now:

  • Make sure the project default settings are “debug” and “simulator”
  • Close Xcode
  • open a terminal window and “cd” to the project directory
  • run rm -rf /tmp/scan-build*
  • run rm -rf build/;scan-build --view xcodebuild
  • Open Xcode and fix errors

That’s been working great for me ever since.

Excellent, excellent. This’ll sort us right out! So we ran it … and it came up with exactly one “bug”, an apparent dead store which is actually completely intentional, it’s just that our “check” macro confuses it.

   BOOL wroteOK = [self.favoritesList writeToFile:[self favoritesPath] atomically:NO];

   check(wroteOK);

Righty-ho. Well, it’s all well and good that our entire application is indeed completely bug free to all appearances, pat pat, but that leaves us with an invisible problem. Oh, those are the best kind.

So back to Instruments and the ObjectAlloc tool we went to look for some hints. And it turns out that, despite our code being completely impeccable as far as we thought, newly loaded images were never getting released. As our image folder “pictures” is 70.4 MB, the problem is evident.

The culprit, it turns out, is loading images with [UIimage imageNamed:] which not only caches all images it loads for future use, but is widely regarded as being overly aggressive in its caching behavior. The recommended solution is to use [UIImage imageWithContentsOfFile:] to load your images, which does not cache anything. Good, good … except then the scrolling performance in the image selection gallery list was awful, pokey and jittery. Yuck!

Sooooooo, what we ended up doing was creating a new folder “thumbnails” with list-cell-sized versions of the images, which worked out to 2.9 MB total, a manageably cacheable amount it appears, and loading those with +imageNamed, then using +imageWithContentsOfFile to bring up larger sizes of individual images as selected with no caching. That makes the selection interface nice and smooth again, and the application not break. Success!

[UPDATE: Oh, the fetching naïveté. Isn't it cute? Turns out that +imageNamed is MUCH MORE EVIL than was believed at this point. Executive summary of update link: Do your own caching for any nontrivial amount of images.]

Continue Reading →
8