Implement getBytes()
This commit is contained in:
@@ -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;
|
||||
|
Reference in New Issue
Block a user