QuantumCache 是一个线程安全的、高性能的最近最少使用 (LRU) 缓存实现,使用 Swift 编写。它被设计为快速且高效,支持各种类型的缓存内容,包括复杂类型和带有泛型关联值的枚举。
CachableContent
协议的类型。虽然 NSCache
是 Swift 中强大且方便的缓存解决方案,但 QuantumCache
提供了几个优点
支持值类型: 与主要处理引用类型的 NSCache
不同,QuantumCache
除了引用类型外,还可以高效地缓存值类型(例如,结构体、枚举)。这使其用途更广泛,更适用于更广泛的用例。
无需 NSObject 子类: 与 NSCache
要求缓存对象必须是 NSObject
的子类不同,QuantumCache
没有这样的限制。这允许您使用纯 Swift 结构体、枚举和类。使用纯 Swift 类型可能更有效率,并且更符合 Swift 的值语义,避免了与 NSObject
子类化相关的开销。
确定性的淘汰策略: QuantumCache
遵循严格的最近最少使用 (LRU) 淘汰策略。这种确定性的方法确保当缓存超出其容量时,最旧的未使用项目始终首先被移除。另一方面,NSCache
可能不会严格遵守 LRU,因为其淘汰策略是基于内部启发式和系统内存压力的。
线程安全: QuantumCache
使用 NSRecursiveLock
来确保跨多个线程的线程安全操作。虽然 NSCache
也是线程安全的,但 QuantumCache
的锁定机制是透明的,旨在处理更复杂的访问模式,例如嵌套锁定场景。
细粒度控制: QuantumCache
提供了对缓存行为更精细的控制,允许开发者自定义淘汰过程并根据特定需求定制缓存。这种程度的控制在 NSCache
中是无法直接获得的。
可预测的性能: 凭借插入和访问操作的常数时间复杂度,QuantumCache
提供了可预测且一致的性能,这对于缓存性能是瓶颈的应用程序至关重要。
自定义: CachableContent
协议允许开发者定义带有任何关联数据的自定义可缓存类型。这种程度的自定义在 NSCache
中不如直接。
您可以使用 Swift Package Manager 将 QuantumCache
添加到您的 Swift 项目中。将以下依赖项添加到您的 Package.swift
dependencies: [
.package(url: "https://github.com/sleepwalkerfx/QuantumCache.git", from: "1.0.0")
]
这是一个关于如何使用 QuantumCache
的基本示例
import QuantumCache
struct MyContent: CachableContent {
var id: Int
var content: String
}
let cache = QuantumCache<MyContent>(capacity: 3)
let item1 = MyContent(id: 1, content: "Hello")
let item2 = MyContent(id: 2, content: "World")
cache.put(item1)
cache.put(item2)
if let retrievedItem = cache.get(1) {
print(retrievedItem.content) // Output: Hello
}
QuantumCache 已经过各种复杂类型的全面测试,以确保其稳健性和正确性。
QuantumCache 已经过测试,以确保它可以正确处理自定义类,在这些类中,实例是被引用而不是被复制的。这包括
以下是如何定义和使用带有自定义类的 QuantumCache
// Define a custom class conforming to `CachableContent`
class ReferenceContent: CachableContent {
var id: Int
var content: String
init(id: Int, content: String) {
self.id = id
self.content = content
}
}
// Create a QuantumCache instance with a specified capacity
let cache = QuantumCache<ReferenceContent>(capacity: 3)
// Create instances of ReferenceContent
let firstItem = ReferenceContent(id: 1, content: "First Item")
let secondItem = ReferenceContent(id: 2, content: "Second Item")
let thirdItem = ReferenceContent(id: 3, content: "Third Item")
// Put items into the cache
cache.put(firstItem)
cache.put(secondItem)
cache.put(thirdItem)
// Access items from the cache and modify them
if let cachedFirstItem = cache.get(1) {
print("Retrieved cached first item: \(cachedFirstItem.content)")
// Modify the content of the retrieved item
cachedFirstItem.content = "Updated First Item"
}
// Insert more items to trigger eviction
let fourthItem = ReferenceContent(id: 4, content: "Fourth Item")
cache.put(fourthItem)
// Access previously cached items
if let updatedFirstItem = cache.get(1) {
print("Retrieved updated first item: \(updatedFirstItem.content)")
}
if let cachedSecondItem = cache.get(2) {
print("Retrieved cached second item: \(cachedSecondItem.content)")
} else {
print("Second item has been evicted")
}
if let cachedThirdItem = cache.get(3) {
print("Retrieved cached third item: \(cachedThirdItem.content)")
} else {
print("Third item has been evicted")
}
if let cachedFourthItem = cache.get(4) {
print("Retrieved cached fourth item: \(cachedFourthItem.content)")
}
QuantumCache 支持带有关联值的枚举,并已针对以下方面进行了测试
以下是如何定义和使用带有关联值的枚举的 QuantumCache
// Define the enum with associated values conforming to `CachableContent` and `Hashable`
enum MockEnumContent: CachableContent, Hashable {
case text(id: Int, content: String)
case data(id: Int, content: Data)
// CachableContent Protocol Requirements
var id: Int {
switch self {
case .text(let id, _):
return id
case .data(let id, _):
return id
}
}
var content: Any {
switch self {
case .text(_, let content):
return content
case .data(_, let content):
return content
}
}
}
// Create a QuantumCache instance with a specified capacity
let cache = QuantumCache<MockEnumContent>(capacity: 5)
// Put items into the cache
let textItem = MockEnumContent.text(id: 1, content: "Hello, World!")
cache.put(textItem)
let dataItem = MockEnumContent.data(id: 2, content: Data([0x00, 0x01, 0x02]))
cache.put(dataItem)
// Access items from the cache
if let cachedTextItem = cache.get(1) {
print("Retrieved cached text: \(cachedTextItem)")
}
if let cachedDataItem = cache.get(2) {
print("Retrieved cached data: \(cachedDataItem)")
}
// Example output:
// Retrieved cached text: text(id: 1, content: "Hello, World!")
// Retrieved cached data: data(id: 2, content: 3 bytes)
QuantumCache 支持带有泛型关联值的枚举。它已针对以下方面进行了测试
以下是如何定义和使用带有泛型关联值的枚举的 QuantumCache
// Define the enum with generic associated values conforming to `CachableContent`
enum GenericEnumContent<T>: CachableContent {
case integer(id: Int, value: Int)
case string(id: Int, value: String)
case generic(id: Int, value: T)
// CachableContent Protocol Requirements
var id: Int {
switch self {
case .integer(let id, _):
return id
case .string(let id, _):
return id
case .generic(let id, _):
return id
}
}
var content: Any {
switch self {
case .integer(_, let value):
return value
case .string(_, let value):
return value
case .generic(_, let value):
return value
}
}
}
// Create a QuantumCache instance with a custom type for the associated type of .generic case
let cache = QuantumCache<GenericEnumContent<Data>>(capacity: 5)
// Put items into the cache
let intItem: GenericEnumContent<Data> = GenericEnumContent.integer(id: 1, value: 42)
cache.put(intItem)
let stringItem: GenericEnumContent<Data> = GenericEnumContent.string(id: 2, value: "Hello, Swift!")
cache.put(stringItem)
let genericItem = GenericEnumContent.generic(id: 3, value: Data([0x00, 0x01]))
cache.put(genericItem)
// Access items from the cache
if let cachedIntItem = cache.get(1) {
print("Retrieved cached integer: \(cachedIntItem)")
}
if let cachedStringItem = cache.get(2) {
print("Retrieved cached string: \(cachedStringItem)")
}
if let cachedGenericItem = cache.get(3) {
print("Retrieved cached generic value: \(cachedGenericItem)")
}
// Example output:
// Retrieved cached integer: integer(id: 1, value: 42)
// Retrieved cached string: string(id: 2, value: "Hello, Swift!")
// Retrieved cached generic value: generic(id: 3, value: 2 bytes)
要运行测试,请使用以下命令
swift test
欢迎贡献!如果您有建议、改进或错误修复,请打开一个 issue 或 pull request。
本项目根据 MIT 许可证获得许可 - 有关详细信息,请参阅 LICENSE 文件。
有关实现和用法的更多详细信息,请查看存储库中的代码和测试。