NSCache
28 Aug 2018NSCache
는 Cocoa에서 사용할 수 있는 캐싱을 위한 클래스입니다.NSCache
는NSDictionary
처럼key-value
형태로 되어 있습니다.NSCache
는 메모리가 충분할 때는 주어진 모든 데이터를 캐싱합니다. 반면, 가용 메모리가 적을 때는 다른 앱을 위해 캐싱된 데이터를 자동으로 버립니다.
이렇게 버려진 데이터는 필요할 때 다시 캐싱해야 합니다. 바꿔말하면, 캐싱된 데이터가 없어도 앱이 적절히 동작(i.e. 다시 데이터 캐싱)할 수 있도록 구조를 설계해야 합니다.
NSCache Property
- countLimit -
NSCache
는 캐싱하는 데이터의 개수를 제한할 수 있습니다. 만약 countLimit이 10으로 설정되어 있는데, 11개의 데이터를NSCache
에 넣게 되면 1개는 자동으로 버립니다. - totalCostLimit -
NSCache
는 객체를 추가할 때 cost(Int
)를 함께 설정할 수 있습니다. 이 때,totalCostLimit
은 cost들의 총합의 최댓값입니다. 즉,NSCache
에 추가된 데이터들의 cost가totalCostLimit
에 도달하거나 넘게 되면NSCache
는 데이터를 버립니다.
let cache: NSCache<NSString, UIImage> = NSCache()
cache.countLimit = 허용하는 key의 개수
cache.totalCostLimit = cost 합계의 최댓값
- evictsObjectsWithDiscardedContent -
NSCache
는 시스템에서 메모리를 너무 많이 사용하지 않도록 디자인되어 있습니다. 그래서 캐싱된 데이터를 자동으로 지우는 다양한 정책을 사용하고 있고, 캐싱된 데이터가 너무 많은 메모리를 사용하면 시스템은 캐싱된 데이터를 삭제합니다.
The NSCache class incorporates various auto-eviction policies, which ensure that a cache doesn’t use too much of the system’s memory. If memory is needed by other applications, these policies remove some items from the cache, minimizing its memory footprint.
이 부분은 좀 더 알아보고 구체적인 서술을 하고자 합니다.
NSCache 구현
NSCache가 어떻게 구현되어 있는지는 애플에서 공개한 Foundation - NSCache를 살펴보면 파악할 수 있습니다.
NSCache
는 기본적으로 연결리스트로 데이터를 캐싱합니다. 연결리스트로 데이터를 캐싱하는 이유에 대해서 명확히 서술되어 있지는 않지만, 캐시는 중간에 있는 데이터 추가, 삭제가 빈번하기 때문에 이를 효율적으로 하기 위해(배열로 해당 작업을 수행시 데이터를 앞으로 당기거나, 뒤로 데이터를 모두 밀어야 하는 작업이 추가적으로 발생합니다.) 연결리스트로 구현된 것이라고 생각해볼 수 있습니다.
한편, NSCache
는 별도로 Dictionary를 두어 데이터의 접근도 O(1)에 수행할 수 있도록 제공하고 있습니다.
NSCache 데이터 교체 알고리즘
일반적으로 캐시는 캐싱된 데이터를 버리는 방식에 있어서 용도에 따라 서로 다른 페이지 교체 알고리즘을 사용합니다. 흔히, FIFO, LRU, LFU 등의 메모리 페이지 교체 알고리즘들이 사용되는데, NSCache
는 이와는 조금 다른 방식으로 데이터를 취하고 버립니다.
NSCache
에는 개별 데이터마다 cost 값을 부여할 수 있습니다. NSCache
는 이 cost값의 오름차순으로 데이터를 추가할 때 정렬을 수행합니다. 실제 코드를 살펴보면 다음과 같습니다.
위의 코드를 보면 NSCache
에 데이터를 추가할 때, cost값을 기준으로 정렬을 수행하는 것을 확인할 수 있습니다. 또한 삭제의 경우, 새로운 값을 추가할 때, 값이 작은 데이터들을 순차적으로 제거하여 totalCostLimit을 유지하는 방식을 활용하고 있습니다.
데이터 추가 삭제를 cost 중심으로 설명하였는데, count를 통해서도 해당 작업을 수행합니다. 이 부분은 여기서 따로 서술하지 않습니다.(cost를 중심으로 데이터를 추가 삭제하는 것과 크게 다르지 않습니다.)
전체 코드는 Foundation - NSCache에서 확인하실 수 있으니, 이를 참고하시면 좋을 것 같습니다.