SkillAgentSearch skills...

FastImageCache

iOS library for quickly displaying images while scrolling

Install / Use

/learn @path/FastImageCache
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Fast Image Cache Logo


Carthage compatible

Fast Image Cache is an efficient, persistent, and—above all—fast way to store and retrieve images in your iOS application. Part of any good iOS application's user experience is fast, smooth scrolling, and Fast Image Cache helps make this easier.

A significant burden on performance for graphics-rich applications like Path is image loading. The traditional method of loading individual images from disk is just too slow, especially while scrolling. Fast Image Cache was created specifically to solve this problem.

Table of Contents

Version History

  • 1.0 (10/18/2013): Initial release
  • 1.1 (10/22/2013): Added ARC support and more robust Core Animation byte alignment
  • 1.2 (10/30/2013): Added support for image format styles and canceling image requests
  • 1.3 (03/30/2014): Significant bug fixes and performance improvements

What Fast Image Cache Does

  • Stores images of similar sizes and styles together
  • Persists image data to disk
  • Returns images to the user significantly faster than traditional methods
  • Automatically manages cache expiry based on recency of usage
  • Utilizes a model-based approach for storing and retrieving images
  • Allows images to be processed on a per-model basis before being stored into the cache

How Fast Image Cache Works

In order to understand how Fast Image Cache works, it's helpful to understand a typical scenario encountered by many applications that work with images.

The Scenario

iOS applications, especially those in the social networking space, often have many images to display at once, such as user photos. The intuitive, traditional approach is to request image data from an API, process the original images to create the desired sizes and styles, and store these processed images on the device.

Later, when an application needs to display these images, they are loaded from disk into memory and displayed in an image view or are otherwise rendered to the screen.

The Problem

It turns out that the process of going from compressed, on-disk image data to a rendered Core Animation layer that the user can actually see is very expensive. As the number of images to be displayed increases, this cost easily adds up to a noticeable degradation in frame rate. And scrollable views further exacerbate the situation because content can change rapidly, requiring fast processing time to maintain a smooth 60FPS.<sup>1</sup>

Consider the workflow that occurs when loading an image from disk and displaying it on screen:

  1. +[UIImage imageWithContentsOfFile:] uses Image I/O to create a CGImageRef from memory-mapped data. At this point, the image has not yet been decoded.
  2. The returned image is assigned to a UIImageView.
  3. An implicit CATransaction captures these layer tree modifications.
  4. On the next iteration of the main run loop, Core Animation commits the implicit transaction, which may involve creating a copy of any images which have been set as layer contents. Depending on the image, copying it involves some or all of these steps: <sup>2</sup>
    1. Buffers are allocated to manage file IO and decompression operations.
    2. The file data is read from disk into memory.
    3. The compressed image data is decoded into its uncompressed bitmap form, which is typically a very CPU-intensive operation.<sup>3</sup>
    4. The uncompressed bitmap data is then used by Core Animation to render the layer.

These costs can easily accumulate and kill perceived application performance. Especially while scrolling, users are presented with an unsatisfying user experience that is not in line with the the overall iOS experience.


<sup>1</sup> 60FPS0.01666s per frame = 16.7ms per frame. This means that any main-thread work that takes longer than 16ms will cause your application to drop animation frames.

<sup>2</sup> The documentation for CALayer's contents property states that "assigning a value to this property causes the layer to use your image rather than [creating] a separate backing store." However, the meaning of "use your image" is still vague. Profiling an application using Instruments often reveals calls to CA::Render::copy_image, even when the Core Animation Instrument has indicated that none of the images have been copied. One reason that Core Animation will require a copy of an image is improper byte alignment.

<sup>3</sup> As of iOS 7, Apple does not make their hardware JPEG decoder available for third-party applications to use. As a result, only a slower, software decoder is used for this step.

The Solution

Fast Image Cache minimizes (or avoids entirely) much of the work described above using a variety of techniques:

Mapped Memory

At the heart of how Fast Image Cache works are image tables. Image tables are similar to sprite sheets, often used in 2D gaming. An image table packs together images of the same dimensions into a single file. This file is opened once and is left open for reading and writing for as long as an application remains in memory.

Image tables use the mmap system call to directly map file data into memory. No memcpy occurs. This system call merely creates a mapping between data on disk and a region of memory.

When a request is made to the image cache to return a specific image, the image table finds (in constant time) the location of the desired image data in the file it maintains. That region of file data is mapped into memory, and a new CGImageRef whose backing store is the mapped file data is created.

When the returned CGImageRef (wrapped into a [UIImage](http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CC0QFjAA&url=http%3A%2F%2Fdeveloper.apple.com%2Flibrary%2Fios%2Fdocumentation%2Fuikit%2Freference%2FUIImage_Class%2F&ei=lG9XUtTdJIm9iwKDq4CACA&usg=

View on GitHub
GitHub Stars8.1k
CategoryDevelopment
Updated2h ago
Forks927

Languages

Objective-C

Security Score

95/100

Audited on Mar 30, 2026

No findings