mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2024-12-14 11:58:02 +00:00
chore: Track QList memory (#4226)
After running `debug POPULATE 100 list 100 rand type list elements 10000` with `--list_experimental_v2=false`: ``` type_used_memory_list:16512800 used_memory:105573120 ``` When running with `--list_experimental_v2=true`: ``` used_memory:105573120 type_used_memory_list:103601700 ``` TODO: does not yet handle compressed entries correctly but we do not enable compression by default. Fixes #3800 Signed-off-by: Roman Gershman <roman@dragonflydb.io>
This commit is contained in:
parent
68b7baf6a7
commit
3ad5b387bd
4 changed files with 57 additions and 30 deletions
|
@ -60,7 +60,7 @@ namespace dfly {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static_assert(sizeof(QList) == 24);
|
static_assert(sizeof(QList) == 32);
|
||||||
|
|
||||||
enum IterDir : uint8_t { FWD = 1, REV = 0 };
|
enum IterDir : uint8_t { FWD = 1, REV = 0 };
|
||||||
|
|
||||||
|
@ -171,9 +171,13 @@ quicklistNode* CreateFromSV(int container, string_view value) {
|
||||||
return CreateRAW(container, entry, sz);
|
return CreateRAW(container, entry, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void NodeSetEntry(quicklistNode* node, uint8_t* entry) {
|
// Returns the relative increase in size.
|
||||||
|
inline ssize_t NodeSetEntry(quicklistNode* node, uint8_t* entry) {
|
||||||
node->entry = entry;
|
node->entry = entry;
|
||||||
node->sz = lpBytes(node->entry);
|
size_t new_sz = lpBytes(node->entry);
|
||||||
|
ssize_t diff = new_sz - node->sz;
|
||||||
|
node->sz = new_sz;
|
||||||
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compress the listpack in 'node' and update encoding details.
|
/* Compress the listpack in 'node' and update encoding details.
|
||||||
|
@ -195,7 +199,7 @@ bool CompressNode(quicklistNode* node) {
|
||||||
if (node->sz < MIN_COMPRESS_BYTES)
|
if (node->sz < MIN_COMPRESS_BYTES)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// ROMAN: we allocate LZF_STATE on heap, piggy-backing on the existing allocation.
|
// We allocate LZF_STATE on heap, piggy-backing on the existing allocation.
|
||||||
char* uptr = (char*)zmalloc(sizeof(quicklistLZF) + node->sz + sizeof(LZF_STATE));
|
char* uptr = (char*)zmalloc(sizeof(quicklistLZF) + node->sz + sizeof(LZF_STATE));
|
||||||
quicklistLZF* lzf = (quicklistLZF*)uptr;
|
quicklistLZF* lzf = (quicklistLZF*)uptr;
|
||||||
LZF_HSLOT* sdata = (LZF_HSLOT*)(uptr + sizeof(quicklistLZF) + node->sz);
|
LZF_HSLOT* sdata = (LZF_HSLOT*)(uptr + sizeof(quicklistLZF) + node->sz);
|
||||||
|
@ -256,14 +260,13 @@ void RecompressOnly(quicklistNode* node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quicklistNode* SplitNode(quicklistNode* node, int offset, bool after) {
|
quicklistNode* SplitNode(quicklistNode* node, int offset, bool after, ssize_t* diff) {
|
||||||
DCHECK(node->container == QUICKLIST_NODE_CONTAINER_PACKED);
|
DCHECK(node->container == QUICKLIST_NODE_CONTAINER_PACKED);
|
||||||
size_t zl_sz = node->sz;
|
size_t zl_sz = node->sz;
|
||||||
uint8_t* entry = (uint8_t*)zmalloc(zl_sz);
|
uint8_t* entry = (uint8_t*)zmalloc(zl_sz);
|
||||||
|
|
||||||
/* Copy original listpack so we can split it */
|
|
||||||
memcpy(entry, node->entry, zl_sz);
|
memcpy(entry, node->entry, zl_sz);
|
||||||
quicklistNode* new_node = CreateRAW(QUICKLIST_NODE_CONTAINER_PACKED, entry, zl_sz);
|
|
||||||
/* Need positive offset for calculating extent below. */
|
/* Need positive offset for calculating extent below. */
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
offset = node->count + offset;
|
offset = node->count + offset;
|
||||||
|
@ -274,11 +277,13 @@ quicklistNode* SplitNode(quicklistNode* node, int offset, bool after) {
|
||||||
int new_start = after ? 0 : offset;
|
int new_start = after ? 0 : offset;
|
||||||
int new_extent = after ? offset + 1 : -1;
|
int new_extent = after ? offset + 1 : -1;
|
||||||
|
|
||||||
NodeSetEntry(node, lpDeleteRange(node->entry, orig_start, orig_extent));
|
ssize_t diff_existing = NodeSetEntry(node, lpDeleteRange(node->entry, orig_start, orig_extent));
|
||||||
node->count = lpLength(node->entry);
|
node->count = lpLength(node->entry);
|
||||||
|
|
||||||
NodeSetEntry(new_node, lpDeleteRange(new_node->entry, new_start, new_extent));
|
entry = lpDeleteRange(entry, new_start, new_extent);
|
||||||
|
quicklistNode* new_node = CreateRAW(QUICKLIST_NODE_CONTAINER_PACKED, entry, lpBytes(entry));
|
||||||
new_node->count = lpLength(new_node->entry);
|
new_node->count = lpLength(new_node->entry);
|
||||||
|
*diff = diff_existing;
|
||||||
|
|
||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
@ -340,6 +345,7 @@ void QList::Clear() {
|
||||||
}
|
}
|
||||||
head_ = nullptr;
|
head_ = nullptr;
|
||||||
count_ = 0;
|
count_ = 0;
|
||||||
|
malloc_size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QList::Push(string_view value, Where where) {
|
void QList::Push(string_view value, Where where) {
|
||||||
|
@ -419,7 +425,6 @@ bool QList::Replace(long index, std::string_view elem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t QList::MallocUsed(bool slow) const {
|
size_t QList::MallocUsed(bool slow) const {
|
||||||
// Approximation since does not account for listpacks.
|
|
||||||
size_t node_size = len_ * sizeof(quicklistNode) + znallocx(sizeof(quicklist));
|
size_t node_size = len_ * sizeof(quicklistNode) + znallocx(sizeof(quicklist));
|
||||||
if (slow) {
|
if (slow) {
|
||||||
for (quicklistNode* node = head_; node; node = node->next) {
|
for (quicklistNode* node = head_; node; node = node->next) {
|
||||||
|
@ -428,7 +433,7 @@ size_t QList::MallocUsed(bool slow) const {
|
||||||
return node_size;
|
return node_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node_size + count_ * 16; // we account for each member 16 bytes.
|
return node_size + malloc_size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QList::Iterate(IterateFunc cb, long start, long end) const {
|
void QList::Iterate(IterateFunc cb, long start, long end) const {
|
||||||
|
@ -464,8 +469,11 @@ bool QList::PushSentinel(string_view value, Where where) {
|
||||||
|
|
||||||
if (ABSL_PREDICT_TRUE(NodeAllowInsert(orig, fill_, sz))) {
|
if (ABSL_PREDICT_TRUE(NodeAllowInsert(orig, fill_, sz))) {
|
||||||
auto func = (where == HEAD) ? LP_Prepend : LP_Append;
|
auto func = (where == HEAD) ? LP_Prepend : LP_Append;
|
||||||
NodeSetEntry(orig, func(orig->entry, value));
|
malloc_size_ += NodeSetEntry(orig, func(orig->entry, value));
|
||||||
orig->count++;
|
orig->count++;
|
||||||
|
if (len_ == 1) { // sanity check
|
||||||
|
DCHECK_EQ(malloc_size_, orig->sz);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,6 +523,7 @@ void QList::InsertNode(quicklistNode* old_node, quicklistNode* new_node, InsertO
|
||||||
|
|
||||||
/* Update len first, so in Compress we know exactly len */
|
/* Update len first, so in Compress we know exactly len */
|
||||||
len_++;
|
len_++;
|
||||||
|
malloc_size_ += new_node->sz;
|
||||||
|
|
||||||
if (old_node)
|
if (old_node)
|
||||||
quicklistCompress(old_node);
|
quicklistCompress(old_node);
|
||||||
|
@ -529,6 +538,7 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
int full = 0, at_tail = 0, at_head = 0, avail_next = 0, avail_prev = 0;
|
int full = 0, at_tail = 0, at_head = 0, avail_next = 0, avail_prev = 0;
|
||||||
quicklistNode* node = it.current_;
|
quicklistNode* node = it.current_;
|
||||||
size_t sz = elem.size();
|
size_t sz = elem.size();
|
||||||
|
|
||||||
bool after = insert_opt == AFTER;
|
bool after = insert_opt == AFTER;
|
||||||
|
|
||||||
/* Populate accounting flags for easier boolean checks later */
|
/* Populate accounting flags for easier boolean checks later */
|
||||||
|
@ -555,9 +565,11 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
InsertPlainNode(node, elem, insert_opt);
|
InsertPlainNode(node, elem, insert_opt);
|
||||||
} else {
|
} else {
|
||||||
DecompressNodeIfNeeded(true, node);
|
DecompressNodeIfNeeded(true, node);
|
||||||
quicklistNode* new_node = SplitNode(node, it.offset_, after);
|
ssize_t diff_existing = 0;
|
||||||
|
quicklistNode* new_node = SplitNode(node, it.offset_, after, &diff_existing);
|
||||||
quicklistNode* entry_node = InsertPlainNode(node, elem, insert_opt);
|
quicklistNode* entry_node = InsertPlainNode(node, elem, insert_opt);
|
||||||
InsertNode(entry_node, new_node, insert_opt);
|
InsertNode(entry_node, new_node, insert_opt);
|
||||||
|
malloc_size_ += diff_existing;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -565,7 +577,8 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
/* Now determine where and how to insert the new element */
|
/* Now determine where and how to insert the new element */
|
||||||
if (!full) {
|
if (!full) {
|
||||||
DecompressNodeIfNeeded(true, node);
|
DecompressNodeIfNeeded(true, node);
|
||||||
NodeSetEntry(node, LP_Insert(node->entry, elem, it.zi_, after ? LP_AFTER : LP_BEFORE));
|
uint8_t* new_entry = LP_Insert(node->entry, elem, it.zi_, after ? LP_AFTER : LP_BEFORE);
|
||||||
|
malloc_size_ += NodeSetEntry(node, new_entry);
|
||||||
node->count++;
|
node->count++;
|
||||||
RecompressOnly(node);
|
RecompressOnly(node);
|
||||||
} else {
|
} else {
|
||||||
|
@ -576,7 +589,7 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
* - insert entry at head of next node. */
|
* - insert entry at head of next node. */
|
||||||
auto* new_node = node->next;
|
auto* new_node = node->next;
|
||||||
DecompressNodeIfNeeded(true, new_node);
|
DecompressNodeIfNeeded(true, new_node);
|
||||||
NodeSetEntry(new_node, LP_Prepend(new_node->entry, elem));
|
malloc_size_ += NodeSetEntry(new_node, LP_Prepend(new_node->entry, elem));
|
||||||
new_node->count++;
|
new_node->count++;
|
||||||
RecompressOnly(new_node);
|
RecompressOnly(new_node);
|
||||||
RecompressOnly(node);
|
RecompressOnly(node);
|
||||||
|
@ -585,7 +598,7 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
* - insert entry at tail of previous node. */
|
* - insert entry at tail of previous node. */
|
||||||
auto* new_node = node->prev;
|
auto* new_node = node->prev;
|
||||||
DecompressNodeIfNeeded(true, new_node);
|
DecompressNodeIfNeeded(true, new_node);
|
||||||
NodeSetEntry(new_node, LP_Append(new_node->entry, elem));
|
malloc_size_ += NodeSetEntry(new_node, LP_Append(new_node->entry, elem));
|
||||||
new_node->count++;
|
new_node->count++;
|
||||||
RecompressOnly(new_node);
|
RecompressOnly(new_node);
|
||||||
RecompressOnly(node);
|
RecompressOnly(node);
|
||||||
|
@ -598,12 +611,14 @@ void QList::Insert(Iterator it, std::string_view elem, InsertOpt insert_opt) {
|
||||||
/* else, node is full we need to split it. */
|
/* else, node is full we need to split it. */
|
||||||
/* covers both after and !after cases */
|
/* covers both after and !after cases */
|
||||||
DecompressNodeIfNeeded(true, node);
|
DecompressNodeIfNeeded(true, node);
|
||||||
auto* new_node = SplitNode(node, it.offset_, after);
|
ssize_t diff_existing = 0;
|
||||||
|
auto* new_node = SplitNode(node, it.offset_, after, &diff_existing);
|
||||||
auto func = after ? LP_Prepend : LP_Append;
|
auto func = after ? LP_Prepend : LP_Append;
|
||||||
NodeSetEntry(new_node, func(new_node->entry, elem));
|
malloc_size_ += NodeSetEntry(new_node, func(new_node->entry, elem));
|
||||||
new_node->count++;
|
new_node->count++;
|
||||||
InsertNode(node, new_node, insert_opt);
|
InsertNode(node, new_node, insert_opt);
|
||||||
MergeNodes(node);
|
MergeNodes(node);
|
||||||
|
malloc_size_ += diff_existing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count_++;
|
count_++;
|
||||||
|
@ -616,15 +631,15 @@ void QList::Replace(Iterator it, std::string_view elem) {
|
||||||
|
|
||||||
if (ABSL_PREDICT_TRUE(!QL_NODE_IS_PLAIN(node) && !IsLargeElement(sz, fill_) &&
|
if (ABSL_PREDICT_TRUE(!QL_NODE_IS_PLAIN(node) && !IsLargeElement(sz, fill_) &&
|
||||||
(newentry = lpReplace(node->entry, &it.zi_, uint_ptr(elem), sz)) != NULL)) {
|
(newentry = lpReplace(node->entry, &it.zi_, uint_ptr(elem), sz)) != NULL)) {
|
||||||
NodeSetEntry(node, newentry);
|
malloc_size_ += NodeSetEntry(node, newentry);
|
||||||
/* quicklistNext() and quicklistGetIteratorEntryAtIdx() provide an uncompressed node */
|
/* quicklistNext() and quicklistGetIteratorEntryAtIdx() provide an uncompressed node */
|
||||||
quicklistCompress(node);
|
quicklistCompress(node);
|
||||||
} else if (QL_NODE_IS_PLAIN(node)) {
|
} else if (QL_NODE_IS_PLAIN(node)) {
|
||||||
if (IsLargeElement(sz, fill_)) {
|
if (IsLargeElement(sz, fill_)) {
|
||||||
zfree(node->entry);
|
zfree(node->entry);
|
||||||
node->entry = (uint8_t*)zmalloc(sz);
|
uint8_t* new_entry = (uint8_t*)zmalloc(sz);
|
||||||
node->sz = sz;
|
memcpy(new_entry, elem.data(), sz);
|
||||||
memcpy(node->entry, elem.data(), sz);
|
malloc_size_ += NodeSetEntry(node, new_entry);
|
||||||
quicklistCompress(node);
|
quicklistCompress(node);
|
||||||
} else {
|
} else {
|
||||||
Insert(it, elem, AFTER);
|
Insert(it, elem, AFTER);
|
||||||
|
@ -635,8 +650,11 @@ void QList::Replace(Iterator it, std::string_view elem) {
|
||||||
node->dont_compress = 1; /* Prevent compression in InsertNode() */
|
node->dont_compress = 1; /* Prevent compression in InsertNode() */
|
||||||
|
|
||||||
/* If the entry is not at the tail, split the node at the entry's offset. */
|
/* If the entry is not at the tail, split the node at the entry's offset. */
|
||||||
if (it.offset_ != node->count - 1 && it.offset_ != -1)
|
if (it.offset_ != node->count - 1 && it.offset_ != -1) {
|
||||||
split_node = SplitNode(node, it.offset_, 1);
|
ssize_t diff_existing = 0;
|
||||||
|
split_node = SplitNode(node, it.offset_, 1, &diff_existing);
|
||||||
|
malloc_size_ += diff_existing;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a new node and insert it after the original node.
|
/* Create a new node and insert it after the original node.
|
||||||
* If the original node was split, insert the split node after the new node. */
|
* If the original node was split, insert the split node after the new node. */
|
||||||
|
@ -796,7 +814,8 @@ quicklistNode* QList::ListpackMerge(quicklistNode* a, quicklistNode* b) {
|
||||||
keep = a;
|
keep = a;
|
||||||
}
|
}
|
||||||
keep->count = lpLength(keep->entry);
|
keep->count = lpLength(keep->entry);
|
||||||
keep->sz = lpBytes(keep->entry);
|
malloc_size_ += NodeSetEntry(keep, keep->entry);
|
||||||
|
|
||||||
keep->recompress = 0; /* Prevent 'keep' from being recompressed if
|
keep->recompress = 0; /* Prevent 'keep' from being recompressed if
|
||||||
* it becomes head or tail after merging. */
|
* it becomes head or tail after merging. */
|
||||||
|
|
||||||
|
@ -825,6 +844,7 @@ void QList::DelNode(quicklistNode* node) {
|
||||||
/* Update len first, so in Compress we know exactly len */
|
/* Update len first, so in Compress we know exactly len */
|
||||||
len_--;
|
len_--;
|
||||||
count_ -= node->count;
|
count_ -= node->count;
|
||||||
|
malloc_size_ -= node->sz;
|
||||||
|
|
||||||
/* If we deleted a node within our compress depth, we
|
/* If we deleted a node within our compress depth, we
|
||||||
* now have compressed nodes needing to be decompressed. */
|
* now have compressed nodes needing to be decompressed. */
|
||||||
|
@ -850,7 +870,7 @@ bool QList::DelPackedIndex(quicklistNode* node, uint8_t* p) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeSetEntry(node, lpDelete(node->entry, p, NULL));
|
malloc_size_ += NodeSetEntry(node, lpDelete(node->entry, p, NULL));
|
||||||
node->count--;
|
node->count--;
|
||||||
count_--;
|
count_--;
|
||||||
|
|
||||||
|
@ -958,6 +978,7 @@ auto QList::Erase(Iterator it) -> Iterator {
|
||||||
// Sanity, should be noop in release mode.
|
// Sanity, should be noop in release mode.
|
||||||
if (len_ == 1) {
|
if (len_ == 1) {
|
||||||
DCHECK_EQ(count_, head_->count);
|
DCHECK_EQ(count_, head_->count);
|
||||||
|
DCHECK_EQ(malloc_size_, head_->sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* else if (!deleted_node), no changes needed.
|
/* else if (!deleted_node), no changes needed.
|
||||||
|
@ -1027,7 +1048,7 @@ bool QList::Erase(const long start, unsigned count) {
|
||||||
DelNode(node);
|
DelNode(node);
|
||||||
} else {
|
} else {
|
||||||
DecompressNodeIfNeeded(true, node);
|
DecompressNodeIfNeeded(true, node);
|
||||||
NodeSetEntry(node, lpDeleteRange(node->entry, offset, del));
|
malloc_size_ += NodeSetEntry(node, lpDeleteRange(node->entry, offset, del));
|
||||||
node->count -= del;
|
node->count -= del;
|
||||||
count_ -= del;
|
count_ -= del;
|
||||||
if (node->count == 0) {
|
if (node->count == 0) {
|
||||||
|
|
|
@ -162,6 +162,9 @@ class QList {
|
||||||
return head_ ? head_->prev : nullptr;
|
return head_ ? head_->prev : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnPreUpdate(quicklistNode* node);
|
||||||
|
void OnPostUpdate(quicklistNode* node);
|
||||||
|
|
||||||
// Returns false if used existing sentinel, true if a new sentinel was created.
|
// Returns false if used existing sentinel, true if a new sentinel was created.
|
||||||
bool PushSentinel(std::string_view value, Where where);
|
bool PushSentinel(std::string_view value, Where where);
|
||||||
|
|
||||||
|
@ -184,7 +187,7 @@ class QList {
|
||||||
bool DelPackedIndex(quicklistNode* node, uint8_t* p);
|
bool DelPackedIndex(quicklistNode* node, uint8_t* p);
|
||||||
|
|
||||||
quicklistNode* head_ = nullptr;
|
quicklistNode* head_ = nullptr;
|
||||||
|
size_t malloc_size_ = 0; // size of the quicklist struct
|
||||||
uint32_t count_ = 0; /* total count of all entries in all listpacks */
|
uint32_t count_ = 0; /* total count of all entries in all listpacks */
|
||||||
uint32_t len_ = 0; /* number of quicklistNodes */
|
uint32_t len_ = 0; /* number of quicklistNodes */
|
||||||
signed int fill_ : QL_FILL_BITS; /* fill factor for individual nodes */
|
signed int fill_ : QL_FILL_BITS; /* fill factor for individual nodes */
|
||||||
|
|
|
@ -166,6 +166,7 @@ TEST_F(QListTest, Basic) {
|
||||||
ql_.Push("abc", QList::HEAD);
|
ql_.Push("abc", QList::HEAD);
|
||||||
EXPECT_EQ(1, ql_.Size());
|
EXPECT_EQ(1, ql_.Size());
|
||||||
EXPECT_TRUE(ql_.Tail() == ql_.Head());
|
EXPECT_TRUE(ql_.Tail() == ql_.Head());
|
||||||
|
EXPECT_LE(ql_.MallocUsed(false), ql_.MallocUsed(true));
|
||||||
|
|
||||||
auto it = ql_.GetIterator(QList::HEAD);
|
auto it = ql_.GetIterator(QList::HEAD);
|
||||||
ASSERT_TRUE(it.Next()); // Needed to initialize the iterator.
|
ASSERT_TRUE(it.Next()); // Needed to initialize the iterator.
|
||||||
|
@ -176,6 +177,7 @@ TEST_F(QListTest, Basic) {
|
||||||
|
|
||||||
ql_.Push("def", QList::TAIL);
|
ql_.Push("def", QList::TAIL);
|
||||||
EXPECT_EQ(2, ql_.Size());
|
EXPECT_EQ(2, ql_.Size());
|
||||||
|
EXPECT_LE(ql_.MallocUsed(false), ql_.MallocUsed(true));
|
||||||
|
|
||||||
it = ql_.GetIterator(QList::TAIL);
|
it = ql_.GetIterator(QList::TAIL);
|
||||||
ASSERT_TRUE(it.Next());
|
ASSERT_TRUE(it.Next());
|
||||||
|
@ -195,6 +197,7 @@ TEST_F(QListTest, Basic) {
|
||||||
vector<string> items = ToItems();
|
vector<string> items = ToItems();
|
||||||
|
|
||||||
EXPECT_THAT(items, ElementsAre("abc", "def"));
|
EXPECT_THAT(items, ElementsAre("abc", "def"));
|
||||||
|
EXPECT_GT(ql_.MallocUsed(false), ql_.MallocUsed(true) * 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(QListTest, ListPack) {
|
TEST_F(QListTest, ListPack) {
|
||||||
|
|
|
@ -60,8 +60,8 @@ ABSL_FLAG(int32_t, list_max_listpack_size, -2, "Maximum listpack size, default i
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ABSL_FLAG(int32_t, list_compress_depth, 0, "Compress depth of the list. Default is no compression");
|
ABSL_FLAG(int32_t, list_compress_depth, 0, "Compress depth of the list. Default is no compression");
|
||||||
ABSL_FLAG(bool, list_experimental_v2, false,
|
ABSL_FLAG(bool, list_experimental_v2, true,
|
||||||
"Compress depth of the list. Default is no compression");
|
"Enables dragonfly specific implementation of quicklist");
|
||||||
|
|
||||||
namespace dfly {
|
namespace dfly {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue