天天看點

/LGC設計模式/The Design of a cache buffer

The Design of a cache buffer 作者: 劉鵬 日期: 2008-11-26 在 GUI 系統中對資源進行高效管理是非常重要的問題。文本以圖檔管理為例,提出一個基于哈希表的 cache buffer。

背景

GUI 系統中往往會用到很多資源,如圖檔。若每次使用圖檔時都從磁盤裝入記憶體, 由于磁盤讀取速度很慢,效率會很低下。

我們可以設計一個 cache buffer,将讀進來的圖檔緩存到 cache 裡,當程式使 用圖檔時先去 cache 裡找,若 cache 沒有,再去磁盤讀取。這跟 Linux Kernel 針對磁盤塊的 cache buffer 是一樣的道理。

設計一個 cache ,需要考慮如下問題:

  • cache 采用什麼樣的資料結構;
  • 如何在 cache 中迅速找到需要的圖檔;
  • cache 滿了之後如何處理,是否采用對換政策;若是,采用什麼樣的換出算 法。

針對上述問題,本文提出一個采用哈希表加雙向連結清單的 cache 設計政策。為了 簡化問題,暫時沒有考慮對換問題。

Buffer Cache 總體結構

使用哈希表組織和管理所有的資料,首先用哈希函數計算字元串在哪個連結清單,然 後根據 key 值順序比較連結清單元素,查找對應的字元。

哈希隊列結構示意圖如下所示:

/LGC設計模式/The Design of a cache buffer
哈希隊列示意圖

哈希連結清單結點如下圖所示:

/LGC設計模式/The Design of a cache buffer
連結清單結點結構圖

資料結構

資料結構代碼如下所示:

typedef struct _RESCACHENODE {



    unsigned char key[LENTH];

    IMAGE* *image;

    int ref_count;

    int is_preload;



    _RESCACHNODE* pre;

    _RESCACHNODE* next;



} RESCACHENODE;





#define NR_HASH_ENTRIES     20



typedef struct  _RESCACHE {



    RECACHENODE* res_hash_table [NR_HASH_ENTRIES];



} RESCACHE;



RESCACHE res_cache = {0};



      

哈希函數

哈希函數的選擇決定了查詢速度,哈希函數需要滿足以下要求:

  • 計算非常快;
  • 沖突均勻化。

下面是一個基于字元求和的哈希函數:

static int hash_string (const char* key)

{

    int hval;

    const char* ptr = (const char*) key;

    char c;

    int i;



    hval = 0;

    for (i = 1; (c = *ptr++); i++)

        hval += c * i;



    return (hval % NR_HASH_ENTRIES);

}



      

關于字元串哈希函數可見參考資源裡的“字元串哈希函數研究”。

Buffer Cache 程式設計接口

/*

 * Read images files top dir.

 **/

static BOOL set_res_top_dir (void);



/* Init cache: set top dir and initialize lock **/

void init_cache (void);



/*

 * Load the file to IMAGE object , add a new node to the cache and

 * set is_preload to FALSE.

 * If the node already exists, then ref_count ++; Otherwise, load

 * the Bitmap.

 *

 * hdc: dc

 * file: key value

 * Return:  If succeed, return TRUE; Otherwise return FALSE.

 */

BOOL insert_into_cache_from_file (HDC hdc, const char *file);





/*

 * Load the memory data to IMAGE object, create a new node to the cache

 * and set is_preload to FALSE.

 * If the node already exists, then ref_count ++; Otherwise, load the

 * image object.

 *

 * hdc: dc

 * file: key value

 * Return:  If succeed, return TRUE; Otherwise return FALSE.

 **/

BOOL insert_into_cache_from_mem (HDC hdc, const char* key,

        const unsigned char* data, size_t data_size);





/*

 * Find  an IMAGE object in cache with the key value "file".

 *

 * file: key value

 * If found, then return the pointer of the image; Otherwise, return NULL;

 */

IMAGE* retrieve_in_cache (const char *file);



/*

 * Remove the IMAGE object from cache buffer.

 * If ref_count > 1, then refcount --; Otherwise, unload the IMAGE object

 * and detach the node from the cache.

 * If is_preload == TRUE, then do not unload IMAGE object.

 *

 * file: key value

 * image: image object.

 */

void remove_from_cache (const char *file);



      

SeeAlso

  • 字元串哈希函數研究

繼續閱讀