diff --git a/block_cache.c b/block_cache.c index 03b05726..78015a3e 100644 --- a/block_cache.c +++ b/block_cache.c @@ -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 */ @@ -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 @@ -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) { @@ -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); @@ -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 */ diff --git a/block_cache.h b/block_cache.h index 1c329a0c..3eabf8ad 100644 --- a/block_cache.h +++ b/block_cache.h @@ -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; @@ -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 */ diff --git a/hash.c b/hash.c index 68cf106a..fd3abdbd 100644 --- a/hash.c +++ b/hash.c @@ -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 */ }; @@ -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);