mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Export of internal Abseil changes
-- f9476c95cf7625d7b0fc4661f253b0aac4341044 by Abseil Team <absl-team@google.com>: Add a test to verify that the new checksum field in Hashtablez is calculated PiperOrigin-RevId: 356744293 -- ff8a3612463000e8c3d451e50367a3c65cb6cf21 by Abseil Team <absl-team@google.com>: Remove the implied support comment for port.h, attributes.h, and integral_types.h's C compatibility from the header documentations. Abseil-cpp is a C++ library; this brings port.h, attributes.h, and integral_types.h, into our stance for the rest of Abseil (aka, no assurance of C compatibility) There is no guarantee that future changes to port.h, attributes.h, and integral_types.h, and their dependencies, will remain compatible with C, even for macros and definitions that currently are. PiperOrigin-RevId: 356727505 -- be62292016381deee628dbb3f36cb6009bcc0282 by Abseil Team <absl-team@google.com>: internal change PiperOrigin-RevId: 356608125 -- 13b35f17171df3d6853ea7088797b3be611505fc by Evan Brown <ezb@google.com>: Clarify the comments for CapacityToGrowth/GrowthToLowerboundCapacity methods to specify the intent that capacity should equal growth when `capacity+1 < kWidth`. Also add testing for this behavior. PiperOrigin-RevId: 356579041 GitOrigin-RevId: f9476c95cf7625d7b0fc4661f253b0aac4341044 Change-Id: Iadd094d109b4869998f2427319ef66d1cf1e8eff
This commit is contained in:
@@ -18,8 +18,6 @@
|
||||
// These macros are used within Abseil and allow the compiler to optimize, where
|
||||
// applicable, certain function calls.
|
||||
//
|
||||
// This file is used for both C and C++!
|
||||
//
|
||||
// Most macros here are exposing GCC or Clang features, and are stubbed out for
|
||||
// other compilers.
|
||||
//
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
//
|
||||
// This files is a forwarding header for other headers containing various
|
||||
// portability macros and functions.
|
||||
// This file is used for both C and C++!
|
||||
|
||||
#ifndef ABSL_BASE_PORT_H_
|
||||
#define ABSL_BASE_PORT_H_
|
||||
|
||||
@@ -468,8 +468,16 @@ inline size_t NormalizeCapacity(size_t n) {
|
||||
return n ? ~size_t{} >> countl_zero(n) : 1;
|
||||
}
|
||||
|
||||
// We use 7/8th as maximum load factor.
|
||||
// For 16-wide groups, that gives an average of two empty slots per group.
|
||||
// General notes on capacity/growth methods below:
|
||||
// - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
|
||||
// average of two empty slots per group.
|
||||
// - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
|
||||
// - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
|
||||
// never need to probe (the whole table fits in one group) so we don't need a
|
||||
// load factor less than 1.
|
||||
|
||||
// Given `capacity` of the table, returns the size (i.e. number of full slots)
|
||||
// at which we should grow the capacity.
|
||||
inline size_t CapacityToGrowth(size_t capacity) {
|
||||
assert(IsValidCapacity(capacity));
|
||||
// `capacity*7/8`
|
||||
@@ -480,7 +488,7 @@ inline size_t CapacityToGrowth(size_t capacity) {
|
||||
return capacity - capacity / 8;
|
||||
}
|
||||
// From desired "growth" to a lowerbound of the necessary capacity.
|
||||
// Might not be a valid one and required NormalizeCapacity().
|
||||
// Might not be a valid one and requires NormalizeCapacity().
|
||||
inline size_t GrowthToLowerboundCapacity(size_t growth) {
|
||||
// `growth*8/7`
|
||||
if (Group::kWidth == 8 && growth == 7) {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "absl/container/internal/raw_hash_set.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
@@ -22,6 +23,8 @@
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -48,11 +51,10 @@ struct RawHashSetTestOnlyAccess {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::DoubleNear;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::Ge;
|
||||
using ::testing::Lt;
|
||||
using ::testing::Optional;
|
||||
using ::testing::Pair;
|
||||
using ::testing::UnorderedElementsAre;
|
||||
|
||||
@@ -75,8 +77,14 @@ TEST(Util, GrowthAndCapacity) {
|
||||
for (size_t growth = 0; growth < 10000; ++growth) {
|
||||
SCOPED_TRACE(growth);
|
||||
size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
|
||||
// The capacity is large enough for `growth`
|
||||
// The capacity is large enough for `growth`.
|
||||
EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
|
||||
// For (capacity+1) < kWidth, growth should equal capacity.
|
||||
if (capacity + 1 < Group::kWidth) {
|
||||
EXPECT_THAT(CapacityToGrowth(capacity), Eq(capacity));
|
||||
} else {
|
||||
EXPECT_THAT(CapacityToGrowth(capacity), Lt(capacity));
|
||||
}
|
||||
if (growth != 0 && capacity > 1) {
|
||||
// There is no smaller capacity that works.
|
||||
EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth));
|
||||
@@ -1875,18 +1883,34 @@ TEST(RawHashSamplerTest, Sample) {
|
||||
|
||||
auto& sampler = HashtablezSampler::Global();
|
||||
size_t start_size = 0;
|
||||
start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
|
||||
std::unordered_set<const HashtablezInfo*> preexisting_info;
|
||||
start_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
||||
preexisting_info.insert(&info);
|
||||
++start_size;
|
||||
});
|
||||
|
||||
std::vector<IntTable> tables;
|
||||
for (int i = 0; i < 1000000; ++i) {
|
||||
tables.emplace_back();
|
||||
tables.back().insert(1);
|
||||
tables.back().insert(i % 5);
|
||||
}
|
||||
size_t end_size = 0;
|
||||
end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
|
||||
std::unordered_map<size_t, int> observed_checksums;
|
||||
end_size += sampler.Iterate([&](const HashtablezInfo& info) {
|
||||
if (preexisting_info.count(&info) == 0) {
|
||||
observed_checksums[info.hashes_bitwise_xor.load(
|
||||
std::memory_order_relaxed)]++;
|
||||
}
|
||||
++end_size;
|
||||
});
|
||||
|
||||
EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
|
||||
0.01, 0.005);
|
||||
EXPECT_EQ(observed_checksums.size(), 5);
|
||||
for (const auto& [_, count] : observed_checksums) {
|
||||
EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.2, 0.05);
|
||||
}
|
||||
}
|
||||
#endif // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
|
||||
|
||||
|
||||
@@ -460,5 +460,4 @@ TEST(Status, Swap) {
|
||||
test_swap(no_payload, with_payload);
|
||||
test_swap(with_payload, no_payload);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user