www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式基地

今天主要給大家分享下基于C語言實(shí)現(xiàn)的LRU緩存淘汰算法。

  • 緩存,是一種提高數(shù)據(jù)讀取性能的技術(shù),不論是在硬件,還是軟件設(shè)計(jì)中都會(huì)被廣泛的應(yīng)用。

  • 在軟件設(shè)計(jì)中,緩存的大小總是有限的。當(dāng)緩存被使用完時(shí),就需要對(duì)數(shù)據(jù)進(jìn)行清理。在清理數(shù)據(jù)時(shí),經(jīng)常會(huì)使用到緩存淘汰策略來決定清理哪些不需要的數(shù)據(jù)。

常見的策略有下面三種:

  • 先進(jìn)先出策略FIFO

  • 最少使用策略LFU

  • 最近最少使用策略LRU

一般采用鏈表實(shí)現(xiàn)LRU,基本的思路如下

首先需要在緩存中維護(hù)一個(gè)雙向鏈表,鏈表中的數(shù)據(jù)按照訪問的時(shí)間從新到舊排列。當(dāng)有一個(gè)數(shù)據(jù)被訪問時(shí),我們從鏈表頭開始順序遍歷。

如果該數(shù)據(jù)在此之前已經(jīng)被放入到了緩存中
  • 我們需要將該數(shù)據(jù)的節(jié)點(diǎn)從原位置刪除,然后重新將其放入到鏈表的表頭。

如果該數(shù)據(jù)在這之前沒有被放入緩存中
  • 如果此時(shí)緩存沒有滿,則將此數(shù)據(jù)放入到鏈表的表頭。

  • 如果此時(shí)緩存已滿,則需要先將鏈表尾部的數(shù)據(jù)刪除,之后將該數(shù)據(jù)放入鏈表的表頭。

上述方法在我們需要從緩存中查找數(shù)據(jù)時(shí),都需要遍歷一遍數(shù)據(jù)。因此,這種做法的時(shí)間復(fù)雜度為O(n)。

使用哈希表保證緩存的訪問速度

為了提高上述方法的時(shí)間復(fù)雜度,我們除了需要將數(shù)據(jù)維護(hù)在雙向鏈表中,還需要將數(shù)據(jù)維護(hù)在哈希表中。哈希表的數(shù)據(jù)訪問的時(shí)間復(fù)雜度為O(1)

LRU緩存內(nèi)部數(shù)據(jù)結(jié)構(gòu)
  • LRU緩存包含了一個(gè)雙向鏈表和一個(gè)哈希表

/* 定義LRU緩存 */ typedef struct LRUCacheS{ sem_t cache_lock; int cacheCapacity; /*緩存的容量*/ int lruListSize; /*緩存的雙向鏈表節(jié)點(diǎn)個(gè)數(shù)*/ cacheEntryS **hashMap; /*緩存的哈希表*/ cacheEntryS *lruListHead; /*緩存的雙向鏈表表頭*/ cacheEntryS *lruListTail; /*緩存的雙向鏈表表尾*/ }LRUCacheS;
緩存中的數(shù)據(jù)單元
  • 緩存中的數(shù)據(jù)單元,既是一個(gè)雙向鏈表的節(jié)點(diǎn),也是哈希表中的一個(gè)節(jié)點(diǎn)。

typedef struct cacheEntryS{ char key[KEY_SIZE]; /* 數(shù)據(jù)的key */ char data[VALUE_SIZE]; /* 數(shù)據(jù)的data */ sem_t entry_lock; struct cacheEntryS *hashListPrev; /* 緩存哈希表指針, 指向哈希鏈表的前一個(gè)元素 */ struct cacheEntryS *hashListNext; /* 緩存哈希表指針, 指向哈希鏈表的后一個(gè)元素 */ struct cacheEntryS *lruListPrev; /* 緩存雙向鏈表指針, 指向鏈表的前一個(gè)元素 */ struct cacheEntryS *lruListNext; /* 緩存雙向鏈表指針, 指向鏈表后一個(gè)元素 */ }cacheEntryS;
測(cè)試
int main(int argc, char **argv){ void *LruCache; //創(chuàng)建緩存器 if (0 == LRUCacheCreate(3, &LruCache)) printf("緩存器創(chuàng)建成功,容量為3\n"); //向緩存器中添加數(shù)據(jù) if (0 != LRUCacheSet(LruCache, "key1", "value1")) printf("put (key1, value1) failed!\n"); if (0 != LRUCacheSet(LruCache, "key2", "value2")) printf("put (key2, value2) failed!\n"); if (0 != LRUCacheSet(LruCache, "key3", "value3")) printf("put (key3, value3) failed!\n"); if (0 != LRUCacheSet(LruCache, "key4", "value4")) printf("put (key4, value4) failed!\n"); if (0 != LRUCacheSet(LruCache, "key5", "value5")) printf("put (key5, value5) failed!\n"); //按照順序輸出緩存器當(dāng)前的內(nèi)容 LRUCachePrint(LruCache); //獲取緩存器內(nèi)容 if (NULL == LRUCacheGet(LruCache, "key1")){ printf("key1 所對(duì)應(yīng)的數(shù)據(jù)未被緩存\n");
 } else{ char data[VALUE_SIZE]; strncpy(data, LRUCacheGet(LruCache, "key1"), VALUE_SIZE); printf("key1所對(duì)應(yīng)的數(shù)據(jù)為:%s", data);
 } char value4[VALUE_SIZE]; strncpy(value4, LRUCacheGet(LruCache, "key4"), VALUE_SIZE); printf("key4所對(duì)應(yīng)的數(shù)據(jù):%s", value4);

 LRUCachePrint(LruCache); //銷毀緩存器 if (0 != LRUCacheDestory(LruCache)) printf("destory error");
}


  • 結(jié)果


項(xiàng)目下載

https://github.com/Lighter-z/c_demo

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉