メモリキャッシュとディスクキャッシュ:YYCache全体的な構造は、2つの部分に分かれています。
しかし、小容量のキャッシュメモリは、高速アクセスを提供し、大容量のディスクキャッシュは低いが、永続的なストレージを提供します。
なぜ我々はキャッシュが必要なのでしょうか?
メモリ読み取りおよびディスクの書き込み速度よりもはるかに大きい速度を書き込み、メモリに頻繁に使用されるデータの存在は、再度、場合それによって性能を向上させる、メモリから直接読み取るために使用されます。
キャッシュメモリの設計のいくつかのポイント
1.キャッシュアルゴリズム:シーンが高いキャッシュヒット率を作るために、に基づいて、適切なキャッシュアルゴリズムを選択します。一般的なキャッシュアルゴリズム:ようにLRU(最低使用)、LRU-2(LRUと同様に、参入障壁が2倍になり)、LFU(最も頻繁に使用される)、FIFO(First In First Out)メモリと。
2.リードとは、性能を書く:同じ場合、データを格納し、データの読み出し速度を。
3.スレッドの安全性:読み取り書き込みキャッシュは、複数のスレッドでは考慮されている可能性があります。
LRUアルゴリズム
LRUアルゴリズムでは、名前が示唆するように、最も最近使用されたデータを除去する(最も最近使用しました)。
1.データ・キャッシュ・ミスは、この時点でバッファがフルタイムでない場合。フロントに直接新しいデータ(アレイの基本構造を決定し、のみリンクされたリスト、複雑さはO(N)であるアレイヘッド挿入時間を使用することができない、リンクリスト挿入時間複雑さのヘッドはO(1)) 。
2.アクセスデータのキャッシュヒット、リストの一番上にデータアクセス。
3.アクセスデータミスデータを、しかし、キャッシュがいっぱいになっているこの時間は、あなたはリストの最後を排除して、別れ、新しいデータに最初にする必要があります。
YYModelメモリキャッシュの設計
YYModelメモリキャッシュはの一部であるYYMemoryCache
クラス。で使用されるYYMemoryCache LRUキャッシュアルゴリズムのHashMap + デュアルリンクリスト。ハッシュマップは、読み取り操作ので、O(1)、確実にするために使用される読み出し速度。二重リンクリストの削除と挿入操作はO(1)は、良好な高速書き込み動作を確実にするためです。
なぜ単独リストをリンクされていませんか?
ノードが事前トラバースを再読み込みする必要がありながら1単鎖削除操作は、前のノードを読み取るために必要となります。
2.いくつかはそれが適切ではないと言うであろう、次のノードデータは、その後、現在のノード(現在のノードのデータを削除)を削除ように、次のノードを削除し、現在のノードに割り当てることができます。あなたが最後のものを削除する場合はまず第一に、それはデータ操作のコピーが、再び、このアプローチではありません。除去機構のキャッシングアルゴリズムは、ちょうど最後のものを削除しています。
YYModel構造
ハッシュマップの役割はすぐに読むことです。二重リンクリストは除去メカニズムを達成するために、秩序を維持するために使用されます。
LRU機構対応する擬似コード:
1.データ・キャッシュ・ミスは、この時点でバッファがフルタイムでない場合。フロントに直接新しいデータ
if (!hashmap[@"key"]) {
Node *node = [[Node alloc] init];
node.data = data;
hashmap[@"key"] = node;
if (self.linkedList.head) {
node.next = self.linkedList.head;
node.prev = nil;
self.linkedList.head.prev = node;
self.linkedList.head = node;
} else {
node.prev = nil;
node.next = nil;
self.linkedList.head = node;
self.linkedList.tail = node;
}
}复制代码
2.アクセスデータのキャッシュヒット、リストの一番上にデータアクセス。
if (hashmap[@"key"]) {
Node *node = hashmap[@"key"];
if (node == self.linkedList.head) {
return;
} else if (node == self.linkedList.tail) {
node.prev.next = nil;
self.linkedList.tail = node.prev;
node.next = self.linkedList.head;
self.linkedList.head.prev = node;
self.linkedList.head = node;
} else {
node.prev.next = node.next;
node.next.prev = node.prev;
node.next = self.linkedList.head;
self.linkedList.head.prev = node;
self.linkedList.head = node;
}
}复制代码
3.アクセスデータミスデータを、しかし、キャッシュがいっぱいになっているこの時間は、あなたはリストの最後を排除して、別れ、新しいデータに最初にする必要があります。
Node *node = self.linkedList.tail;
node.prev.next = nil;
self.linkedList.tail = node.prev;
[hashmap removeObjectForKey:@"key"];
free(node);复制代码
スレッドセーフ
スレッドセーフロック保証を読み書き1
2.非同期スレッドでリリースノードを削除し、パフォーマンスを向上させます。
if (_lru->_totalCost > _costLimit) {
dispatch_async(_queue, ^{
[self trimToCost:_costLimit];
});
}复制代码
ます。https://juejin.im/post/5d08efe46fb9a07ee30e1bebで再現