diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 1f51d40..9d138e4 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -718,15 +718,20 @@ struct ReadContext { // A type that's plumbed along the non-const call tree. Same lifetime as // ConflictSet::Impl struct WriteContext { - int64_t entries_erased_accum = 0; - int64_t insert_iterations_accum = 0; - int64_t entries_inserted_accum = 0; - int64_t nodes_allocated_accum = 0; - int64_t nodes_released_accum = 0; - int64_t point_writes_accum = 0; - int64_t range_writes_accum = 0; + + struct Accum { + int64_t entries_erased = 0; + int64_t insert_iterations = 0; + int64_t entries_inserted = 0; + int64_t nodes_allocated = 0; + int64_t nodes_released = 0; + int64_t point_writes = 0; + int64_t range_writes = 0; + int64_t write_bytes = 0; + } accum; + template T *allocate(int c) { - ++nodes_allocated_accum; + ++accum.nodes_allocated; if constexpr (std::is_same_v) { return node0.allocate(c); } else if constexpr (std::is_same_v) { @@ -741,7 +746,7 @@ struct WriteContext { } template void release(T *c) { static_assert(!std::is_same_v); - ++nodes_released_accum; + ++accum.nodes_released; if constexpr (std::is_same_v) { return node0.release(c); } else if constexpr (std::is_same_v) { @@ -1454,7 +1459,7 @@ void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl, // will update it to its new pointee as well. Precondition: `self->entryPresent` Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl, bool logical, Node *&dontInvalidate) { - ++tls->entries_erased_accum; + ++tls->accum.entries_erased; assert(self->parent != nullptr); #if DEBUG_VERBOSE && !defined(NDEBUG) @@ -2834,7 +2839,7 @@ template InternalVersionT writeVersion, WriteContext *tls, ConflictSet::Impl *impl) { - for (;; ++tls->insert_iterations_accum) { + for (;; ++tls->accum.insert_iterations) { if ((*self)->partialKeyLen > 0) { // Handle an existing partial key @@ -2945,10 +2950,10 @@ void destroyTree(Node *root) { void addPointWrite(Node *&root, std::span key, InternalVersionT writeVersion, WriteContext *tls, ConflictSet::Impl *impl) { - ++tls->point_writes_accum; + ++tls->accum.point_writes; auto *n = insert(&root, key, writeVersion, tls, impl); if (!n->entryPresent) { - ++tls->entries_inserted_accum; + ++tls->accum.entries_inserted; auto *p = nextLogical(n); addKey(n); @@ -2975,7 +2980,7 @@ void addWriteRange(Node *&root, std::span begin, end.back() == 0) { return addPointWrite(root, begin, writeVersion, tls, impl); } - ++tls->range_writes_accum; + ++tls->accum.range_writes; const bool beginIsPrefix = lcp == int(begin.size()); auto remaining = begin.subspan(0, lcp); @@ -3019,7 +3024,7 @@ void addWriteRange(Node *&root, std::span begin, beginNode->entryPresent = true; if (insertedBegin) { - ++tls->entries_inserted_accum; + ++tls->accum.entries_inserted; auto *p = nextLogical(beginNode); beginNode->entry.rangeVersion = p == nullptr ? InternalVersionT::zero @@ -3040,7 +3045,7 @@ void addWriteRange(Node *&root, std::span begin, endNode->entryPresent = true; if (insertedEnd) { - ++tls->entries_inserted_accum; + ++tls->accum.entries_inserted; auto *p = nextLogical(endNode); endNode->entry.pointVersion = p == nullptr ? InternalVersionT::zero @@ -3184,10 +3189,9 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { gcScanStep(1000); } - int64_t write_byte_accum = 0; for (int i = 0; i < count; ++i) { const auto &w = writes[i]; - write_byte_accum += w.begin.len + w.end.len; + tls.accum.write_bytes += w.begin.len + w.end.len; auto begin = std::span(w.begin.p, w.begin.len); auto end = std::span(w.end.p, w.end.len); if (w.end.len > 0) { @@ -3201,14 +3205,15 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { } memory_bytes.set(totalBytes); - point_writes_total.add(std::exchange(tls.point_writes_accum, 0)); - range_writes_total.add(std::exchange(tls.range_writes_accum, 0)); - nodes_allocated_total.add(std::exchange(tls.nodes_allocated_accum, 0)); - nodes_released_total.add(std::exchange(tls.nodes_released_accum, 0)); - entries_inserted_total.add(std::exchange(tls.entries_inserted_accum, 0)); - entries_erased_total.add(std::exchange(tls.entries_erased_accum, 0)); - insert_iterations_total.add(std::exchange(tls.insert_iterations_accum, 0)); - write_bytes_total.add(write_byte_accum); + point_writes_total.add(tls.accum.point_writes); + range_writes_total.add(tls.accum.range_writes); + nodes_allocated_total.add(tls.accum.nodes_allocated); + nodes_released_total.add(tls.accum.nodes_released); + entries_inserted_total.add(tls.accum.entries_inserted); + entries_erased_total.add(tls.accum.entries_erased); + insert_iterations_total.add(tls.accum.insert_iterations); + write_bytes_total.add(tls.accum.write_bytes); + memset(&tls.accum, 0, sizeof(tls.accum)); } // Spends up to `fuel` gc'ing, and returns its unused fuel. Reclaims memory @@ -3283,10 +3288,10 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl { keyUpdates = gcScanStep(keyUpdates); memory_bytes.set(totalBytes); - nodes_allocated_total.add(std::exchange(tls.nodes_allocated_accum, 0)); - nodes_released_total.add(std::exchange(tls.nodes_released_accum, 0)); - entries_inserted_total.add(std::exchange(tls.entries_inserted_accum, 0)); - entries_erased_total.add(std::exchange(tls.entries_erased_accum, 0)); + nodes_allocated_total.add(std::exchange(tls.accum.nodes_allocated, 0)); + nodes_released_total.add(std::exchange(tls.accum.nodes_released, 0)); + entries_inserted_total.add(std::exchange(tls.accum.entries_inserted, 0)); + entries_erased_total.add(std::exchange(tls.accum.entries_erased, 0)); oldest_version.set(oldestVersionFullPrecision); }