CS, Swift: Implementing an ImageCacher Using LFU(Least Frequently Used )

Insub
2 min readJul 7, 2024

Introduction

Recently, while studying for the Information Processing Engineer exam, I learned about LRU (Least Recently Used) and LFU (Least Frequently Used) caching strategies. To apply this knowledge in practice, I will implement an image cacher. In this article, we will create a simple yet efficient ImageCacher using the LFU caching strategy.

Previous Post

Exaplanation

LFU caching is a strategy that retains the most frequently used data in the cache and removes data that is less frequently used. This way, infrequently used data is automatically removed, and frequently used data remains in the cache. Below is an example of implementing a thread-safe LFU cache using Swift’s actor.

actor ImageCacher {    

static let shared = ImageCacher()
private init() { }

private var cachedImages: [String: UIImage] = [:]
private var accessFrequency: [String: Int] = [:]
private let cacheLimit = 100

func cachedImage(for key: String) -> UIImage? {
if let image = cachedImages[key] {
updateAccessFrequency(for: key)
return image
}
return nil
}

func cacheImage(_ image: UIImage, for key: String) {
if cachedImages.keys.count >= cacheLimit {
removeLeastFrequentlyUsedImage()
}
cachedImages[key] = image
updateAccessFrequency(for: key, initial: true)
}

private func updateAccessFrequency(for key: String, initial: Bool = false) {
if initial {
accessFrequency[key] = 1
} else {
accessFrequency[key, default: 0] += 1
}
}

private func removeLeastFrequentlyUsedImage() {
if let leastFrequentlyUsedKey = accessFrequency.min(by: { $0.value < $1.value })?.key {
cachedImages.removeValue(forKey: leastFrequentlyUsedKey)
accessFrequency.removeValue(forKey: leastFrequentlyUsedKey)
}
}
}

Code Explanation

Cache Structure:

  • cachedImages: A dictionary to store image data.
  • accessFrequency: A dictionary to store the access frequency of each image key.
  • cacheLimit: The maximum number of images to store in the cache.

cachedImage(for:):

  • Returns the image corresponding to the given key.
  • If the image exists, updates the access frequency.

cacheImage(_:for:):

  • Stores the given image data with the specified key in the cache.
  • If the cache size exceeds the limit, removes the least frequently used image.
  • Updates the access frequency.

updateAccessFrequency(for:initial:):

  • Updates the access frequency of the accessed key.
  • Sets the access frequency to 1 when initially storing.

removeLeastFrequentlyUsedImage():

  • Finds and removes the image with the lowest access frequency.

Conclusion

We have implemented an image cacher using the LFU (Least Frequently Used) page replacement algorithm. This method efficiently manages memory usage by automatically removing infrequently used data. Using Swift’s actor ensures thread safety. LFU retains frequently used data in the cache and removes data with lower access frequencies, effectively increasing cache hit rates.

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response