// Copyright 2021 The Abseil Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "absl/strings/cord_analysis.h" #include <cassert> #include <cstddef> #include <cstdint> #include <unordered_set> #include "absl/base/config.h" #include "absl/base/nullability.h" #include "absl/strings/internal/cord_data_edge.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_rep_btree.h" #include "absl/strings/internal/cord_rep_crc.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace cord_internal { namespace { // Accounting mode for analyzing memory usage. enum class Mode { … }; // CordRepRef holds a `const CordRep*` reference in rep, and depending on mode, // holds a 'fraction' representing a cumulative inverse refcount weight. template <Mode mode> struct CordRepRef { … }; // RawUsage holds the computed total number of bytes. template <Mode mode> struct RawUsage { … }; // Overloaded representation of RawUsage that tracks the set of objects // counted, and avoids double-counting objects referenced more than once // by the same Cord. template <> struct RawUsage<Mode::kTotalMorePrecise> { … }; // Returns n / refcount avoiding a div for the common refcount == 1. template <typename refcount_t> double MaybeDiv(double d, refcount_t refcount) { … } // Overloaded 'kFairShare' specialization for CordRepRef. This class holds a // `fraction` value which represents a cumulative inverse refcount weight. // For example, a top node with a reference count of 2 will have a fraction // value of 1/2 = 0.5, representing the 'fair share' of memory it references. // A node below such a node with a reference count of 5 then has a fraction of // 0.5 / 5 = 0.1 representing the fair share of memory below that node, etc. template <> struct CordRepRef<Mode::kFairShare> { … }; // Overloaded 'kFairShare' specialization for RawUsage template <> struct RawUsage<Mode::kFairShare> { … }; // Computes the estimated memory size of the provided data edge. // External reps are assumed 'heap allocated at their exact size'. template <Mode mode> void AnalyzeDataEdge(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { … } // Computes the memory size of the provided Btree tree. template <Mode mode> void AnalyzeBtree(CordRepRef<mode> rep, RawUsage<mode>& raw_usage) { … } template <Mode mode> size_t GetEstimatedUsage(absl::Nonnull<const CordRep*> rep) { … } } // namespace size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep) { … } size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep) { … } size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep) { … } } // namespace cord_internal ABSL_NAMESPACE_END } // namespace absl