Roll abseil_revision b2dc72c17a..de71511109
Change Log:
https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+log/b2dc72c17a..de71511109
Full diff:
https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/b2dc72c17a..de71511109
Bug: None
Change-Id: Ic3cf2a0b7e9559867f8694142beddae65596dc49
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3173136
Reviewed-by: Danil Chapovalov <danilchap@chromium.org>
Commit-Queue: Mirko Bonadei <mbonadei@chromium.org>
Cr-Commit-Position: refs/heads/main@{#923780}
NOKEYCHECK=True
GitOrigin-RevId: 2fc881511cfa81cc144ea5d3bb169d568c01173c
diff --git a/README.chromium b/README.chromium
index 0c6a6a8..4c4ca86 100644
--- a/README.chromium
+++ b/README.chromium
@@ -4,7 +4,7 @@
License: Apache 2.0
License File: LICENSE
Version: 0
-Revision: b2dc72c17ac663885b62334d334da9f8970543b5
+Revision: de71511109d967000e68baedb75de104adb2b778
Security Critical: yes
Description:
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index ca03d9b..4b13370 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -68,6 +68,7 @@
hashes_bitwise_or.store(0, std::memory_order_relaxed);
hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);
hashes_bitwise_xor.store(0, std::memory_order_relaxed);
+ max_reserve.store(0, std::memory_order_relaxed);
create_time = absl::Now();
// The inliner makes hardcoded skip_count difficult (especially when combined
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index d86207f..812118e 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -80,6 +80,7 @@
std::atomic<size_t> hashes_bitwise_or;
std::atomic<size_t> hashes_bitwise_and;
std::atomic<size_t> hashes_bitwise_xor;
+ std::atomic<size_t> max_reserve;
// All of the fields below are set by `PrepareForSampling`, they must not be
// mutated in `Record*` functions. They are logically `const` in that sense.
@@ -107,6 +108,18 @@
std::memory_order_relaxed);
}
+inline void RecordReservationSlow(HashtablezInfo* info,
+ size_t target_capacity) {
+ info->max_reserve.store(
+ (std::max)(info->max_reserve.load(std::memory_order_relaxed),
+ target_capacity),
+ std::memory_order_relaxed);
+}
+
+inline void RecordClearedReservationSlow(HashtablezInfo* info) {
+ info->max_reserve.store(0, std::memory_order_relaxed);
+}
+
inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
size_t capacity) {
info->size.store(size, std::memory_order_relaxed);
@@ -170,6 +183,16 @@
RecordRehashSlow(info_, total_probe_length);
}
+ inline void RecordReservation(size_t target_capacity) {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordReservationSlow(info_, target_capacity);
+ }
+
+ inline void RecordClearedReservation() {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordClearedReservationSlow(info_);
+ }
+
inline void RecordInsert(size_t hash, size_t distance_from_desired) {
if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
RecordInsertSlow(info_, hash, distance_from_desired);
@@ -199,6 +222,8 @@
inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
inline void RecordRehash(size_t /*total_probe_length*/) {}
+ inline void RecordReservation(size_t /*target_capacity*/) {}
+ inline void RecordClearedReservation() {}
inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
inline void RecordErase() {}
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 53fcfe6..f053c19 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -91,6 +91,7 @@
EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
EXPECT_EQ(info.hashes_bitwise_xor.load(), 0);
+ EXPECT_EQ(info.max_reserve.load(), 0);
EXPECT_GE(info.create_time, test_start);
info.capacity.store(1, std::memory_order_relaxed);
@@ -101,6 +102,7 @@
info.hashes_bitwise_or.store(1, std::memory_order_relaxed);
info.hashes_bitwise_and.store(1, std::memory_order_relaxed);
info.hashes_bitwise_xor.store(1, std::memory_order_relaxed);
+ info.max_reserve.store(1, std::memory_order_relaxed);
info.create_time = test_start - absl::Hours(20);
info.PrepareForSampling();
@@ -113,6 +115,7 @@
EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
EXPECT_EQ(info.hashes_bitwise_xor.load(), 0);
+ EXPECT_EQ(info.max_reserve.load(), 0);
EXPECT_GE(info.create_time, test_start);
}
@@ -187,6 +190,22 @@
EXPECT_EQ(info.num_rehashes.load(), 1);
}
+TEST(HashtablezInfoTest, RecordReservation) {
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+ RecordReservationSlow(&info, 3);
+ EXPECT_EQ(info.max_reserve.load(), 3);
+
+ RecordReservationSlow(&info, 2);
+ // High watermark does not change
+ EXPECT_EQ(info.max_reserve.load(), 3);
+
+ RecordReservationSlow(&info, 10);
+ // High watermark does change
+ EXPECT_EQ(info.max_reserve.load(), 10);
+}
+
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
TEST(HashtablezSamplerTest, SmallSampleParameter) {
SetHashtablezEnabled(true);
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index f4919ce..212052e 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1069,6 +1069,8 @@
// past that we simply deallocate the array.
if (capacity_ > 127) {
destroy_slots();
+
+ infoz().RecordClearedReservation();
} else if (capacity_) {
for (size_t i = 0; i != capacity_; ++i) {
if (IsFull(ctrl_[i])) {
@@ -1382,14 +1384,20 @@
if (n == 0 && size_ == 0) {
destroy_slots();
infoz().RecordStorageChanged(0, 0);
+ infoz().RecordClearedReservation();
return;
}
+
// bitor is a faster way of doing `max` here. We will round up to the next
// power-of-2-minus-1, so bitor is good enough.
auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
// n == 0 unconditionally rehashes as per the standard.
if (n == 0 || m > capacity_) {
resize(m);
+
+ // This is after resize, to ensure that we have completed the allocation
+ // and have potentially sampled the hashtable.
+ infoz().RecordReservation(n);
}
}
@@ -1397,6 +1405,10 @@
if (n > size() + growth_left()) {
size_t m = GrowthToLowerboundCapacity(n);
resize(NormalizeCapacity(m));
+
+ // This is after resize, to ensure that we have completed the allocation
+ // and have potentially sampled the hashtable.
+ infoz().RecordReservation(n);
}
}
@@ -1638,6 +1650,7 @@
PolicyTraits::destroy(&alloc_ref(), slots_ + i);
}
}
+
// Unpoison before returning the memory to the allocator.
SanitizerUnpoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
Deallocate<alignof(slot_type)>(
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 4012a3a..b46c492 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -2049,15 +2049,31 @@
std::vector<IntTable> tables;
for (int i = 0; i < 1000000; ++i) {
tables.emplace_back();
+
+ const bool do_reserve = (i % 10 > 5);
+ const bool do_rehash = !do_reserve && (i % 10 > 0);
+
+ if (do_reserve) {
+ // Don't reserve on all tables.
+ tables.back().reserve(10 * (i % 10));
+ }
+
tables.back().insert(1);
tables.back().insert(i % 5);
+
+ if (do_rehash) {
+ // Rehash some other tables.
+ tables.back().rehash(10 * (i % 10));
+ }
}
size_t end_size = 0;
std::unordered_map<size_t, int> observed_checksums;
+ std::unordered_map<ssize_t, int> reservations;
end_size += sampler.Iterate([&](const HashtablezInfo& info) {
if (preexisting_info.count(&info) == 0) {
observed_checksums[info.hashes_bitwise_xor.load(
std::memory_order_relaxed)]++;
+ reservations[info.max_reserve.load(std::memory_order_relaxed)]++;
}
++end_size;
});
@@ -2068,6 +2084,15 @@
for (const auto& [_, count] : observed_checksums) {
EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.2, 0.05);
}
+
+ EXPECT_EQ(reservations.size(), 10);
+ for (const auto& [reservation, count] : reservations) {
+ EXPECT_GE(reservation, 0);
+ EXPECT_LT(reservation, 100);
+
+ EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.1, 0.05)
+ << reservation;
+ }
}
#endif // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
diff --git a/absl/profiling/internal/sample_recorder.h b/absl/profiling/internal/sample_recorder.h
index a257ea5..5e04a9c 100644
--- a/absl/profiling/internal/sample_recorder.h
+++ b/absl/profiling/internal/sample_recorder.h
@@ -41,7 +41,6 @@
// samples maintained by the SampleRecorder. Type T defines the sampled data.
template <typename T>
struct Sample {
- public:
// Guards the ability to restore the sample to a pristine state. This
// prevents races with sampling and resurrecting an object.
absl::Mutex init_mu;
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 115705a..29af978 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -708,8 +708,8 @@
if (btree_enabled()) {
// TODO(b/192061034): keep legacy 10% growth rate: consider other rates.
rep = ForceBtree(rep);
- const size_t alloc_hint = (std::min)(kMaxFlatLength, rep->length / 10);
- rep = CordRepBtree::Append(rep->btree(), src, alloc_hint);
+ const size_t min_growth = std::max<size_t>(rep->length / 10, src.size());
+ rep = CordRepBtree::Append(rep->btree(), src, min_growth - src.size());
} else {
// Use new block(s) for any remaining bytes that were not handled above.
// Alloc extra memory only if the right child of the root of the new tree
diff --git a/absl/strings/internal/cord_rep_btree.cc b/absl/strings/internal/cord_rep_btree.cc
index 8fe589f..6d53ab6 100644
--- a/absl/strings/internal/cord_rep_btree.cc
+++ b/absl/strings/internal/cord_rep_btree.cc
@@ -96,7 +96,8 @@
maybe_dump_data(rep);
DumpAll(substring->child, include_contents, stream, depth + 1);
} else if (rep->tag >= FLAT) {
- stream << "Flat, len = " << rep->length;
+ stream << "Flat, len = " << rep->length
+ << ", cap = " << rep->flat()->Capacity();
maybe_dump_data(rep);
} else if (rep->tag == EXTERNAL) {
stream << "Extn, len = " << rep->length;
diff --git a/absl/time/time.h b/absl/time/time.h
index e9cbce8..5abd815 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -480,8 +480,9 @@
// ToInt64Hours()
//
// Helper functions that convert a Duration to an integral count of the
-// indicated unit. These functions are shorthand for the `IDivDuration()`
-// function above; see its documentation for details about overflow, etc.
+// indicated unit. These return the same results as the `IDivDuration()`
+// function, though they usually do so more efficiently; see the
+// documentation of `IDivDuration()` for details about overflow, etc.
//
// Example:
//