Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache statistics #52

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions block_cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ struct block_cache_private {
pthread_cond_t worker_work; // there is new work for worker thread(s)
pthread_cond_t worker_exit; // a worker thread has exited
pthread_cond_t write_complete; // a write has completed
struct block_cache_usage_stats *usage_stats; /* Pointer to array of usage stats (for each block) */
};

/* Callback info */
Expand Down Expand Up @@ -198,6 +199,8 @@ static uint64_t block_cache_get_time_millis(void);
static int block_cache_read_data(struct block_cache_private *priv, struct cache_entry *entry, void *dest, u_int off, u_int len);
static int block_cache_write_data(struct block_cache_private *priv, struct cache_entry *entry, const void *src, u_int off,
u_int len);
static void block_cache_update_read_stats(struct block_cache_private *priv, s3b_block_t block_num);
static void block_cache_update_write_stats(struct block_cache_private *priv, s3b_block_t block_num);

/* Invariants checking */
#ifndef NDEBUG
Expand Down Expand Up @@ -551,6 +554,9 @@ block_cache_do_read(struct block_cache_private *const priv, s3b_block_t block_nu
assert(len <= priv->config->block_size);
assert(off + len <= priv->config->block_size);

/* update read usage stats here, so we eventually count read hits too */
block_cache_update_read_stats(priv, block_num);

again:
/* Check to see if a cache entry already exists */
if ((entry = s3b_hash_get(priv->hashtable, block_num)) != NULL) {
Expand Down Expand Up @@ -746,6 +752,9 @@ block_cache_write(struct block_cache_private *const priv, s3b_block_t block_num,
/* Grab lock */
pthread_mutex_lock(&priv->mutex);

/* update write usage stats here, so we eventually count write hits too */
block_cache_update_write_stats(priv, block_num);

again:
/* Sanity check */
S3BCACHE_CHECK_INVARIANTS(priv);
Expand Down Expand Up @@ -1338,6 +1347,31 @@ block_cache_dirty_callback(void *arg, void *value)
}
}


static void block_cache_update_read_stats(struct block_cache_private *priv, s3b_block_t block_num)
{
uint64_t timestamp = block_cache_get_time_millis();
if (priv->stats.usage_stats[block_num].num_reads > 0) {
uint64_t old_timestamp = priv->stats.usage_stats[block_num].last_read_timestamp;
priv->stats.usage_stats[block_num].cumulative_reads_time += (timestamp - old_timestamp);
}
priv->stats.usage_stats[block_num].last_read_timestamp = timestamp;
priv->stats.usage_stats[block_num].num_reads++;
}

static void block_cache_update_write_stats(struct block_cache_private *priv, s3b_block_t block_num)
{
uint64_t timestamp = block_cache_get_time_millis();
if (priv->stats.usage_stats[block_num].num_writes > 0) {
uint64_t old_timestamp = priv->stats.usage_stats[block_num].last_write_timestamp;
priv->stats.usage_stats[block_num].cumulative_writes_time += (timestamp - old_timestamp);
}
priv->stats.usage_stats[block_num].last_write_timestamp = timestamp;
priv->stats.usage_stats[block_num].num_writes++;
}



#ifndef NDEBUG

/* Accounting structure */
Expand Down
13 changes: 13 additions & 0 deletions block_cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ struct block_cache_conf {
log_func_t *log;
};

/* Usage statistics for block_cache */
/* 36 bytes for each block */
struct block_cache_usage_stats {
uint16_t num_reads; /* Number of read operations */
uint64_t cumulative_reads_time; /* Sum of all the differences between read opeation times */
uint64_t last_read_timestamp; /* Last time we read this block */

uint16_t num_writes; /* Number of write operations */
uint64_t cumulative_writes_time; /* Sum of all the differences between writes opeation times */
uint64_t last_write_timestamp; /* Last time we wrote this block */
};

/* Statistics structure for block_cache */
struct block_cache_stats {
u_int initial_size;
Expand All @@ -48,6 +60,7 @@ struct block_cache_stats {
u_int verified;
u_int mismatch;
u_int out_of_memory_errors;
struct block_cache_usage_stats *usage_stats; /* Pointer to array of usage stats (for each block) */
};

/* block_cache.c */
Expand Down
5 changes: 5 additions & 0 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct s3b_hash {
u_int maxkeys; /* max capacity */
u_int numkeys; /* number of keys in table */
u_int alen; /* hash array length */
u_int collisions; /* Hash collisions */
u_int replaces; /* Correct hash replaces */
void *array[0]; /* hash array */
};

Expand Down Expand Up @@ -106,7 +108,10 @@ s3b_hash_put(struct s3b_hash *hash, void *value)
break;
if (KEY(value2) == key) {
VALUE(hash, i) = value; /* replace existing value having the same key with new value */
hash->replaces++;
return value2;
} else {
hash->collisions++; /* We have a collision */
}
}
assert(hash->numkeys < hash->maxkeys);
Expand Down