6 ms·
FastImageCache – iOS library for quickly displaying images while scrolling
- liuliu 13y agoIt does seem weird that they store the uncompressed image on the disk. I think that a benchmark on this comparing with compressed / decompress on CPU would be interesting because one is bounded on I/O, another is bounded by CPU throughput.
- conradev 13y agoOne thing that is often overlooked when considering file I/O is that the kernel caches previously accessed files for fast reads. This, combined with the lazy-loading mmap() can prove for good performance with simultaneous low memory usage for something like an image cache. This technique is used on the iOS home screen - both the icon images and the rendered icon labels are stored as uncompressed bitmaps on disk and mmap'd when needed into memory. The fast loading allows SpringBoard to aggressively recycle icon views.
- Groxx 13y agoDoes mmapping the file mean that it'll block on file I/O if it's not already cached, though? I don't see any claims (haven't read the code) that it prevents this.
- michaelmior 13y agoYes. If you mmap a file and then try to access it and it's not already in RAM, you'll block while the bit you're trying to access is paged in.
- mallorypaine 13y agoWhen the pages are first accessed, the file data is paged in, and yes, this will be a blocking operation. One way to mitigate this would be to force the data to be paged in using a background thread, so that the pages are live by the time Core Animation needs those bytes to render the layer. This page preheating isn't usually necessary for small images, which is the primary use case for FIC. FIC really pays off in a scenario like Path's mobile app. We have many, many small-to-medium-size user images to display, and those images are competing for CPU time with all of the styled text labels we're drawing. The less CPU we have to devote to images, the faster we'll be able to scroll.
- Groxx 13y agoAaah, all the text rendering, that lends more weight to storing them uncompressed. Hadn't thought of that, I was pondering more on the I/O being way slower than (uncontested, in retrospect) CPU of basic decompression. Well, Path is amazingly smooth for how much styled stuff is in it, so nice work :) The UI really does stand out in how well it's done.
- nielsbot 13y agoI've used this to track down my scrolling performance problems in the past, although it's been a while: https://github.com/nielsbot/Profiler https://github.com/nielsbot/Profiler (yes, I'm plugging my own code :-)
- malkia 13y agoWondering if there is any support for PVR compressed images(2bit/4bit)?
- skyebook 13y agoIt actually isn't all that surprising, we've hit similar bottlenecks where JPEG decompression on the iPhone ends up choking feeds that are scrolled through quickly. We didn't go the route of caching the uncompressed data on disk, though, we just keep the images in a maintained in-memory cache.
- nielsbot 13y agothat can work depending on how many images you have... Note also that there's a decompression hit loading PNG too.
- liuliu 13y agoExactly. I would think that a layered cache scheme probably could have the best of the two worlds (a good size of cached content on disk, and fast uncompressed image hit from memory). But using mmap'ed file instead of doing own layered cache seems less hassle. Also, you are doing decompression on a background thread, which shouldn't be much a choke on 4S and later devices (probably, again). I need to have some tests to backup my claims obviously :)
- skyebook 13y agoIf you're using libdispatch on the 4S you might consider using a serial queue (for NSOperationQueue just set the maxConcurrentOperationCount to 1) as it starts to eat the CPU pretty quickly if you're trying to load a lot of images. Even on the 5 I was surprised by how much it helped to have the images cached (no anecdotal data on the 5S as it came out way after we started caching)
- pugz 13y agoIt might vary depending on the image format. http://imageoptim.com/tweetbot.html http://imageoptim.com/tweetbot.html < This indicates that the disk throughput is more of a limiting factor than anything.
- jamieomatthews 13y agoWhats the difference between this and SDWebImage, if any?? I cant see a ton of different API differences. Looks like this probably wont support ARC, though.
- michaelmior 13y agoThe big difference in how the cache is managed. SDWebImage has worked well when I've used it, but it's cache management is much more simplistic. I'd be curious to try FastImageCache on projects I've worked on to see if there's any improvement. Scrolling performance can be a tough thing to optimize for.
- hboon 13y agoAre you aware of -fno-objc-arc?
- sircambridge 13y agoA better solution then dealing with 60fps scrolling : Don't scroll, Flip!
- dirtyaura 13y agoNot really, scrolling seems to be very natural interaction model on touch screens. If you compare UI approaches of different apps, most of the popular apps use scrolling, flipping hasn't really proven itself and it's a bit gimmicky
- rbritton 13y agoAs they made some note of, Core Animation is very picky about the image format you provide via the contents property. For example, if you retain a reference to a CGImageRef that you also assign to a CALayer's contents property, you will end up with at least double the memory usage if it's not in CA's preferred format and it makes a copy of it. In my experience doing that alone can help performance immensely. I've since lost track of the Apple documentation that said it, but CA prefers 16-byte alignment and (kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little) for the pixel format.
- nielsbot 13y agoI think it can change from device to device too
- alayne 13y agoIt's not using ARC. Is this legacy code, or couldn't they get equivalent performance with ARC enabled?
- mallorypaine 13y agoHello. Mallory Paine here. I wrote FIC. This is not legacy code...it should be trivial to convert it to ARC and performance should be unaffected. I'm a bit old school myself so I chose to write it with manual retains. Does this approach make the code more difficult for you to use within an ARC project?
- nielsbot 13y agoIt might even be faster under ARC since I think the compiler can optimize some retain/release calls. I think the ARC retain and release may be faster than -retain/-release, but I'm not sure about that. Overall, yes, it's less smooth to include non-ARC code in an ARC project.
- jdewald 13y agoI was under the impression that ARC simply inserts the retain/releases into the code essentially write before the compile, so in theory would be equivalent.
- LinaLauneBaer 13y agoARC inserts the retain/release calls but once that is done there is an additional step where duplicate retain/release pairs are eliminated.
- allsystemsgo 13y agoWhy would you write it with manual retains? Who doesn't use ARC at this point?
- rbritton 13y ago