diff --git a/src/box/vinyl.c b/src/box/vinyl.c index 38c125171e2a52225f3ca9c043d573cd9906de41..606970eb82438607dacbb6402383b4a2da1b6f4d 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -232,7 +232,6 @@ struct vy_stat { int64_t dump_total; /* iterators statistics */ struct vy_iterator_stat txw_stat; - struct vy_iterator_stat cache_stat; }; static struct vy_stat * @@ -4491,7 +4490,6 @@ vy_info_append_performance(struct vy_env *env, struct info_handler *h) info_table_begin(h, "iterator"); vy_info_append_iterator_stat(h, "txw", &stat->txw_stat); - vy_info_append_iterator_stat(h, "cache", &stat->cache_stat); info_table_end(h); info_table_end(h); @@ -4549,6 +4547,7 @@ vy_index_info(struct vy_index *index, struct info_handler *h) { char buf[1024]; struct vy_index_stat *stat = &index->stat; + struct vy_cache_stat *cache_stat = &index->cache.stat; info_begin(h); @@ -4579,6 +4578,15 @@ vy_index_info(struct vy_index *index, struct info_handler *h) vy_info_append_compact_stat(h, "compact", &stat->disk.compact); info_table_end(h); + info_table_begin(h, "cache"); + vy_info_append_stmt_counter(h, NULL, &cache_stat->count); + info_append_int(h, "lookup", cache_stat->lookup); + vy_info_append_stmt_counter(h, "get", &cache_stat->get); + vy_info_append_stmt_counter(h, "put", &cache_stat->put); + vy_info_append_stmt_counter(h, "invalidate", &cache_stat->invalidate); + vy_info_append_stmt_counter(h, "evict", &cache_stat->evict); + info_table_end(h); + info_append_int(h, "range_count", index->range_count); info_append_int(h, "run_count", index->run_count); info_append_int(h, "run_avg", index->run_count / index->range_count); @@ -7679,8 +7687,7 @@ vy_read_iterator_add_cache(struct vy_read_iterator *itr) { struct vy_merge_src *sub_src = vy_merge_iterator_add(&itr->merge_iterator, true, false); - struct vy_iterator_stat *stat = &itr->index->env->stat->cache_stat; - vy_cache_iterator_open(&sub_src->cache_iterator, stat, + vy_cache_iterator_open(&sub_src->cache_iterator, &itr->index->cache, itr->iterator_type, itr->key, itr->read_view); if (itr->curr_stmt != NULL) { diff --git a/src/box/vy_cache.c b/src/box/vy_cache.c index 33799a89f98aa552e0fb98856b829ecc46cbeec8..7ce43a8efbdb2debd941ccec14a071fc1224aaca 100644 --- a/src/box/vy_cache.c +++ b/src/box/vy_cache.c @@ -90,12 +90,14 @@ vy_cache_entry_new(struct vy_cache_env *env, struct vy_cache *cache, rlist_add(&env->cache_lru, &entry->in_lru); env->mem_used += vy_cache_entry_size(entry); env->cached_count++; + vy_stmt_counter_acct_tuple(&cache->stat.count, stmt); return entry; } static void vy_cache_entry_delete(struct vy_cache_env *env, struct vy_cache_entry *entry) { + vy_stmt_counter_unacct_tuple(&entry->cache->stat.count, entry->stmt); assert(env->cached_count > 0); env->cached_count--; assert(env->mem_used >= vy_cache_entry_size(entry)); @@ -188,6 +190,7 @@ vy_cache_gc_step(struct vy_cache_env *env) } } cache->version++; + vy_stmt_counter_acct_tuple(&cache->stat.evict, entry->stmt); vy_cache_tree_delete(&cache->cache_tree, entry); vy_cache_entry_delete(cache->env, entry); } @@ -294,6 +297,8 @@ vy_cache_add(struct vy_cache *cache, struct tuple *stmt, else if (direction < 0 && boundary_level < entry->right_boundary_level) entry->right_boundary_level = boundary_level; + vy_stmt_counter_acct_tuple(&cache->stat.put, stmt); + /* Done if it's not a chain */ if (prev_stmt == NULL) return; @@ -419,6 +424,8 @@ vy_cache_on_write(struct vy_cache *cache, const struct tuple *stmt, *deleted = to_delete->stmt; tuple_ref(to_delete->stmt); } + vy_stmt_counter_acct_tuple(&cache->stat.invalidate, + to_delete->stmt); vy_cache_tree_delete(&cache->cache_tree, to_delete); vy_cache_entry_delete(cache->env, to_delete); } @@ -495,6 +502,14 @@ vy_cache_iterator_is_end_stop(struct vy_cache_iterator *itr, } } +static void +vy_cache_iterator_get(struct vy_cache_iterator *itr, struct tuple **ret) +{ + *ret = itr->curr_stmt; + if (*ret != NULL) + vy_stmt_counter_acct_tuple(&itr->cache->stat.get, *ret); +} + /** * Find next (lower, older) record with the same key as current * @@ -505,7 +520,6 @@ vy_cache_iterator_start(struct vy_cache_iterator *itr, struct tuple **ret, { assert(!itr->search_started); assert(itr->curr_stmt == NULL); - itr->stat->lookup_count++; *ret = NULL; *stop = false; itr->search_started = true; @@ -513,6 +527,8 @@ vy_cache_iterator_start(struct vy_cache_iterator *itr, struct tuple **ret, struct vy_cache_tree *tree = &itr->cache->cache_tree; const struct tuple *key = itr->key; + itr->cache->stat.lookup++; + if (tuple_field_count(itr->key) > 0) { bool exact; itr->curr_pos = itr->iterator_type == ITER_EQ || @@ -558,8 +574,7 @@ vy_cache_iterator_start(struct vy_cache_iterator *itr, struct tuple **ret, } itr->curr_stmt = candidate; tuple_ref(itr->curr_stmt); - *ret = itr->curr_stmt; - return; + vy_cache_iterator_get(itr, ret); } static void @@ -615,7 +630,6 @@ vy_cache_iterator_next_key(struct vy_stmt_iterator *vitr, } if (!itr->curr_stmt) /* End of search. */ return 0; - itr->stat->step_count++; struct vy_cache_tree *tree = &itr->cache->cache_tree; int dir = iterator_direction(itr->iterator_type); @@ -677,7 +691,7 @@ vy_cache_iterator_next_key(struct vy_stmt_iterator *vitr, itr->curr_stmt = stmt; tuple_ref(itr->curr_stmt); } - *ret = itr->curr_stmt; + vy_cache_iterator_get(itr, ret); return 0; } @@ -734,11 +748,11 @@ vy_cache_iterator_restore(struct vy_stmt_iterator *vitr, vy_cache_tree_iterator_get_elem(tree, &pos); assert(entry != NULL); vy_cache_iterator_is_stop(itr, *entry, stop); - *ret = itr->curr_stmt; + vy_cache_iterator_get(itr, ret); return 0; } if (itr->version == itr->cache->version) { - *ret = itr->curr_stmt; + vy_cache_iterator_get(itr, ret); return 0; } while (true) { @@ -765,7 +779,7 @@ vy_cache_iterator_restore(struct vy_stmt_iterator *vitr, vy_cache_iterator_is_stop(itr, *entry, stop); } } - *ret = itr->curr_stmt; + vy_cache_iterator_get(itr, ret); return rc; } @@ -826,13 +840,11 @@ static struct vy_stmt_iterator_iface vy_cache_iterator_iface = { }; void -vy_cache_iterator_open(struct vy_cache_iterator *itr, - struct vy_iterator_stat *stat, struct vy_cache *cache, +vy_cache_iterator_open(struct vy_cache_iterator *itr, struct vy_cache *cache, enum iterator_type iterator_type, const struct tuple *key, const struct vy_read_view **rv) { itr->base.iface = &vy_cache_iterator_iface; - itr->stat = stat; itr->cache = cache; itr->iterator_type = iterator_type; diff --git a/src/box/vy_cache.h b/src/box/vy_cache.h index 15f7d39842eab0e2147871a5f96e4b276bd75576..2b2dab5150f649b8e55c7255a6019be7f2b1c47c 100644 --- a/src/box/vy_cache.h +++ b/src/box/vy_cache.h @@ -39,6 +39,7 @@ #include "index.h" /* enum iterator_type */ #include "vy_stmt.h" /* for comparators */ #include "vy_stmt_iterator.h" /* struct vy_stmt_iterator */ +#include "vy_stat.h" #include "small/mempool.h" #if defined(__cplusplus) @@ -153,6 +154,8 @@ struct vy_cache { uint32_t version; /* Saved pointer to common cache environment */ struct vy_cache_env *env; + /* Cache statistics. */ + struct vy_cache_stat stat; }; /** @@ -205,8 +208,6 @@ vy_cache_on_write(struct vy_cache *cache, const struct tuple *stmt, struct vy_cache_iterator { /** Parent class, must be the first member */ struct vy_stmt_iterator base; - /** Iterator usage statistics */ - struct vy_iterator_stat *stat; /* The cache */ struct vy_cache *cache; @@ -242,8 +243,7 @@ struct vy_cache_iterator { * @param vlsn - LSN visibility, iterator shows values with lsn <= vlsn */ void -vy_cache_iterator_open(struct vy_cache_iterator *itr, - struct vy_iterator_stat *stat, struct vy_cache *cache, +vy_cache_iterator_open(struct vy_cache_iterator *itr, struct vy_cache *cache, enum iterator_type iterator_type, const struct tuple *key, const struct vy_read_view **rv); diff --git a/src/box/vy_mem.c b/src/box/vy_mem.c index 215a64749a2659c6b4d767f7f580f4cb8f446666..d80a301c8449d252e6bb140ccc2f8f5290537318 100644 --- a/src/box/vy_mem.c +++ b/src/box/vy_mem.c @@ -269,8 +269,7 @@ vy_mem_iterator_copy_to(struct vy_mem_iterator *itr, struct tuple **ret) itr->last_stmt = vy_stmt_dup(itr->curr_stmt, tuple_format(itr->curr_stmt)); *ret = itr->last_stmt; if (itr->last_stmt != NULL) { - itr->stat->get.rows++; - itr->stat->get.bytes += tuple_size(*ret); + vy_stmt_counter_acct_tuple(&itr->stat->get, *ret); return 0; } return -1; diff --git a/src/box/vy_run.c b/src/box/vy_run.c index 75c20361680d152388174ba47941932dd614f8de..0293f186b300587b6fd355017d872fa2a4ea2085 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -1551,8 +1551,7 @@ vy_run_iterator_get(struct vy_run_iterator *itr, struct tuple **result) if (rc == 0) { itr->curr_stmt_pos = itr->curr_pos; itr->curr_stmt = *result; - itr->stat->get.rows++; - itr->stat->get.bytes += tuple_size(*result); + vy_stmt_counter_acct_tuple(&itr->stat->get, *result); } return rc; } diff --git a/src/box/vy_stat.h b/src/box/vy_stat.h index 23493ea322f93803954b5c6ef2d1f6496f270888..e62fc267472c972142ac81a0e411a294ec8f6110 100644 --- a/src/box/vy_stat.h +++ b/src/box/vy_stat.h @@ -33,6 +33,8 @@ #include <stdint.h> +#include "tuple.h" + #if defined(__cplusplus) extern "C" { #endif /* defined(__cplusplus) */ @@ -121,6 +123,44 @@ struct vy_index_stat { } disk; }; +/** Tuple cache statistics. */ +struct vy_cache_stat { + /** Number of statements in the cache. */ + struct vy_stmt_counter count; + /** Number of lookups in the cache. */ + int64_t lookup; + /** Number of reads from the cache. */ + struct vy_stmt_counter get; + /** Number of writes to the cache. */ + struct vy_stmt_counter put; + /** + * Number of statements removed from the cache + * due to overwrite. + */ + struct vy_stmt_counter invalidate; + /** + * Number of statements removed from the cache + * due to memory shortage. + */ + struct vy_stmt_counter evict; +}; + +static inline void +vy_stmt_counter_acct_tuple(struct vy_stmt_counter *c, + const struct tuple *tuple) +{ + c->rows++; + c->bytes += tuple_size(tuple); +} + +static inline void +vy_stmt_counter_unacct_tuple(struct vy_stmt_counter *c, + const struct tuple *tuple) +{ + c->rows--; + c->bytes -= tuple_size(tuple); +} + static inline void vy_stmt_counter_add(struct vy_stmt_counter *c1, const struct vy_stmt_counter *c2)