Export of internal Abseil changes
-- 91ca367a7548270155721bdda74611aeea2a2153 by Abseil Team <absl-team@google.com>: Replace the only usage of btree_node::swap with simpler logic using transfers and delete btree_node::swap. Add a benchmark for constructing small containers. PiperOrigin-RevId: 301169874 -- ff9d73a7125b7f8ab5733cda877204dfbfac138e by Derek Mauro <dmauro@google.com>: Ensure ABSL_CXX_STANDARD is set. Fixes #640 PiperOrigin-RevId: 301160106 -- 14ca0beee8c109e532134e7e9da7b072da1bf911 by Abseil Team <absl-team@google.com>: Rollback the change to make Cord iterators a fixed size. That change increased the iterator size, which can cause a deep recursion call to hit the stack memory limit, in turn causing a signal 11 failure. PiperOrigin-RevId: 301084915 -- 619e3cd9e56408bdb8b3b5a1e08dda1e95242264 by Matthew Brown <matthewbr@google.com>: Internal Change PiperOrigin-RevId: 300832828 -- 64f8d62ab4c4c78077dbe85a9595a8eeb6d16608 by Gennadiy Rozental <rogeeff@google.com>: Fix for empty braces support. We will call proper aggregate construction in case when {} is used as default value. In other words instead of "new T", we'll call "new T{}". PiperOrigin-RevId: 300715686 -- db3f65594d6db8b104b01262f884dff465b696ef by Abseil Team <absl-team@google.com>: Emscripten supports thread-local storage nowadays. PiperOrigin-RevId: 300675185 GitOrigin-RevId: 91ca367a7548270155721bdda74611aeea2a2153 Change-Id: I3344f745f9c3fc78775532b1808442fabd98e34a
This commit is contained in:
parent
c6954897f7
commit
7853a7586c
12 changed files with 254 additions and 283 deletions
|
@ -134,6 +134,27 @@ void BM_InsertEnd(benchmark::State& state) {
|
|||
}
|
||||
}
|
||||
|
||||
// Benchmark inserting the first few elements in a container. In b-tree, this is
|
||||
// when the root node grows.
|
||||
template <typename T>
|
||||
void BM_InsertSmall(benchmark::State& state) {
|
||||
using V = typename remove_pair_const<typename T::value_type>::type;
|
||||
|
||||
const int kSize = 8;
|
||||
std::vector<V> values = GenerateValues<V>(kSize);
|
||||
T container;
|
||||
|
||||
while (state.KeepRunningBatch(kSize)) {
|
||||
for (int i = 0; i < kSize; ++i) {
|
||||
benchmark::DoNotOptimize(container.insert(values[i]));
|
||||
}
|
||||
state.PauseTiming();
|
||||
// Do not measure the time it takes to clear the container.
|
||||
container.clear();
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void BM_LookupImpl(benchmark::State& state, bool sorted) {
|
||||
using V = typename remove_pair_const<typename T::value_type>::type;
|
||||
|
@ -493,6 +514,7 @@ BTREE_TYPES(Time);
|
|||
MY_BENCHMARK4(type, Insert); \
|
||||
MY_BENCHMARK4(type, InsertSorted); \
|
||||
MY_BENCHMARK4(type, InsertEnd); \
|
||||
MY_BENCHMARK4(type, InsertSmall); \
|
||||
MY_BENCHMARK4(type, Lookup); \
|
||||
MY_BENCHMARK4(type, FullLookup); \
|
||||
MY_BENCHMARK4(type, Delete); \
|
||||
|
|
|
@ -776,9 +776,6 @@ class btree_node {
|
|||
// delimiting key in the parent node onto itself.
|
||||
void merge(btree_node *src, allocator_type *alloc);
|
||||
|
||||
// Swaps the contents of `this` and `other`.
|
||||
void swap(btree_node *other, allocator_type *alloc);
|
||||
|
||||
// Node allocation/deletion routines.
|
||||
void init_leaf(btree_node *parent, int max_count) {
|
||||
set_parent(parent);
|
||||
|
@ -820,6 +817,14 @@ class btree_node {
|
|||
absl::container_internal::SanitizerPoisonObject(slot(i));
|
||||
}
|
||||
|
||||
// Transfers value from slot `src_i` in `src` to slot `dest_i` in `this`.
|
||||
void transfer(const size_type dest_i, const size_type src_i, btree_node *src,
|
||||
allocator_type *alloc) {
|
||||
absl::container_internal::SanitizerUnpoisonObject(slot(dest_i));
|
||||
params_type::transfer(alloc, slot(dest_i), src->slot(src_i));
|
||||
absl::container_internal::SanitizerPoisonObject(src->slot(src_i));
|
||||
}
|
||||
|
||||
// Move n values starting at value i in this node into the values starting at
|
||||
// value j in dest_node.
|
||||
void uninitialized_move_n(const size_type n, const size_type i,
|
||||
|
@ -1752,54 +1757,6 @@ void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
|
|||
parent()->remove_value(position(), alloc);
|
||||
}
|
||||
|
||||
template <typename P>
|
||||
void btree_node<P>::swap(btree_node *other, allocator_type *alloc) {
|
||||
using std::swap;
|
||||
assert(leaf() == other->leaf());
|
||||
|
||||
// Determine which is the smaller/larger node.
|
||||
btree_node *smaller = this, *larger = other;
|
||||
if (smaller->count() > larger->count()) {
|
||||
swap(smaller, larger);
|
||||
}
|
||||
|
||||
// Swap the values.
|
||||
for (slot_type *a = smaller->start_slot(), *b = larger->start_slot(),
|
||||
*end = smaller->finish_slot();
|
||||
a != end; ++a, ++b) {
|
||||
params_type::swap(alloc, a, b);
|
||||
}
|
||||
|
||||
// Move values that can't be swapped.
|
||||
const size_type to_move = larger->count() - smaller->count();
|
||||
larger->uninitialized_move_n(to_move, smaller->finish(), smaller->finish(),
|
||||
smaller, alloc);
|
||||
larger->value_destroy_n(smaller->finish(), to_move, alloc);
|
||||
|
||||
if (!leaf()) {
|
||||
// Swap the child pointers.
|
||||
std::swap_ranges(&smaller->mutable_child(smaller->start()),
|
||||
&smaller->mutable_child(smaller->finish() + 1),
|
||||
&larger->mutable_child(larger->start()));
|
||||
// Update swapped children's parent pointers.
|
||||
int i = smaller->start();
|
||||
int j = larger->start();
|
||||
for (; i <= smaller->finish(); ++i, ++j) {
|
||||
smaller->child(i)->set_parent(smaller);
|
||||
larger->child(j)->set_parent(larger);
|
||||
}
|
||||
// Move the child pointers that couldn't be swapped.
|
||||
for (; j <= larger->finish(); ++i, ++j) {
|
||||
smaller->init_child(i, larger->child(j));
|
||||
larger->clear_child(j);
|
||||
}
|
||||
}
|
||||
|
||||
// Swap the `finish`s.
|
||||
// TODO(ezb): with floating storage, will also need to swap starts.
|
||||
swap(mutable_finish(), other->mutable_finish());
|
||||
}
|
||||
|
||||
////
|
||||
// btree_iterator methods
|
||||
template <typename N, typename R, typename P>
|
||||
|
@ -2492,6 +2449,7 @@ inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
|
|||
++iter.position;
|
||||
}
|
||||
const int max_count = iter.node->max_count();
|
||||
allocator_type *alloc = mutable_allocator();
|
||||
if (iter.node->count() == max_count) {
|
||||
// Make room in the leaf for the new item.
|
||||
if (max_count < kNodeValues) {
|
||||
|
@ -2500,15 +2458,21 @@ inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
|
|||
assert(iter.node == root());
|
||||
iter.node =
|
||||
new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count));
|
||||
iter.node->swap(root(), mutable_allocator());
|
||||
delete_leaf_node(root());
|
||||
mutable_root() = rightmost_ = iter.node;
|
||||
// Transfer the values from the old root to the new root.
|
||||
node_type *old_root = root();
|
||||
node_type *new_root = iter.node;
|
||||
for (int i = old_root->start(), f = old_root->finish(); i < f; ++i) {
|
||||
new_root->transfer(i, i, old_root, alloc);
|
||||
}
|
||||
new_root->set_finish(old_root->finish());
|
||||
old_root->set_finish(old_root->start());
|
||||
delete_leaf_node(old_root);
|
||||
mutable_root() = rightmost_ = new_root;
|
||||
} else {
|
||||
rebalance_or_split(&iter);
|
||||
}
|
||||
}
|
||||
iter.node->emplace_value(iter.position, mutable_allocator(),
|
||||
std::forward<Args>(args)...);
|
||||
iter.node->emplace_value(iter.position, alloc, std::forward<Args>(args)...);
|
||||
++size_;
|
||||
return iter;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue