|
|
|
// Copyright 2019 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/internal/cordz_info.h"
|
|
|
|
|
|
|
|
#include "absl/base/config.h"
|
|
|
|
#include "absl/base/internal/spinlock.h"
|
|
|
|
#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"
|
Export of internal Abseil changes
--
83e4cdf03a4d702b30e69204060de09e462e23c6 by Greg Falcon <gfalcon@google.com>:
Revert the crc addition to RefcountAndFlags, and restore related comments to their original state.
In development, the implementation of SetExpectedCrc() changed, and there is no longer a need to track the CRC status in the refcount.
Since the distinction between IsOne() and IsMutable() is subtle *and unused*, removing it now can help avoid subtle bugs in the future. This distinction can always be added back later, if it proves necessary.
Keep the reserved bit for now; all it costs is one extra mask instruction in the refcount checks, and space for extra state in Cord is always hard to find.
PiperOrigin-RevId: 408647038
--
ee67585cf66954176615271f50f8b278119dd138 by Greg Falcon <gfalcon@google.com>:
Implement Cord::SetExpectedChecksum() and Cord::ExpectedChecksum().
SetExpectedChecksum() will store a uint32_t out-of-band alongside a Cord's data. This value persists through copies and assignments. Mutating operations on a Cord cause the value to be forgotten. ExpectedChecksum() retrieves the stored value, if present.
This API is intended for storing a CRC32C checksum alongside data, allowing checksums to be passed through dataflows and validated at the final step. However, this API is agnostic to the meaning of the stored value. No CRC32C validation is performed by these new APIs.
This implementation adds a new CordRep node, CordRepCrc. A CordRepCrc may (currently) only live at the top of a tree. This allows traversal logic to be agnostic to these nodes, instead putting the needed branches at the mutation level. This also implements the property requested from API review, that any mutation is guaranteed to permanently forget the stored CRC.
PiperOrigin-RevId: 408611221
--
a86f592402b37c854ebdc77d2b9b425451a7a675 by Martijn Vels <mvels@google.com>:
Move 'ExtractResult' into CordRep
The result of an extract operation is logically identical for any tree implementation, and having a single type makes 'tree independent' implementation in cord.cc more concise.
PiperOrigin-RevId: 408332408
--
baa7647e21db59a87f75af9cac62172ce38a0f71 by Abseil Team <absl-team@google.com>:
Replace usages of `assert` macros with `ABSL_HARDENING_ASSERT`.
PiperOrigin-RevId: 408272133
--
c7658133d8662c39fa5035fc93a364c7c3d327e0 by Martijn Vels <mvels@google.com>:
Add CordRepBtree::ExtractAppendBuffer
PiperOrigin-RevId: 407944179
--
5775100363b5890ebfe710fadebf040445eab991 by Martijn Vels <mvels@google.com>:
Add CordRepConcat::ExtractAppendBuffer
PiperOrigin-RevId: 407932968
--
9f520ba1600a93352c78f644a369c7c76195ee86 by Greg Falcon <gfalcon@google.com>:
Add cordz tracking for crc nodes.
This also adds a new kSetExpectedChecksum method to the list of tracked methods. This is presently unused but will be used soon.
PiperOrigin-RevId: 407884120
GitOrigin-RevId: 83e4cdf03a4d702b30e69204060de09e462e23c6
Change-Id: I134ace2d87215813eaa60a282996a33884676c06
3 years ago
|
|
|
#include "absl/strings/internal/cord_rep_crc.h"
|
|
|
|
#include "absl/strings/internal/cord_rep_ring.h"
|
|
|
|
#include "absl/strings/internal/cordz_handle.h"
|
|
|
|
#include "absl/strings/internal/cordz_statistics.h"
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
#include "absl/strings/internal/cordz_update_tracker.h"
|
|
|
|
#include "absl/synchronization/mutex.h"
|
|
|
|
#include "absl/types/span.h"
|
|
|
|
|
|
|
|
namespace absl {
|
|
|
|
ABSL_NAMESPACE_BEGIN
|
|
|
|
namespace cord_internal {
|
|
|
|
|
|
|
|
using ::absl::base_internal::SpinLockHolder;
|
|
|
|
|
|
|
|
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
|
|
|
|
constexpr int CordzInfo::kMaxStackDepth;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// CordRepAnalyzer performs the analysis of a cord.
|
|
|
|
//
|
|
|
|
// It computes absolute node counts and total memory usage, and an 'estimated
|
|
|
|
// fair share memory usage` statistic.
|
|
|
|
// Conceptually, it divides the 'memory usage' at each location in the 'cord
|
|
|
|
// graph' by the cumulative reference count of that location. The cumulative
|
|
|
|
// reference count is the factored total of all edges leading into that node.
|
|
|
|
//
|
|
|
|
// The top level node is treated specially: we assume the current thread
|
|
|
|
// (typically called from the CordzHandler) to hold a reference purely to
|
|
|
|
// perform a safe analysis, and not being part of the application. So we
|
|
|
|
// substract 1 from the reference count of the top node to compute the
|
|
|
|
// 'application fair share' excluding the reference of the current thread.
|
|
|
|
//
|
|
|
|
// An example of fair sharing, and why we multiply reference counts:
|
|
|
|
// Assume we have 2 CordReps, both being a Substring referencing a Flat:
|
|
|
|
// CordSubstring A (refcount = 5) --> child Flat C (refcount = 2)
|
|
|
|
// CordSubstring B (refcount = 9) --> child Flat C (refcount = 2)
|
|
|
|
//
|
|
|
|
// Flat C has 2 incoming edges from the 2 substrings (refcount = 2) and is not
|
|
|
|
// referenced directly anywhere else. Translated into a 'fair share', we then
|
|
|
|
// attribute 50% of the memory (memory / refcount = 2) to each incoming edge.
|
|
|
|
// Rep A has a refcount of 5, so we attribute each incoming edge 1 / 5th of the
|
|
|
|
// memory cost below it, i.e.: the fair share of Rep A of the memory used by C
|
|
|
|
// is then 'memory C / (refcount C * refcount A) + (memory A / refcount A)'.
|
|
|
|
// It is also easy to see how all incoming edges add up to 100%.
|
|
|
|
class CordRepAnalyzer {
|
|
|
|
public:
|
|
|
|
// Creates an analyzer instance binding to `statistics`.
|
|
|
|
explicit CordRepAnalyzer(CordzStatistics& statistics)
|
|
|
|
: statistics_(statistics) {}
|
|
|
|
|
|
|
|
// Analyzes the memory statistics and node counts for the provided `rep`, and
|
|
|
|
// adds the results to `statistics`. Note that node counts and memory sizes
|
|
|
|
// are not initialized, computed values are added to any existing values.
|
|
|
|
void AnalyzeCordRep(const CordRep* rep) {
|
|
|
|
// Process all linear nodes.
|
|
|
|
// As per the class comments, use refcout - 1 on the top level node, as the
|
|
|
|
// top level node is assumed to be referenced only for analysis purposes.
|
|
|
|
size_t refcount = rep->refcount.Get();
|
|
|
|
RepRef repref{rep, (refcount > 1) ? refcount - 1 : 1};
|
|
|
|
|
Export of internal Abseil changes
--
83e4cdf03a4d702b30e69204060de09e462e23c6 by Greg Falcon <gfalcon@google.com>:
Revert the crc addition to RefcountAndFlags, and restore related comments to their original state.
In development, the implementation of SetExpectedCrc() changed, and there is no longer a need to track the CRC status in the refcount.
Since the distinction between IsOne() and IsMutable() is subtle *and unused*, removing it now can help avoid subtle bugs in the future. This distinction can always be added back later, if it proves necessary.
Keep the reserved bit for now; all it costs is one extra mask instruction in the refcount checks, and space for extra state in Cord is always hard to find.
PiperOrigin-RevId: 408647038
--
ee67585cf66954176615271f50f8b278119dd138 by Greg Falcon <gfalcon@google.com>:
Implement Cord::SetExpectedChecksum() and Cord::ExpectedChecksum().
SetExpectedChecksum() will store a uint32_t out-of-band alongside a Cord's data. This value persists through copies and assignments. Mutating operations on a Cord cause the value to be forgotten. ExpectedChecksum() retrieves the stored value, if present.
This API is intended for storing a CRC32C checksum alongside data, allowing checksums to be passed through dataflows and validated at the final step. However, this API is agnostic to the meaning of the stored value. No CRC32C validation is performed by these new APIs.
This implementation adds a new CordRep node, CordRepCrc. A CordRepCrc may (currently) only live at the top of a tree. This allows traversal logic to be agnostic to these nodes, instead putting the needed branches at the mutation level. This also implements the property requested from API review, that any mutation is guaranteed to permanently forget the stored CRC.
PiperOrigin-RevId: 408611221
--
a86f592402b37c854ebdc77d2b9b425451a7a675 by Martijn Vels <mvels@google.com>:
Move 'ExtractResult' into CordRep
The result of an extract operation is logically identical for any tree implementation, and having a single type makes 'tree independent' implementation in cord.cc more concise.
PiperOrigin-RevId: 408332408
--
baa7647e21db59a87f75af9cac62172ce38a0f71 by Abseil Team <absl-team@google.com>:
Replace usages of `assert` macros with `ABSL_HARDENING_ASSERT`.
PiperOrigin-RevId: 408272133
--
c7658133d8662c39fa5035fc93a364c7c3d327e0 by Martijn Vels <mvels@google.com>:
Add CordRepBtree::ExtractAppendBuffer
PiperOrigin-RevId: 407944179
--
5775100363b5890ebfe710fadebf040445eab991 by Martijn Vels <mvels@google.com>:
Add CordRepConcat::ExtractAppendBuffer
PiperOrigin-RevId: 407932968
--
9f520ba1600a93352c78f644a369c7c76195ee86 by Greg Falcon <gfalcon@google.com>:
Add cordz tracking for crc nodes.
This also adds a new kSetExpectedChecksum method to the list of tracked methods. This is presently unused but will be used soon.
PiperOrigin-RevId: 407884120
GitOrigin-RevId: 83e4cdf03a4d702b30e69204060de09e462e23c6
Change-Id: I134ace2d87215813eaa60a282996a33884676c06
3 years ago
|
|
|
// Process the top level CRC node, if present.
|
|
|
|
if (repref.rep->tag == CRC) {
|
|
|
|
statistics_.node_count++;
|
|
|
|
statistics_.node_counts.crc++;
|
|
|
|
memory_usage_.Add(sizeof(CordRepCrc), repref.refcount);
|
|
|
|
repref = repref.Child(repref.rep->crc()->child);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process all top level linear nodes (substrings and flats).
|
|
|
|
repref = CountLinearReps(repref, memory_usage_);
|
|
|
|
|
|
|
|
if (repref.rep != nullptr) {
|
|
|
|
if (repref.rep->tag == RING) {
|
|
|
|
AnalyzeRing(repref);
|
|
|
|
} else if (repref.rep->tag == BTREE) {
|
|
|
|
AnalyzeBtree(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 +=
|
|
|
|
static_cast<size_t>(memory_usage_.fair_share);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
// RepRef identifies a CordRep* inside the Cord tree with its cumulative
|
|
|
|
// refcount including itself. For example, a tree consisting of a substring
|
|
|
|
// with a refcount of 3 and a child flat with a refcount of 4 will have RepRef
|
|
|
|
// refcounts of 3 and 12 respectively.
|
|
|
|
struct RepRef {
|
|
|
|
const CordRep* rep;
|
|
|
|
size_t refcount;
|
|
|
|
|
|
|
|
// Returns a 'child' RepRef which contains the cumulative reference count of
|
|
|
|
// this instance multiplied by the child's reference count.
|
|
|
|
RepRef Child(const CordRep* child) const {
|
|
|
|
return RepRef{child, refcount * child->refcount.Get()};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Memory usage values
|
|
|
|
struct MemoryUsage {
|
|
|
|
size_t total = 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 += static_cast<double>(size) / refcount;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Counts a flat of the provide allocated size
|
|
|
|
void CountFlat(size_t size) {
|
|
|
|
statistics_.node_count++;
|
|
|
|
statistics_.node_counts.flat++;
|
|
|
|
if (size <= 64) {
|
|
|
|
statistics_.node_counts.flat_64++;
|
|
|
|
} else if (size <= 128) {
|
|
|
|
statistics_.node_counts.flat_128++;
|
|
|
|
} else if (size <= 256) {
|
|
|
|
statistics_.node_counts.flat_256++;
|
|
|
|
} else if (size <= 512) {
|
|
|
|
statistics_.node_counts.flat_512++;
|
|
|
|
} else if (size <= 1024) {
|
|
|
|
statistics_.node_counts.flat_1k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Processes 'linear' reps (substring, flat, external) not requiring iteration
|
|
|
|
// or recursion. Returns RefRep{null} if all reps were processed, else returns
|
|
|
|
// the top-most non-linear concat or ring cordrep.
|
|
|
|
// Node counts are updated into `statistics_`, memory usage is update into
|
|
|
|
// `memory_usage`, which typically references `memory_usage_` except for ring
|
|
|
|
// buffers where we count children unrounded.
|
|
|
|
RepRef CountLinearReps(RepRef rep, MemoryUsage& memory_usage) {
|
|
|
|
// Consume all substrings
|
|
|
|
while (rep.rep->tag == SUBSTRING) {
|
|
|
|
statistics_.node_count++;
|
|
|
|
statistics_.node_counts.substring++;
|
|
|
|
memory_usage.Add(sizeof(CordRepSubstring), rep.refcount);
|
|
|
|
rep = rep.Child(rep.rep->substring()->child);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consume possible FLAT
|
|
|
|
if (rep.rep->tag >= FLAT) {
|
|
|
|
size_t size = rep.rep->flat()->AllocatedSize();
|
|
|
|
CountFlat(size);
|
|
|
|
memory_usage.Add(size, rep.refcount);
|
|
|
|
return RepRef{nullptr, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consume possible external
|
|
|
|
if (rep.rep->tag == EXTERNAL) {
|
|
|
|
statistics_.node_count++;
|
|
|
|
statistics_.node_counts.external++;
|
|
|
|
size_t size = rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>);
|
|
|
|
memory_usage.Add(size, rep.refcount);
|
|
|
|
return RepRef{nullptr, 0};
|
|
|
|
}
|
|
|
|
|
|
|
|
return rep;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Analyzes the provided ring.
|
|
|
|
void AnalyzeRing(RepRef rep) {
|
|
|
|
statistics_.node_count++;
|
|
|
|
statistics_.node_counts.ring++;
|
|
|
|
const CordRepRing* ring = rep.rep->ring();
|
|
|
|
memory_usage_.Add(CordRepRing::AllocSize(ring->capacity()), rep.refcount);
|
|
|
|
ring->ForEach([&](CordRepRing::index_type pos) {
|
|
|
|
CountLinearReps(rep.Child(ring->entry_child(pos)), memory_usage_);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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_;
|
|
|
|
MemoryUsage memory_usage_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
CordzInfo* CordzInfo::Head(const CordzSnapshot& snapshot) {
|
|
|
|
ABSL_ASSERT(snapshot.is_snapshot());
|
|
|
|
|
|
|
|
// We can do an 'unsafe' load of 'head', as we are guaranteed that the
|
|
|
|
// instance it points to is kept alive by the provided CordzSnapshot, so we
|
|
|
|
// can simply return the current value using an acquire load.
|
|
|
|
// We do enforce in DEBUG builds that the 'head' value is present in the
|
|
|
|
// delete queue: ODR violations may lead to 'snapshot' and 'global_list_'
|
|
|
|
// being in different libraries / modules.
|
|
|
|
CordzInfo* head = global_list_.head.load(std::memory_order_acquire);
|
|
|
|
ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(head));
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
|
|
|
|
CordzInfo* CordzInfo::Next(const CordzSnapshot& snapshot) const {
|
|
|
|
ABSL_ASSERT(snapshot.is_snapshot());
|
|
|
|
|
|
|
|
// Similar to the 'Head()' function, we do not need a mutex here.
|
|
|
|
CordzInfo* next = ci_next_.load(std::memory_order_acquire);
|
|
|
|
ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(this));
|
|
|
|
ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(next));
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CordzInfo::TrackCord(InlineData& cord, MethodIdentifier method) {
|
|
|
|
assert(cord.is_tree());
|
|
|
|
assert(!cord.is_profiled());
|
|
|
|
CordzInfo* cordz_info = new CordzInfo(cord.as_tree(), nullptr, method);
|
|
|
|
cord.set_cordz_info(cordz_info);
|
|
|
|
cordz_info->Track();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CordzInfo::TrackCord(InlineData& cord, const InlineData& src,
|
|
|
|
MethodIdentifier method) {
|
|
|
|
assert(cord.is_tree());
|
|
|
|
assert(src.is_tree());
|
|
|
|
|
|
|
|
// Unsample current as we the current cord is being replaced with 'src',
|
|
|
|
// so any method history is no longer relevant.
|
|
|
|
CordzInfo* cordz_info = cord.cordz_info();
|
|
|
|
if (cordz_info != nullptr) cordz_info->Untrack();
|
|
|
|
|
|
|
|
// Start new cord sample
|
|
|
|
cordz_info = new CordzInfo(cord.as_tree(), src.cordz_info(), method);
|
|
|
|
cord.set_cordz_info(cordz_info);
|
|
|
|
cordz_info->Track();
|
|
|
|
}
|
|
|
|
|
Export of internal Abseil changes
--
9fc37c11b9e46287acef00ee06ed9adcba54dd13 by Greg Falcon <gfalcon@google.com>:
Rename absl::hash_internal::HashState to absl::hash_internal::MixingHashState.
Before this change, we had two classes named HashState: absl::HashState, the public API used for type erasure, and absl::hash_internal::HashState, the internal concrete implementation ordinarily used.
The internal class used to be named `CityHashState`, but we renamed it to `HashState` it when we changed underlying hash implementation to wyhash. This inadvertent naming conflict made the code much harder to read, and this change intends to undo that.
PiperOrigin-RevId: 373481959
--
4aec55ffddebd085c239352a2e20721091f719a1 by Greg Falcon <gfalcon@google.com>:
Introduce absl::HashOf(), a convenience wrapper around absl::Hash that calculates hashes from the values of its arguments.
PiperOrigin-RevId: 373461406
--
86b5fd8db50bbc8bd0aa9258523527381fe0445d by Abseil Team <absl-team@google.com>:
Improve speed of BlockingCounter by making its most common path lock free.
With the new implementation, the fast path of BlockingCounter::DecrementCount()
is only a fetch_sub operation. This is most times much more efficient than the
previous implementation (full mutex lock/unlock). As a matter of fact, in most
actual usecases in practice, the waiter thread is already waiting on the
Wait() call when DecrementCount() is called, which makes Mutex::Unlock() take
the slow path as there's a waiter thread that it might need to wake up.
PiperOrigin-RevId: 373394164
--
65c876be5eac0cd32583ff8535ede4109d39cf3f by Martijn Vels <mvels@google.com>:
Move the 'sample copied cord' logic into MaybeTrackCord(),
This changes move the logic for selecting if a cord should remain being sampled from Cord to CordzInfo::MaybeTrackCord, and updates the documentation for the latter method.
PiperOrigin-RevId: 373363168
--
e84410bd0aada293a81dfb82656c952e209e21fb by Martijn Vels <mvels@google.com>:
Add check for the first call to cordz_should_profile() for each thread.
This prevents the first cord of a newly created thread to be always sampled, which is a 'bad' kind of determinism for sampling.
PiperOrigin-RevId: 373229768
--
bf09c589dc099ac8f4af780bf7e609c53c27574c by Samuel Benzaquen <sbenza@google.com>:
Refactor the Flags structure into an enum.
This gives us more control over the representation and allows for easier
merging during parsing.
PiperOrigin-RevId: 373163038
--
b947b0c51083b7b6508284b5d31819596c91729e by Derek Mauro <dmauro@google.com>:
Fixes warnings about shadowed variables
Fixes #956
PiperOrigin-RevId: 373158133
GitOrigin-RevId: 9fc37c11b9e46287acef00ee06ed9adcba54dd13
Change-Id: I91f35699f9bf439d1a870c6493946a310afe088c
4 years ago
|
|
|
void CordzInfo::MaybeTrackCordImpl(InlineData& cord, const InlineData& src,
|
|
|
|
MethodIdentifier method) {
|
|
|
|
if (src.is_profiled()) {
|
|
|
|
TrackCord(cord, src, method);
|
|
|
|
} else if (cord.is_profiled()) {
|
|
|
|
cord.cordz_info()->Untrack();
|
|
|
|
cord.clear_cordz_info();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
CordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {
|
|
|
|
if (src == nullptr) return MethodIdentifier::kUnknown;
|
|
|
|
return src->parent_method_ != MethodIdentifier::kUnknown ? src->parent_method_
|
|
|
|
: src->method_;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
|
|
|
|
assert(stack);
|
|
|
|
if (src == nullptr) return 0;
|
|
|
|
if (src->parent_stack_depth_) {
|
|
|
|
memcpy(stack, src->parent_stack_, src->parent_stack_depth_ * sizeof(void*));
|
|
|
|
return src->parent_stack_depth_;
|
|
|
|
}
|
|
|
|
memcpy(stack, src->stack_, src->stack_depth_ * sizeof(void*));
|
|
|
|
return src->stack_depth_;
|
|
|
|
}
|
|
|
|
|
|
|
|
CordzInfo::CordzInfo(CordRep* rep, const CordzInfo* src,
|
|
|
|
MethodIdentifier method)
|
|
|
|
: rep_(rep),
|
|
|
|
stack_depth_(absl::GetStackTrace(stack_, /*max_depth=*/kMaxStackDepth,
|
|
|
|
/*skip_count=*/1)),
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
parent_stack_depth_(FillParentStack(src, parent_stack_)),
|
|
|
|
method_(method),
|
|
|
|
parent_method_(GetParentMethod(src)),
|
|
|
|
create_time_(absl::Now()) {
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
update_tracker_.LossyAdd(method);
|
|
|
|
if (src) {
|
|
|
|
// Copy parent counters.
|
|
|
|
update_tracker_.LossyAdd(src->update_tracker_);
|
|
|
|
}
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
}
|
|
|
|
|
|
|
|
CordzInfo::~CordzInfo() {
|
|
|
|
// `rep_` is potentially kept alive if CordzInfo is included
|
|
|
|
// in a collection snapshot (which should be rare).
|
|
|
|
if (ABSL_PREDICT_FALSE(rep_)) {
|
|
|
|
CordRep::Unref(rep_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CordzInfo::Track() {
|
|
|
|
SpinLockHolder l(&list_->mutex);
|
|
|
|
|
|
|
|
CordzInfo* const head = list_->head.load(std::memory_order_acquire);
|
|
|
|
if (head != nullptr) {
|
|
|
|
head->ci_prev_.store(this, std::memory_order_release);
|
|
|
|
}
|
|
|
|
ci_next_.store(head, std::memory_order_release);
|
|
|
|
list_->head.store(this, std::memory_order_release);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CordzInfo::Untrack() {
|
|
|
|
ODRCheck();
|
|
|
|
{
|
|
|
|
SpinLockHolder l(&list_->mutex);
|
|
|
|
|
|
|
|
CordzInfo* const head = list_->head.load(std::memory_order_acquire);
|
|
|
|
CordzInfo* const next = ci_next_.load(std::memory_order_acquire);
|
|
|
|
CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire);
|
|
|
|
|
|
|
|
if (next) {
|
|
|
|
ABSL_ASSERT(next->ci_prev_.load(std::memory_order_acquire) == this);
|
|
|
|
next->ci_prev_.store(prev, std::memory_order_release);
|
|
|
|
}
|
|
|
|
if (prev) {
|
|
|
|
ABSL_ASSERT(head != this);
|
|
|
|
ABSL_ASSERT(prev->ci_next_.load(std::memory_order_acquire) == this);
|
|
|
|
prev->ci_next_.store(next, std::memory_order_release);
|
|
|
|
} else {
|
|
|
|
ABSL_ASSERT(head == this);
|
|
|
|
list_->head.store(next, std::memory_order_release);
|
|
|
|
}
|
|
|
|
}
|
Export of internal Abseil changes
--
60b8e77be4bab1bbd3b4c3b70054879229634511 by Derek Mauro <dmauro@google.com>:
Use _MSVC_LANG for some C++ dialect checks since MSVC doesn't
set __cplusplus accurately by default.
https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
See GitHub #722.
PiperOrigin-RevId: 371362181
--
5d736accdff04db0e722f377c0d79f2d3ed53263 by Martijn Vels <mvels@google.com>:
Fix the estimated memory size for CordRepExternal
PiperOrigin-RevId: 371350380
--
eaaa1d8a167aeca67a2aa3a098a2b61a9d72172f by Martijn Vels <mvels@google.com>:
Remove flakes by not enforcing re-allocated pointers do never match original
Tests that do multiple updates could end up with the original allocated pointer on a 2nd resize, so the 'EqIfPrivate' should not assume that if we do 'not' have the capacity that all following relocations will never match the original. We only care about 'pointer unchanged if private and there is capacity', trying to establish 'pointer changed at some point due to re-allocation; is pointless.
PiperOrigin-RevId: 371338965
--
d1837bee6bade1902b095c1cbf64231668bb84c5 by Martijn Vels <mvels@google.com>:
Undo inline of small data copy in cord
This leads to a performance regression as the code is not inlined (absent hard FDO inputs), and there are no suitable tail call options.
PiperOrigin-RevId: 371332332
--
06dc64b833069efc7d18b11df607c8c22be690da by Martijn Vels <mvels@google.com>:
Add final instrumentation for Cordz and remove 'old' cordz logic.
This change instruments the last cord function for cordz. It removes the 'old' functions: set_tree, replace_tree, UpdateCordzStatistics and RecordMetrics.
PiperOrigin-RevId: 371219909
--
a5e0be538579c603052feec03e6d9910c43ea787 by Martijn Vels <mvels@google.com>:
Extend the life of CordRep* if inside a snapshot
If a snapshot (potentially) includes the current CordzInfo, we need to extent the lifetime of the CordRep*, as the snapshot 'point in time' observation of the cord should ideally be preserved.
PiperOrigin-RevId: 371146151
--
74d77a89774cd6c8ecdeebee0193b294a39383d6 by Martijn Vels <mvels@google.com>:
Instrument std::string consuming methods: ctor, operator=, Append and Prepend
This change moves the 'steal into CordRep' logic into a separate function so we can use it directly in the ctor, operator assign and append and prepend, allowing Cordz instrumentation with the proper method attributes.
The assign operator is implemented in AssignLargeString leaving the dispatch inlined in cord.h (which as a side effects also allows clean tail calls in the AssignLargeString method)
PiperOrigin-RevId: 371094756
--
b39effc45266b7ce2e7f96caa3b16cb6e3acc2dd by Martijn Vels <mvels@google.com>:
Add Cordz instrumentation to CordReader
PiperOrigin-RevId: 370990181
GitOrigin-RevId: 60b8e77be4bab1bbd3b4c3b70054879229634511
Change-Id: I96af62e6f1a643e8b1228ae01e6c84e33706bb05
4 years ago
|
|
|
|
|
|
|
// We can no longer be discovered: perform a fast path check if we are not
|
|
|
|
// listed on any delete queue, so we can directly delete this instance.
|
|
|
|
if (SafeToDelete()) {
|
|
|
|
UnsafeSetCordRep(nullptr);
|
|
|
|
delete this;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We are likely part of a snapshot, extend the life of the CordRep
|
|
|
|
{
|
|
|
|
absl::MutexLock lock(&mutex_);
|
|
|
|
if (rep_) CordRep::Ref(rep_);
|
|
|
|
}
|
|
|
|
CordzHandle::Delete(this);
|
|
|
|
}
|
|
|
|
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
void CordzInfo::Lock(MethodIdentifier method)
|
|
|
|
ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_) {
|
|
|
|
mutex_.Lock();
|
|
|
|
update_tracker_.LossyAdd(method);
|
|
|
|
assert(rep_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CordzInfo::Unlock() ABSL_UNLOCK_FUNCTION(mutex_) {
|
|
|
|
bool tracked = rep_ != nullptr;
|
|
|
|
mutex_.Unlock();
|
|
|
|
if (!tracked) {
|
|
|
|
Untrack();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
absl::Span<void* const> CordzInfo::GetStack() const {
|
|
|
|
return absl::MakeConstSpan(stack_, stack_depth_);
|
|
|
|
}
|
|
|
|
|
|
|
|
absl::Span<void* const> CordzInfo::GetParentStack() const {
|
|
|
|
return absl::MakeConstSpan(parent_stack_, parent_stack_depth_);
|
|
|
|
}
|
|
|
|
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
CordzStatistics CordzInfo::GetCordzStatistics() const {
|
|
|
|
CordzStatistics stats;
|
|
|
|
stats.method = method_;
|
|
|
|
stats.parent_method = parent_method_;
|
|
|
|
stats.update_tracker = update_tracker_;
|
|
|
|
if (CordRep* rep = RefCordRep()) {
|
|
|
|
stats.size = rep->length;
|
|
|
|
CordRepAnalyzer analyzer(stats);
|
|
|
|
analyzer.AnalyzeCordRep(rep);
|
|
|
|
CordRep::Unref(rep);
|
|
|
|
}
|
Export of internal Abseil changes
--
ac1df60490c9583e475e22de7adfc40023196fbf by Martijn Vels <mvels@google.com>:
Change Cord constructor(string_view) to explicit make_tree and Cordz tracking
This CL changes the ctor to use an easier to maintain model where Cord code explicitly invokes Cordz update or new / tree logic, which avoids the ambiguity of the 'branched' InlineRep::set_tree code. This removes the need to equip InlineRep with 'MethodIdentifier' or other necessary call info, and also is a cleaner model: InlineRep is carrying too much code now that should plainly sit in Cord, especially with all internal abstractions having moved to InlineData.
See child CL(s) for desired state
PiperOrigin-RevId: 369433619
--
b665af7f586e6c679a8b27d4f78d5a1d2b596058 by Abseil Team <absl-team@google.com>:
Rename the 'Compare' template type to 'LessThan', as the passed-in function is expected to act like operator<. It is worth avoiding confusion with std::compare, which returns an int (-1/0/1), as due to implicit casting this can lead to hard-to-spot bugs.
PiperOrigin-RevId: 369391118
--
c3c775269cad0f4982ec63f3616dd78bb9e52dca by Martijn Vels <mvels@google.com>:
Integrate CordzUpdateTracker into CordzInfo
PiperOrigin-RevId: 369348824
--
771d81ed357496c117179e1daec76eba5155932d by Martijn Vels <mvels@google.com>:
Replace mutex() with Lock() / Unlock() function
Mini design future tracking of CordzInfo sampled cords: CordzInfo holds a CordRep* reference without a reference count. Cord is responsible for synchronizing updates for sampled cords such that the CordRep* contained in CordzInfo is at all times valid. This is done by scoping Lock() and Unlock() calls around the code modifying the code of a sampled cord. For example (using the future CL CordzUpdateScope()):
CordzInfo* cordz_info = get_cordz_info();
CordzUpdateScope scope(cordz_info, CordzUpdateTracker::kRemovePrefix);
CordRep* rep = RemovePrefixImpl(root);
set_tree(rep);
if (cordz_info) {
cordz_info->SetCordRep(rep);
}
On CordzInfo::Unlock(), if the internal rep is null, the cord is no longer sampled, and CordzInfo will be deleted. Thus any update resulting in the Cord being inlined will automatically no longer be sampled.
PiperOrigin-RevId: 369338802
--
5563c12df04a1e965a03b50bdd032739c55c0706 by Martijn Vels <mvels@google.com>:
Add UpdateTracker to CordzStatistics
PiperOrigin-RevId: 369318178
--
6b4d8463722a3e55a3e8f6cb3741a41055e7f83e by Martijn Vels <mvels@google.com>:
Add kClear, kConstructor* and kUnknown values and fix typo
PiperOrigin-RevId: 369297163
--
041adcbc929789d6d53371a8236840fc350e1eeb by Derek Mauro <dmauro@google.com>:
Switch from malloc to operator new in pool_urbg.cc
so it can only fail by throwing/aborting
PiperOrigin-RevId: 369274087
--
5d97a5f43e3f2d02d0a5bbe586d93b5751812981 by Benjamin Barenblat <bbaren@google.com>:
Correct Thumb function bound computation in the symbolizer
On 32-bit ARM, all functions are aligned to multiples of two bytes, and
the lowest-order bit in a function’s address is ignored by the CPU when
computing branch targets. That bit is still present in instructions and
ELF symbol tables, though; it’s repurposed to indicate whether the
function contains ARM or Thumb code. If the symbolizer doesn’t ignore
that bit, it will believe Thumb functions have boundaries that are off
by one byte, so instruct the symbolizer to null out the lowest-order bit
after retrieving it from the symbol table.
PiperOrigin-RevId: 369254082
--
462bb307c6cc332c1e2c3adb5f0cad51804bf937 by Derek Mauro <dmauro@google.com>:
Add a check for malloc failure in pool_urbg.cc
GitHub #940
PiperOrigin-RevId: 369238100
GitOrigin-RevId: ac1df60490c9583e475e22de7adfc40023196fbf
Change-Id: Ic6ec91c62cd3a0031f6a75a43a83da959ece2d25
4 years ago
|
|
|
return stats;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace cord_internal
|
|
|
|
ABSL_NAMESPACE_END
|
|
|
|
} // namespace absl
|