Export of internal Abseil changes

--
f0456157cdc6cef6dbb5d2f99f9dc3ca0e213fab by Abseil Team <absl-team@google.com>:

Improve flag_benchmark reproducibility, test multiple threads

This adds multiple threads to the flags benchmark, and also uses some
linker magic to ensure that the defined flags are mapped to a consistent
alignment regardless of other code changes in the benchmark binary.

The benchmark performance in multiple threads is somewhat sensitive to
the alignment of the FlagImpl class, depending on whether the flag value
and the absl::Mutex are on the same cacheline or different ones. Making
all flags be cacheline-aligned would probably waste too much memory,
so this CL instead just makes the memory alignment consistent within the
tests.

PiperOrigin-RevId: 347536882

--
a019646d306b9497a1eba7efa5e2c4c651d9979d by Derek Mauro <dmauro@google.com>:

Fix other comments in node_hash_set.h

PiperOrigin-RevId: 347462975

--
66a4b39fe84a3e81935ad08ee76291df13d1d5e6 by Abseil Team <absl-team@google.com>:

Internal change

PiperOrigin-RevId: 347436244

--
52f4d18c2c4439d26428f64ac4de41e6183919ee by Mark Barolak <mbar@google.com>:

container: fix introduction for node_hash_set.h

Import of https://github.com/abseil/abseil-cpp/pull/861

PiperOrigin-RevId: 347432772
GitOrigin-RevId: f0456157cdc6cef6dbb5d2f99f9dc3ca0e213fab
Change-Id: I629f27e5b9584d92b0a42284c1acf708779bad3f
pull/866/head
Abseil Team 4 years ago committed by Mark Barolak
parent 52acfe6fc6
commit 68f1ad9325
  1. 30
      absl/container/node_hash_set.h
  2. 4
      absl/flags/BUILD.bazel
  3. 13
      absl/flags/flag_benchmark.cc
  4. 13
      absl/flags/flag_benchmark.lds
  5. 1
      absl/strings/cord.cc

@ -18,7 +18,7 @@
//
// An `absl::node_hash_set<T>` is an unordered associative container designed to
// be a more efficient replacement for `std::unordered_set`. Like
// `unordered_set`, search, insertion, and deletion of map elements can be done
// `unordered_set`, search, insertion, and deletion of set elements can be done
// as an `O(1)` operation. However, `node_hash_set` (and other unordered
// associative containers known as the collection of Abseil "Swiss tables")
// contain other optimizations that result in both memory and computation
@ -60,7 +60,7 @@ struct NodeHashSetPolicy;
// following notable differences:
//
// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
// `insert()`, provided that the map is provided a compatible heterogeneous
// `insert()`, provided that the set is provided a compatible heterogeneous
// hashing function and equality operator.
// * Contains a `capacity()` member function indicating the number of element
// slots (open, deleted, and empty) within the hash set.
@ -76,13 +76,13 @@ struct NodeHashSetPolicy;
// Example:
//
// // Create a node hash set of three strings
// absl::node_hash_map<std::string, std::string> ducks =
// absl::node_hash_set<std::string> ducks =
// {"huey", "dewey", "louie"};
//
// // Insert a new element into the node hash map
// ducks.insert("donald"};
// // Insert a new element into the node hash set
// ducks.insert("donald");
//
// // Force a rehash of the node hash map
// // Force a rehash of the node hash set
// ducks.rehash(0);
//
// // See if "dewey" is present
@ -100,7 +100,7 @@ class node_hash_set
public:
// Constructors and Assignment Operators
//
// A node_hash_set supports the same overload set as `std::unordered_map`
// A node_hash_set supports the same overload set as `std::unordered_set`
// for construction and assignment:
//
// * Default constructor
@ -167,7 +167,7 @@ class node_hash_set
// available within the `node_hash_set`.
//
// NOTE: this member function is particular to `absl::node_hash_set` and is
// not provided in the `std::unordered_map` API.
// not provided in the `std::unordered_set` API.
using Base::capacity;
// node_hash_set::empty()
@ -208,7 +208,7 @@ class node_hash_set
// `void`.
//
// NOTE: this return behavior is different than that of STL containers in
// general and `std::unordered_map` in particular.
// general and `std::unordered_set` in particular.
//
// iterator erase(const_iterator first, const_iterator last):
//
@ -314,7 +314,7 @@ class node_hash_set
// node_hash_set::merge()
//
// Extracts elements from a given `source` flat hash map into this
// Extracts elements from a given `source` node hash set into this
// `node_hash_set`. If the destination `node_hash_set` already contains an
// element with an equivalent key, that element is not extracted.
using Base::merge;
@ -322,15 +322,15 @@ class node_hash_set
// node_hash_set::swap(node_hash_set& other)
//
// Exchanges the contents of this `node_hash_set` with those of the `other`
// flat hash map, avoiding invocation of any move, copy, or swap operations on
// node hash set, avoiding invocation of any move, copy, or swap operations on
// individual elements.
//
// All iterators and references on the `node_hash_set` remain valid, excepting
// for the past-the-end iterator, which is invalidated.
//
// `swap()` requires that the flat hash set's hashing and key equivalence
// `swap()` requires that the node hash set's hashing and key equivalence
// functions be Swappable, and are exchaged using unqualified calls to
// non-member `swap()`. If the map's allocator has
// non-member `swap()`. If the set's allocator has
// `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
// set to `true`, the allocators are also exchanged using an unqualified call
// to non-member `swap()`; otherwise, the allocators are not swapped.
@ -385,14 +385,14 @@ class node_hash_set
// node_hash_set::bucket_count()
//
// Returns the number of "buckets" within the `node_hash_set`. Note that
// because a flat hash map contains all elements within its internal storage,
// because a node hash set contains all elements within its internal storage,
// this value simply equals the current capacity of the `node_hash_set`.
using Base::bucket_count;
// node_hash_set::load_factor()
//
// Returns the current load factor of the `node_hash_set` (the average number
// of slots occupied with a value within the hash map).
// of slots occupied with a value within the hash set).
using Base::load_factor;
// node_hash_set::max_load_factor()

@ -376,9 +376,13 @@ cc_binary(
"flag_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = select({
"//conditions:default": [],
}) + ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
"flag_benchmark.lds",
":flag",
":marshalling",
":parse",

@ -103,8 +103,17 @@ std::string AbslUnparseFlag(const UDT&) { return ""; }
#define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, "");
#if defined(__clang__) && defined(__linux__)
// Force the flags used for benchmarks into a separate ELF section.
// This ensures that, even when other parts of the code might change size,
// the layout of the flags across cachelines is kept constant. This makes
// benchmark results more reproducible across unrelated code changes.
#pragma clang section data = ".benchmark_flags"
#endif
BENCHMARKED_TYPES(FLAG_DEF)
#if defined(__clang__) && defined(__linux__)
#pragma clang section data = ""
#endif
// Register thousands of flags to bloat up the size of the registry.
// This mimics real life production binaries.
#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
@ -130,7 +139,7 @@ namespace {
benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \
} \
} \
BENCHMARK(BM_GetFlag_##T);
BENCHMARK(BM_GetFlag_##T)->ThreadRange(1, 16);
BENCHMARKED_TYPES(BM_GetFlag)

@ -0,0 +1,13 @@
/* This linker script forces the flags used by flags_benchmark
* into a separate page-aligned section. This isn't necessary for
* correctness but ensures that the benchmark results are more
* reproducible across unrelated code changes.
*/
SECTIONS {
.benchmark_flags : {
. = ALIGN(0x1000);
* (.benchmark_flags);
}
}
INSERT AFTER .data

@ -58,6 +58,7 @@ using ::absl::cord_internal::kMaxFlatLength;
using ::absl::cord_internal::CONCAT;
using ::absl::cord_internal::EXTERNAL;
using ::absl::cord_internal::FLAT;
using ::absl::cord_internal::RING;
using ::absl::cord_internal::SUBSTRING;
using ::absl::cord_internal::kInlinedVectorSize;

Loading…
Cancel
Save