Fix size() bug in dashtable

add more stats to info command
fix warnings in -O3 mode.
This commit is contained in:
Roman Gershman 2022-01-20 17:17:11 +02:00
parent f4cfce143c
commit 7a839b6081
10 changed files with 122 additions and 4 deletions

View File

@ -411,9 +411,11 @@ size_t DashTable<_Key, _Value, Policy>::Erase(const Key_t& key) {
auto it = target->FindIt(key, key_hash, EqPred());
if (!it.found())
return 0;
policy_.DestroyKey(target->Key(it.index, it.slot));
policy_.DestroyValue(target->Value(it.index, it.slot));
target->Delete(it, key_hash);
--size_;
return 1;
}
@ -428,6 +430,7 @@ void DashTable<_Key, _Value, Policy>::Erase(iterator it) {
policy_.DestroyValue(it->second);
target->Delete(sit, key_hash);
--size_;
}
template <typename _Key, typename _Value, typename Policy>

View File

@ -355,8 +355,11 @@ TEST_F(DashTest, Insert) {
Dash64::const_iterator it = dt_.Find(i);
ASSERT_TRUE(it == dt_.end());
}
EXPECT_EQ(kNumItems, dt_.size());
EXPECT_EQ(1, dt_.Erase(0));
EXPECT_EQ(0, dt_.Erase(0));
EXPECT_EQ(kNumItems - 1, dt_.size());
auto it = dt_.begin();
ASSERT_FALSE(it.is_done());
auto some_val = it->second;

View File

@ -1375,7 +1375,8 @@ void lpRandomPair(unsigned char *lp, unsigned long total_count, listpackEntry *k
/* Generate even numbers, because listpack saved K-V pair */
int r = (rand() % total_count) * 2;
assert((p = lpSeek(lp, r)));
p = lpSeek(lp, r);
assert(p);
key->sval = lpGetValue(p, &(key->slen), &(key->lval));
if (!val)

View File

@ -36,7 +36,7 @@
#include "config.h"
#include "listpack.h"
#include "util.h" /* for ll2string */
#include "lzf.h"
#include "lzfP.h"
#ifndef REDIS_STATIC
@ -224,10 +224,13 @@ REDIS_STATIC int __quicklistCompressNode(quicklistNode *node) {
return 0;
quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz);
// TODO: roman - to move out of stack.
LZF_STATE sdata;
/* Cancel if compression fails or doesn't compress small enough */
if (((lzf->sz = lzf_compress(node->entry, node->sz, lzf->compressed,
node->sz)) == 0) ||
node->sz, sdata)) == 0) ||
lzf->sz + MIN_COMPRESS_IMPROVE >= node->sz) {
/* lzf_compress aborts/rejects compression if value not compressible. */
zfree(lzf);

View File

@ -250,6 +250,7 @@ sds _sdsMakeRoomFor(sds s, size_t addlen, int greedy) {
len = sdslen(s);
sh = (char*)s-sdsHdrSize(oldtype);
reqlen = newlen = (len+addlen);
(void)reqlen;
assert(newlen > len); /* Catch size_t overflow */
if (greedy == 1) {
if (newlen < SDS_MAX_PREALLOC)

View File

@ -22,6 +22,28 @@ using namespace boost;
using namespace std;
using namespace util;
#define ADD(x) (x) += o.x
DbStats& DbStats::operator+=(const DbStats& o) {
ADD(key_count);
ADD(expire_count);
ADD(bucket_count);
ADD(inline_keys);
ADD(obj_memory_usage);
ADD(table_mem_usage);
return *this;
}
SliceEvents& SliceEvents::operator+=(const SliceEvents& o) {
ADD(evicted_entries);
return *this;
}
#undef ADD
DbSlice::DbSlice(uint32_t index, EngineShard* owner) : shard_id_(index), owner_(owner) {
db_arr_.emplace_back();
CreateDb(0);
@ -38,6 +60,25 @@ DbSlice::~DbSlice() {
}
}
auto DbSlice::GetStats() const -> Stats {
Stats s;
s.events = events_;
for (const auto& db : db_arr_) {
if (!db)
continue;
s.db.key_count += db->main_table.size();
s.db.bucket_count += db->main_table.bucket_count();
s.db.expire_count += db->expire_table.size();
s.db.obj_memory_usage += db->stats.obj_memory_usage;
s.db.inline_keys += db->stats.inline_keys;
s.db.table_mem_usage += (db->main_table.mem_usage() + db->expire_table.mem_usage());
}
return s;
}
void DbSlice::Reserve(DbIndex db_ind, size_t key_size) {
ActivateDb(db_ind);

View File

@ -18,19 +18,64 @@ class ProactorBase;
namespace dfly {
struct DbStats {
// number of active keys.
size_t key_count = 0;
// number of keys that have expiry deadline.
size_t expire_count = 0;
// number of buckets in dictionary (key capacity)
size_t bucket_count = 0;
// Number of inline keys.
size_t inline_keys = 0;
// Object memory usage besides hash-table capacity.
// Applies for any non-inline objects.
size_t obj_memory_usage = 0;
// Memory used by dictionaries.
size_t table_mem_usage = 0;
DbStats& operator+=(const DbStats& o);
};
struct SliceEvents {
// Number of eviction events.
uint64_t evicted_entries = 0;
SliceEvents& operator+=(const SliceEvents& o);
};
class DbSlice {
struct InternalDbStats {
// Number of inline keys.
uint64_t inline_keys = 0;
// Object memory usage besides hash-table capacity.
// Applies for any non-inline objects.
size_t obj_memory_usage = 0;
};
DbSlice(const DbSlice&) = delete;
void operator=(const DbSlice&) = delete;
public:
struct Stats {
DbStats db;
SliceEvents events;
};
DbSlice(uint32_t index, EngineShard* owner);
~DbSlice();
// Activates `db_ind` database if it does not exist (see ActivateDb below).
void Reserve(DbIndex db_ind, size_t key_size);
Stats GetStats() const;
//! UpdateExpireClock updates the expire clock for this db slice.
//! Must be a wall clock so we could replicate it betweeen machines.
void UpdateExpireClock(uint64_t now_ms) {
@ -111,6 +156,8 @@ class DbSlice {
uint64_t now_ms_ = 0; // Used for expire logic, represents a real clock.
SliceEvents events_;
using LockTable = absl::flat_hash_map<std::string, IntentLock>;
struct DbWrapper {

View File

@ -59,6 +59,12 @@ namespace dfly {
using namespace std;
namespace {
quicklistEntry QLEntry() {
quicklistEntry res{.quicklist = NULL, .node = NULL, .zi = NULL, .value = NULL,
.longval = 0, .sz = 0, .offset = 0};
return res;
}
quicklist* GetQL(const PrimeValue& mv) {
return mv.GetQL();
}
@ -379,7 +385,7 @@ OpResult<string> ListFamily::OpIndex(const OpArgs& op_args, std::string_view key
if (!res)
return res.status();
quicklist* ql = GetQL(res.value()->second);
quicklistEntry entry;
quicklistEntry entry = QLEntry();
quicklistIter* iter = quicklistGetIteratorEntryAtIdx(ql, index, &entry);
if (!iter)

View File

@ -23,6 +23,7 @@ extern "C" {
#include "server/main_service.h"
#include "server/server_state.h"
#include "server/transaction.h"
#include "strings/human_readable.h"
#include "util/accept_server.h"
DECLARE_uint32(port);
@ -125,8 +126,10 @@ Metrics ServerFamily::GetMetrics() const {
fibers::mutex mu;
auto cb = [&](EngineShard* shard) {
auto local_stats = shard->db_slice().GetStats();
lock_guard<fibers::mutex> lk(mu);
result.db += local_stats.db;
result.conn_stats += *ServerState::tl_connection_stats();
};
@ -148,6 +151,13 @@ tcp_port:)";
string info = absl::StrCat(kInfo1, FLAGS_port, "\n");
Metrics m = GetMetrics();
absl::StrAppend(&info, "\n# Memory\n");
absl::StrAppend(&info, "object_used_memory:", m.db.obj_memory_usage, "\n");
absl::StrAppend(&info, "table_used_memory:", m.db.table_mem_usage, "\n");
absl::StrAppend(&info, "used_memory_human:",
strings::HumanReadableNumBytes(m.db.table_mem_usage + m.db.obj_memory_usage),
"\n");
absl::StrAppend(&info, "\n# Stats\n");
absl::StrAppend(&info, "total_commands_processed:", m.conn_stats.command_cnt, "\n");
absl::StrAppend(&info, "total_pipelined_commands:", m.conn_stats.pipelined_cmd_cnt, "\n");

View File

@ -19,6 +19,9 @@ class CommandRegistry;
class Service;
struct Metrics {
DbStats db;
SliceEvents events;
ConnectionStats conn_stats;
};