summaryrefslogtreecommitdiff
path: root/absl/strings/internal/cordz_info.cc
diff options
context:
space:
mode:
Diffstat (limited to 'absl/strings/internal/cordz_info.cc')
-rw-r--r--absl/strings/internal/cordz_info.cc51
1 files changed, 30 insertions, 21 deletions
diff --git a/absl/strings/internal/cordz_info.cc b/absl/strings/internal/cordz_info.cc
index a3a0b9c0..5c18bbc5 100644
--- a/absl/strings/internal/cordz_info.cc
+++ b/absl/strings/internal/cordz_info.cc
@@ -19,6 +19,7 @@
#include "absl/container/inlined_vector.h"
#include "absl/debugging/stacktrace.h"
#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_ring.h"
#include "absl/strings/internal/cordz_handle.h"
#include "absl/strings/internal/cordz_statistics.h"
@@ -83,19 +84,23 @@ class CordRepAnalyzer {
// Process all top level linear nodes (substrings and flats).
repref = CountLinearReps(repref, memory_usage_);
- // We should have have either a concat or ring node node if not null.
if (repref.rep != nullptr) {
- assert(repref.rep->tag == RING || repref.rep->tag == CONCAT);
if (repref.rep->tag == RING) {
AnalyzeRing(repref);
+ } else if (repref.rep->tag == BTREE) {
+ AnalyzeBtree(repref);
} else if (repref.rep->tag == CONCAT) {
AnalyzeConcat(repref);
+ } else {
+ // We should have either a concat, btree, or ring node if not null.
+ assert(false);
}
}
// Adds values to output
statistics_.estimated_memory_usage += memory_usage_.total;
- statistics_.estimated_fair_share_memory_usage += memory_usage_.fair_share;
+ statistics_.estimated_fair_share_memory_usage +=
+ static_cast<size_t>(memory_usage_.fair_share);
}
private:
@@ -117,13 +122,13 @@ class CordRepAnalyzer {
// Memory usage values
struct MemoryUsage {
size_t total = 0;
- size_t fair_share = 0;
+ double fair_share = 0.0;
// Adds 'size` memory usage to this class, with a cumulative (recursive)
// reference count of `refcount`
void Add(size_t size, size_t refcount) {
total += size;
- fair_share += size / refcount;
+ fair_share += static_cast<double>(size) / refcount;
}
};
@@ -215,28 +220,32 @@ class CordRepAnalyzer {
}
}
- // Counts the provided ring buffer child into `child_usage`.
- void CountRingChild(const CordRep* child, MemoryUsage& child_usage) {
- RepRef rep{child, static_cast<size_t>(child->refcount.Get())};
- rep = CountLinearReps(rep, child_usage);
- assert(rep.rep == nullptr);
- }
-
- // Analyzes the provided ring. As ring buffers can have many child nodes, the
- // effect of rounding errors can become non trivial, so we compute the totals
- // first at the ring level, and then divide the fair share of the total
- // including children fair share totals.
+ // Analyzes the provided ring.
void AnalyzeRing(RepRef rep) {
statistics_.node_count++;
statistics_.node_counts.ring++;
- MemoryUsage ring_usage;
const CordRepRing* ring = rep.rep->ring();
- ring_usage.Add(CordRepRing::AllocSize(ring->capacity()), 1);
+ memory_usage_.Add(CordRepRing::AllocSize(ring->capacity()), rep.refcount);
ring->ForEach([&](CordRepRing::index_type pos) {
- CountRingChild(ring->entry_child(pos), ring_usage);
+ CountLinearReps(rep.Child(ring->entry_child(pos)), memory_usage_);
});
- memory_usage_.total += ring_usage.total;
- memory_usage_.fair_share += ring_usage.fair_share / rep.refcount;
+ }
+
+ // Analyzes the provided btree.
+ void AnalyzeBtree(RepRef rep) {
+ statistics_.node_count++;
+ statistics_.node_counts.btree++;
+ memory_usage_.Add(sizeof(CordRepBtree), rep.refcount);
+ const CordRepBtree* tree = rep.rep->btree();
+ if (tree->height() > 0) {
+ for (CordRep* edge : tree->Edges()) {
+ AnalyzeBtree(rep.Child(edge));
+ }
+ } else {
+ for (CordRep* edge : tree->Edges()) {
+ CountLinearReps(rep.Child(edge), memory_usage_);
+ }
+ }
}
CordzStatistics& statistics_;