Implement getBytes()

This commit is contained in:
2024-05-10 12:10:00 -07:00
parent c65d874c07
commit f5920ba6c7
5 changed files with 469 additions and 36 deletions

View File

@@ -1,4 +1,5 @@
#include "VersionedMap.h"
#include "Internal.h"
#include "RootSet.h"
#include <assert.h>
@@ -13,15 +14,6 @@
#include <unordered_set>
#include <xxhash.h>
#ifndef DEBUG_VERBOSE
#define DEBUG_VERBOSE 0
#endif
#if DEBUG_VERBOSE
// Use to toggle debug verbose dynamically
bool debugVerboseEnabled = true;
#endif
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::MutationType>);
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::Key>);
static_assert(std::is_standard_layout_v<weaselab::VersionedMap::Mutation>);
@@ -126,14 +118,15 @@ struct Entry {
}
#endif
if (--refCount == 0) {
free((void *)this);
safe_free((void *)this, sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
}
}
static Entry *make(int64_t pointVersion, int64_t rangeVersion,
const uint8_t *key, int keyLen, const uint8_t *val,
int valLen) {
auto e = (Entry *)malloc(sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
auto e =
(Entry *)safe_malloc(sizeof(Entry) + keyLen + 1 + std::max(valLen, 0));
e->pointVersion = pointVersion;
e->rangeVersion = rangeVersion;
e->keyLen = keyLen;
@@ -176,7 +169,7 @@ static_assert(kUpsizeNodes * sizeof(Node) == kUpsizeBytes);
struct BitSet {
explicit BitSet(uint32_t size)
: words((uint64_t *)calloc(size / 64 + 1, 8)) {}
: words((uint64_t *)safe_calloc(size / 64 + 1, 8)), size(size) {}
bool test(uint32_t i) const {
return words[i >> 6] & (uint64_t(1) << (i & 63));
@@ -207,13 +200,17 @@ struct BitSet {
}
}
~BitSet() { free(words); }
~BitSet() { safe_free(words, (size / 64 + 1) * 8); }
private:
uint32_t max_ = 0;
uint64_t *const words;
const uint32_t size;
};
int64_t mmapBytes = 0;
int64_t peakMmapBytes = 0;
struct MemManager {
MemManager()
: base((Node *)mmapSafe(nullptr, kMapSize, PROT_NONE,
@@ -248,6 +245,10 @@ struct MemManager {
mprotectSafe(base + firstUnaddressable, kUpsizeBytes,
PROT_READ | PROT_WRITE);
firstUnaddressable += kUpsizeNodes;
#if SHOW_MEMORY
mmapBytes = getBytes();
peakMmapBytes = std::max(peakMmapBytes, mmapBytes);
#endif
if (firstUnaddressable > kMapSize / sizeof(Node)) {
fprintf( // GCOVR_EXCL_LINE
stderr, // GCOVR_EXCL_LINE
@@ -344,6 +345,9 @@ struct MemManager {
(firstUnaddressable - newFirstUnaddressable) * sizeof(Node),
PROT_NONE);
firstUnaddressable = newFirstUnaddressable;
#if SHOW_MEMORY
mmapBytes = getBytes();
#endif
}
next = max + 1;
@@ -366,6 +370,10 @@ struct MemManager {
kMinAddressable, next);
}
int64_t getBytes() const {
return (firstUnaddressable - kMinAddressable) * sizeof(Node);
}
private:
uint32_t next = kMinAddressable;
uint32_t firstUnaddressable = kMinAddressable;
@@ -764,17 +772,22 @@ struct VersionedMap::Impl {
}
void setOldestVersion(int64_t oldestVersion) {
mallocBytesDelta = 0;
this->oldestVersion = oldestVersion;
roots.setOldestVersion(oldestVersion);
mm.gc(roots.roots(), roots.rootCount(), oldestVersion);
totalMallocBytes += mallocBytesDelta;
}
int64_t getBytes() const { return totalMallocBytes + mm.getBytes(); }
void printInOrder(int64_t version);
void printInOrderHelper(int64_t version, uint32_t node, int depth);
void addMutations(const Mutation *mutations, int numMutations,
int64_t version) {
mallocBytesDelta = 0;
// TODO scan to remove mutations older than oldestVersion
assert(latestVersion < version);
latestVersion = version;
@@ -805,6 +818,7 @@ struct VersionedMap::Impl {
}
}
roots.add(latestRoot, latestVersion);
totalMallocBytes += mallocBytesDelta;
}
void firstGeq(const Key *key, const int64_t *version, Iterator *iterator,
@@ -816,17 +830,25 @@ struct VersionedMap::Impl {
uint32_t latestRoot;
int64_t oldestVersion = 0;
int64_t latestVersion = 0;
int64_t totalMallocBytes = sizeof(Impl);
};
VersionedMap::VersionedMap(int64_t version)
: impl(new(malloc(sizeof(Impl))) Impl()) {
impl->latestVersion = version;
VersionedMap::Impl *internal_makeImpl(int64_t version) {
mallocBytesDelta = 0;
auto *result =
new (safe_malloc(sizeof(VersionedMap::Impl))) VersionedMap::Impl();
result->totalMallocBytes = mallocBytesDelta;
result->latestVersion = version;
return result;
}
VersionedMap::VersionedMap(int64_t version)
: impl(internal_makeImpl(version)) {}
VersionedMap::~VersionedMap() {
if (impl != nullptr) {
impl->~Impl();
free(impl);
safe_free(impl, sizeof(*impl));
}
}
@@ -864,20 +886,20 @@ struct VersionedMap::Iterator::Impl {
VersionedMap::Iterator::~Iterator() {
if (impl != nullptr) {
impl->~Impl();
free(impl);
safe_free(impl, sizeof(*impl));
}
}
VersionedMap::Iterator::Iterator(const Iterator &other)
: impl(new(malloc(sizeof(Impl))) Impl(*other.impl)) {}
: impl(new(safe_malloc(sizeof(Impl))) Impl(*other.impl)) {}
VersionedMap::Iterator &
VersionedMap::Iterator::operator=(const Iterator &other) {
if (impl != nullptr) {
impl->~Impl();
free(impl);
safe_free(impl, sizeof(*impl));
}
impl = new (malloc(sizeof(Impl))) Impl(*other.impl);
impl = new (safe_malloc(sizeof(Impl))) Impl(*other.impl);
return *this;
}
@@ -888,7 +910,7 @@ VersionedMap::Iterator &
VersionedMap::Iterator::operator=(Iterator &&other) noexcept {
if (impl != nullptr) {
impl->~Impl();
free(impl);
safe_free(impl, sizeof(*impl));
}
impl = std::exchange(other.impl, nullptr);
return *this;
@@ -1033,7 +1055,8 @@ void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version,
new (iterator[i].impl) Iterator::Impl();
} else {
root = handle.rootForVersion(version[i]);
iterator[i].impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl();
iterator[i].impl =
new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl();
}
auto finger = search<std::memory_order_acquire>(key[i], root, version[i]);
@@ -1090,7 +1113,7 @@ void VersionedMap::firstGeq(const Key *key, const int64_t *version,
VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
VersionedMap::Iterator result;
result.impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl();
result.impl = new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl();
result.impl->cmp = 1;
bool ignored;
@@ -1129,7 +1152,7 @@ VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
VersionedMap::Iterator VersionedMap::end(int64_t version) const {
VersionedMap::Iterator result;
result.impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl();
result.impl = new (safe_malloc(sizeof(Iterator::Impl))) Iterator::Impl();
result.impl->cmp = 1;
result.impl->map = impl;
result.impl->mutationIndex = 0;
@@ -1145,7 +1168,7 @@ void VersionedMap::setOldestVersion(int64_t oldestVersion) {
impl->setOldestVersion(oldestVersion);
}
// TODO implement getBytes
int64_t VersionedMap::getBytes() const { return impl->getBytes(); }
// ==================== END IMPLEMENTATION ====================
@@ -1190,6 +1213,18 @@ VersionedMap::Impl *cast(const VersionedMap &m) {
return result;
}
#if SHOW_MEMORY
struct __attribute__((visibility("default"))) PeakPrinter {
~PeakPrinter() {
printf("--- versioned_map ---\n");
printf("malloc bytes: %g\n", double(mallocBytes));
printf("Peak malloc bytes: %g\n", double(peakMallocBytes));
printf("mmap bytes: %g\n", double(mmapBytes));
printf("Peak mmap bytes: %g\n", double(peakMmapBytes));
}
} peakPrinter;
#endif
} // namespace weaselab
#ifdef ENABLE_MAIN
@@ -1200,6 +1235,7 @@ void breakpoint_me() {}
int main() {
{
weaselab::VersionedMap versionedMap{0};
printf("Bytes: %" PRId64 "\n", versionedMap.getBytes());
{
weaselab::VersionedMap::Mutation m[] = {
{(const uint8_t *)"a", nullptr, 1, 0, weaselab::VersionedMap::Set},
@@ -1211,6 +1247,7 @@ int main() {
};
versionedMap.addMutations(m, sizeof(m) / sizeof(m[0]), 1);
}
printf("Bytes: %" PRId64 "\n", versionedMap.getBytes());
{
weaselab::VersionedMap::Mutation m[] = {
{(const uint8_t *)"a", (const uint8_t *)"d", 1, 1,
@@ -1230,7 +1267,9 @@ int main() {
weaselab::VersionedMap::Key k = {(const uint8_t *)"a", 2};
weaselab::VersionedMap::Iterator iter;
versionedMap.firstGeq(&k, &v, &iter, 1);
printf("Bytes: %" PRId64 "\n", versionedMap.getBytes());
versionedMap.setOldestVersion(2);
printf("Bytes: %" PRId64 "\n", versionedMap.getBytes());
breakpoint_me();
for (auto end = versionedMap.end(v); iter != end; ++iter) {
const auto &m = *iter;