Add RootSet
This commit is contained in:
116
VersionedMap.cpp
116
VersionedMap.cpp
@@ -216,6 +216,9 @@ struct MemManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (int i = 0; i < numRoots; ++i) {
|
for (int i = 0; i < numRoots; ++i) {
|
||||||
|
if (roots[i] == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
tryPush(roots[i]);
|
tryPush(roots[i]);
|
||||||
while (stackIndex > 0) {
|
while (stackIndex > 0) {
|
||||||
uint32_t p = stack[--stackIndex];
|
uint32_t p = stack[--stackIndex];
|
||||||
@@ -281,7 +284,100 @@ private:
|
|||||||
uint32_t freeList = 0;
|
uint32_t freeList = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VersionedMap::Impl {};
|
struct RootSet {
|
||||||
|
|
||||||
|
/// Register the root node for version after adding mutations
|
||||||
|
void add(uint32_t node, int64_t version) {
|
||||||
|
if (end == 0) {
|
||||||
|
nodes[end] = node;
|
||||||
|
versions[end] = version;
|
||||||
|
++end;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (nodes[end - 1] == node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (end == capacity) {
|
||||||
|
capacity *= 2;
|
||||||
|
nodes = (uint32_t *)realloc(nodes, capacity * sizeof(uint32_t));
|
||||||
|
versions = (int64_t *)realloc(versions, capacity * sizeof(int64_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes[end] = node;
|
||||||
|
versions[end] = version;
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inform that there will be no calls to rootForVersion with a version less
|
||||||
|
/// than `oldestVersion`
|
||||||
|
void setOldestVersion(int64_t oldestVersion) {
|
||||||
|
const uint32_t firstToKeep = rootForVersion(oldestVersion);
|
||||||
|
|
||||||
|
if (firstToKeep != 0) {
|
||||||
|
memmove(nodes, nodes + firstToKeep,
|
||||||
|
(end - firstToKeep) * sizeof(uint32_t));
|
||||||
|
memmove(versions, versions + firstToKeep,
|
||||||
|
(end - firstToKeep) * sizeof(int64_t));
|
||||||
|
end -= firstToKeep;
|
||||||
|
}
|
||||||
|
assert(end > 0);
|
||||||
|
assert(nodes[0] <= oldestVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a root node that can correctly be used for `version`
|
||||||
|
uint32_t rootForVersion(int64_t version) const {
|
||||||
|
assert(end > 0);
|
||||||
|
assert(nodes[0] <= version);
|
||||||
|
|
||||||
|
// Find the last version <= oldestVersion
|
||||||
|
int left = 0;
|
||||||
|
int right = end;
|
||||||
|
int result = 0;
|
||||||
|
while (left <= right) {
|
||||||
|
int mid = left + (right - left) / 2;
|
||||||
|
if (versions[mid] <= version) {
|
||||||
|
result = mid;
|
||||||
|
left = mid + 1;
|
||||||
|
} else {
|
||||||
|
right = mid - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(result < end);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t *roots() const { return nodes; }
|
||||||
|
int rootCount() const { return end; }
|
||||||
|
|
||||||
|
RootSet() {
|
||||||
|
nodes = (uint32_t *)malloc(kMinCapacity * sizeof(uint32_t));
|
||||||
|
versions = (int64_t *)malloc(kMinCapacity * sizeof(int64_t));
|
||||||
|
capacity = kMinCapacity;
|
||||||
|
nodes[0] = 0;
|
||||||
|
versions[0] = 0;
|
||||||
|
end = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
~RootSet() {
|
||||||
|
free(versions);
|
||||||
|
free(nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t *nodes;
|
||||||
|
// versions[i] is the version of nodes[i]
|
||||||
|
int64_t *versions;
|
||||||
|
|
||||||
|
constexpr static uint32_t kMinCapacity = 16;
|
||||||
|
uint32_t capacity;
|
||||||
|
uint32_t end;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VersionedMap::Impl {
|
||||||
|
|
||||||
|
MemManager mm;
|
||||||
|
RootSet roots;
|
||||||
|
};
|
||||||
} // namespace weaselab
|
} // namespace weaselab
|
||||||
|
|
||||||
#ifdef ENABLE_MAIN
|
#ifdef ENABLE_MAIN
|
||||||
@@ -311,5 +407,23 @@ int main() {
|
|||||||
mm.base[root].pointers[1] = 0;
|
mm.base[root].pointers[1] = 0;
|
||||||
mm.base[root].updated.store(false, std::memory_order_relaxed);
|
mm.base[root].updated.store(false, std::memory_order_relaxed);
|
||||||
bench.run("gc", [&]() { mm.gc(&root, 1, 0); });
|
bench.run("gc", [&]() { mm.gc(&root, 1, 0); });
|
||||||
|
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
constexpr int kNumVersions = 1000;
|
||||||
|
weaselab::RootSet roots;
|
||||||
|
for (; i < kNumVersions; i += 2) {
|
||||||
|
roots.add(i, i);
|
||||||
|
roots.add(i, i + 1);
|
||||||
|
}
|
||||||
|
bench.run("roots - setOldestVersion", [&]() {
|
||||||
|
roots.add(i, i);
|
||||||
|
roots.setOldestVersion(i - kNumVersions);
|
||||||
|
++i;
|
||||||
|
});
|
||||||
|
bench.run("roots - rootForVersion", [&]() {
|
||||||
|
bench.doNotOptimizeAway(roots.rootForVersion(i - kNumVersions / 2));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
Reference in New Issue
Block a user