performance/io-cache: change data structure used to store page-cache.

- io-cache uses rbtree based hash tables to store page-cache instead of lists.

Signed-off-by: Anand V. Avati <avati@dev.gluster.com>

BUG: 335 (Io-cache optimization)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=335
This commit is contained in:
Raghavendra G 2009-10-26 03:01:33 +00:00 committed by Anand V. Avati
parent 78d281d602
commit 3809bb1bbd
5 changed files with 90 additions and 69 deletions

View File

@ -9,6 +9,6 @@ io_cache_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la
noinst_HEADERS = io-cache.h
AM_CFLAGS = -fPIC -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -Wall -D$(GF_HOST_OS) \
-I$(top_srcdir)/libglusterfs/src -shared -nostartfiles $(GF_CFLAGS)
-I$(top_srcdir)/libglusterfs/src -I$(CONTRIBDIR)/rbtree -shared -nostartfiles $(GF_CFLAGS)
CLEANFILES =

View File

@ -80,7 +80,7 @@ ioc_inode_need_revalidate (ioc_inode_t *ioc_inode)
ret = gettimeofday (&tv, NULL);
if (time_elapsed (&tv, &ioc_inode->tv) >= table->cache_timeout)
if (time_elapsed (&tv, &ioc_inode->cache.tv) >= table->cache_timeout)
need_revalidate = 1;
return need_revalidate;
@ -100,7 +100,8 @@ __ioc_inode_flush (ioc_inode_t *ioc_inode)
int32_t destroy_size = 0;
int32_t ret = 0;
list_for_each_entry_safe (curr, next, &ioc_inode->pages, pages) {
list_for_each_entry_safe (curr, next, &ioc_inode->cache.page_lru,
page_lru) {
ret = ioc_page_destroy (curr);
if (ret != -1)
@ -185,7 +186,7 @@ ioc_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
/* update the time-stamp of revalidation */
ioc_inode_lock (ioc_inode);
{
gettimeofday (&ioc_inode->tv, NULL);
gettimeofday (&ioc_inode->cache.tv, NULL);
}
ioc_inode_unlock (ioc_inode);
@ -271,7 +272,7 @@ ioc_cache_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
{
destroy_size = __ioc_inode_flush (ioc_inode);
if (op_ret >= 0)
ioc_inode->mtime = stbuf->st_mtime;
ioc_inode->cache.mtime = stbuf->st_mtime;
}
ioc_inode_unlock (ioc_inode);
local_stbuf = NULL;
@ -290,7 +291,7 @@ ioc_cache_validate_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
ioc_inode_lock (ioc_inode);
{
gettimeofday (&ioc_inode->tv, NULL);
gettimeofday (&ioc_inode->cache.tv, NULL);
}
ioc_inode_unlock (ioc_inode);
@ -1117,7 +1118,7 @@ ioc_lk (call_frame_t *frame, xlator_t *this, fd_t *fd, int32_t cmd,
ioc_inode_lock (ioc_inode);
{
gettimeofday (&ioc_inode->tv, NULL);
gettimeofday (&ioc_inode->cache.tv, NULL);
}
ioc_inode_unlock (ioc_inode);

View File

@ -34,11 +34,14 @@
#include "xlator.h"
#include "common-utils.h"
#include "call-stub.h"
#include "rbthash.h"
#include "hashfn.h"
#include <sys/time.h>
#include <fnmatch.h>
#define IOC_PAGE_SIZE (1024 * 128) /* 128KB */
#define IOC_CACHE_SIZE (32 * 1024 * 1024)
#define IOC_PAGE_TABLE_BUCKET_COUNT 4096
struct ioc_table;
struct ioc_local;
@ -110,7 +113,6 @@ struct ioc_local {
*
*/
struct ioc_page {
struct list_head pages;
struct list_head page_lru;
struct ioc_inode *inode; /* inode this page belongs to */
struct ioc_priority *priority;
@ -125,28 +127,32 @@ struct ioc_page {
pthread_mutex_t page_lock;
};
struct ioc_cache {
rbthash_table_t *page_table;
struct list_head page_lru;
time_t mtime; /*
* mtime of the server file when last
* cached
*/
struct timeval tv; /*
* time-stamp at last re-validate
*/
};
struct ioc_inode {
struct ioc_table *table;
struct list_head pages; /* list of pages of this inode */
struct list_head inode_list; /*
* list of inodes, maintained by io-cache
* translator
*/
struct list_head inode_lru;
struct list_head page_lru;
struct ioc_waitq *waitq;
pthread_mutex_t inode_lock;
uint32_t weight; /*
* weight of the inode, increases on each
* read
*/
time_t mtime; /*
* mtime of the server file when last
* cached
*/
struct timeval tv; /*
* time-stamp at last re-validate
*/
struct ioc_table *table;
struct ioc_cache cache;
struct list_head inode_list; /*
* list of inodes, maintained by
* io-cache translator
*/
struct list_head inode_lru;
struct ioc_waitq *waitq;
pthread_mutex_t inode_lock;
uint32_t weight; /*
* weight of the inode, increases
* on each read
*/
};
struct ioc_table {

View File

@ -25,6 +25,19 @@
#include "io-cache.h"
inline uint32_t
ioc_hashfn (void *data, int len)
{
uint32_t hash = 0;
while (len > 0) {
hash ^= *(uint32_t *)data;
data += sizeof (uint32_t);
len -= sizeof (uint32_t);
}
return hash;
}
/*
* str_to_ptr - convert a string to pointer
* @string: string
@ -163,8 +176,15 @@ ioc_inode_update (ioc_table_t *table, inode_t *inode, uint32_t weight)
ioc_inode->table = table;
/* initialize the list for pages */
INIT_LIST_HEAD (&ioc_inode->pages);
INIT_LIST_HEAD (&ioc_inode->page_lru);
ioc_inode->cache.page_table = rbthash_table_init (IOC_PAGE_TABLE_BUCKET_COUNT,
ioc_hashfn, free);
if (ioc_inode->cache.page_table == NULL) {
FREE (ioc_inode);
ioc_inode = NULL;
goto out;
}
INIT_LIST_HEAD (&ioc_inode->cache.page_lru);
ioc_table_lock (table);

View File

@ -30,35 +30,28 @@
#include <assert.h>
#include <sys/time.h>
char
ioc_empty (struct ioc_cache *cache)
{
return list_empty (&cache->page_lru);
}
ioc_page_t *
ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
{
int8_t found = 0;
ioc_page_t *page = NULL;
ioc_table_t *table = NULL;
off_t rounded_offset = 0;
ioc_page_t *page = NULL;
ioc_table_t *table = NULL;
off_t rounded_offset = 0;
table = ioc_inode->table;
rounded_offset = floor (offset, table->page_size);
if (list_empty (&ioc_inode->pages)) {
return NULL;
}
page = rbthash_get (ioc_inode->cache.page_table, &rounded_offset,
sizeof (rounded_offset));
list_for_each_entry (page, &ioc_inode->pages, pages) {
if (page->offset == rounded_offset) {
found = 1;
break;
}
}
/* was previously returning ioc_inode itself..,
* 1st of its type and found one more downstairs :O */
if (!found){
page = NULL;
} else {
if (page != NULL) {
/* push the page to the end of the lru list */
list_move_tail (&page->page_lru, &ioc_inode->page_lru);
list_move_tail (&page->page_lru, &ioc_inode->cache.page_lru);
}
return page;
@ -74,7 +67,7 @@ ioc_page_get (ioc_inode_t *ioc_inode, off_t offset)
int64_t
ioc_page_destroy (ioc_page_t *page)
{
int64_t page_size = 0;
int64_t page_size = 0;
page_size = iobref_size (page->iobref);
@ -82,8 +75,8 @@ ioc_page_destroy (ioc_page_t *page)
/* frames waiting on this page, do not destroy this page */
page_size = -1;
} else {
list_del (&page->pages);
rbthash_remove (page->inode->cache.page_table, &page->offset,
sizeof (page->offset));
list_del (&page->page_lru);
gf_log (page->inode->table->xl->name, GF_LOG_TRACE,
@ -98,7 +91,6 @@ ioc_page_destroy (ioc_page_t *page)
}
page->inode = NULL;
}
if (page_size != -1) {
@ -140,8 +132,8 @@ ioc_prune (ioc_table_t *table)
/* { */
list_for_each_entry_safe (page, next,
&curr->page_lru,
page_lru) {
&curr->cache.page_lru,
page_lru) {
/* done with all pages, and not
* reached equilibrium yet??
* continue with next inode in
@ -163,7 +155,7 @@ ioc_prune (ioc_table_t *table)
if (size_pruned >= size_to_prune)
break;
} /* list_for_each_entry_safe(page...) */
if (list_empty (&curr->pages)) {
if (ioc_empty (&curr->cache)) {
list_del_init (&curr->inode_lru);
}
@ -194,10 +186,10 @@ ioc_prune (ioc_table_t *table)
ioc_page_t *
ioc_page_create (ioc_inode_t *ioc_inode, off_t offset)
{
ioc_table_t *table = NULL;
ioc_page_t *page = NULL;
off_t rounded_offset = 0;
ioc_page_t *newpage = NULL;
ioc_table_t *table = NULL;
ioc_page_t *page = NULL;
off_t rounded_offset = 0;
ioc_page_t *newpage = NULL;
table = ioc_inode->table;
rounded_offset = floor (offset, table->page_size);
@ -219,8 +211,10 @@ ioc_page_create (ioc_inode_t *ioc_inode, off_t offset)
newpage->inode = ioc_inode;
pthread_mutex_init (&newpage->page_lock, NULL);
list_add_tail (&newpage->page_lru, &ioc_inode->page_lru);
list_add_tail (&newpage->pages, &ioc_inode->pages);
rbthash_insert (ioc_inode->cache.page_table, newpage, &rounded_offset,
sizeof (rounded_offset));
list_add_tail (&newpage->page_lru, &ioc_inode->cache.page_lru);
page = newpage;
@ -293,12 +287,12 @@ ioc_cache_still_valid (ioc_inode_t *ioc_inode, struct stat *stbuf)
int8_t cache_still_valid = 1;
#if 0
if (!stbuf || (stbuf->st_mtime != ioc_inode->mtime) ||
if (!stbuf || (stbuf->st_mtime != ioc_inode->cache.mtime) ||
(stbuf->st_mtim.tv_nsec != ioc_inode->stbuf.st_mtim.tv_nsec))
cache_still_valid = 0;
#else
if (!stbuf || (stbuf->st_mtime != ioc_inode->mtime))
if (!stbuf || (stbuf->st_mtime != ioc_inode->cache.mtime))
cache_still_valid = 0;
#endif
@ -369,9 +363,9 @@ ioc_fault_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
}
if (op_ret >= 0)
ioc_inode->mtime = stbuf->st_mtime;
ioc_inode->cache.mtime = stbuf->st_mtime;
gettimeofday (&ioc_inode->tv, NULL);
gettimeofday (&ioc_inode->cache.tv, NULL);
if (op_ret < 0) {
/* error, readv returned -1 */
@ -571,7 +565,7 @@ ioc_frame_fill (ioc_page_t *page, call_frame_t *frame, off_t offset,
frame, offset, size, page->size, local->wait_count);
/* immediately move this page to the end of the page_lru list */
list_move_tail (&page->page_lru, &ioc_inode->page_lru);
list_move_tail (&page->page_lru, &ioc_inode->cache.page_lru);
/* fill local->pending_size bytes from local->pending_offset */
if (local->op_ret != -1 && page->size) {
if (offset > page->offset)