diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 9a723e5..0ec8b92 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -83,6 +83,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/memory",
+        "//absl/random",
         "//absl/types:span",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 252b6b2..f3dd138 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -68,6 +68,7 @@
     absl::config
     absl::core_headers
     absl::memory
+    absl::random_random
     absl::span
     GTest::gmock_main
 )
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 85e3b11..cb06335 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -16,6 +16,7 @@
 
 #include <algorithm>
 #include <array>
+#include <cstddef>
 #include <functional>
 #include <initializer_list>
 #include <iterator>
@@ -35,6 +36,7 @@
 #include "absl/base/config.h"
 #include "absl/base/macros.h"
 #include "absl/memory/memory.h"
+#include "absl/random/random.h"
 #include "absl/types/span.h"
 
 namespace {
@@ -986,25 +988,16 @@
   EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5));
 }
 
-template <typename T>
-T RandomlySeededPrng() {
-  std::random_device rdev;
-  std::seed_seq::result_type data[T::state_size];
-  std::generate_n(data, T::state_size, std::ref(rdev));
-  std::seed_seq prng_seed(data, data + T::state_size);
-  return T(prng_seed);
-}
-
 TEST(MutatingTest, Shuffle) {
   std::vector<int> actual = {1, 2, 3, 4, 5};
-  absl::c_shuffle(actual, RandomlySeededPrng<std::mt19937_64>());
+  absl::c_shuffle(actual, absl::InsecureBitGen());
   EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5));
 }
 
 TEST(MutatingTest, Sample) {
   std::vector<int> actual;
   absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3,
-                 RandomlySeededPrng<std::mt19937_64>());
+                 absl::InsecureBitGen());
   EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5}));
   EXPECT_THAT(actual, SizeIs(3));
 }
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 91f930a..61e816f 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -494,6 +494,7 @@
         "//absl/base:no_destructor",
         "//absl/memory",
         "//absl/meta:type_traits",
+        "//absl/random",
         "//absl/strings",
     ],
 )
@@ -625,6 +626,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/profiling:sample_recorder",
+        "//absl/random",
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
@@ -785,6 +787,7 @@
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/numeric:int128",
+        "//absl/random",
         "//absl/strings",
         "//absl/types:optional",
         "@googletest//:gtest",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 70f78c4..d8cd7d0 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -543,6 +543,7 @@
     absl::memory
     absl::meta
     absl::no_destructor
+    absl::random_random
     absl::strings
   TESTONLY
 )
@@ -658,6 +659,7 @@
   DEPS
     absl::config
     absl::hashtablez_sampler
+    absl::random_random
     GTest::gmock_main
 )
 
@@ -824,6 +826,7 @@
     absl::node_hash_set
     absl::optional
     absl::prefetch
+    absl::random_random
     absl::raw_hash_set
     absl::strings
     absl::test_allocator
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index e89dfdb..be20e21 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -14,61 +14,39 @@
 
 #include "absl/container/internal/hash_generator_testing.h"
 
+#include <algorithm>
 #include <deque>
+#include <random>
+#include <string>
 
 #include "absl/base/no_destructor.h"
+#include "absl/random/random.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hash_internal {
-namespace {
-
-class RandomDeviceSeedSeq {
- public:
-  using result_type = typename std::random_device::result_type;
-
-  template <class Iterator>
-  void generate(Iterator start, Iterator end) {
-    while (start != end) {
-      *start = gen_();
-      ++start;
-    }
-  }
-
- private:
-  std::random_device gen_;
-};
-
-}  // namespace
-
-std::mt19937_64* GetSharedRng() {
-  static absl::NoDestructor<std::mt19937_64> rng([] {
-    RandomDeviceSeedSeq seed_seq;
-    return std::mt19937_64(seed_seq);
-  }());
-  return rng.get();
-}
 
 std::string Generator<std::string>::operator()() const {
+  absl::InsecureBitGen gen;
   // NOLINTNEXTLINE(runtime/int)
   std::uniform_int_distribution<short> chars(0x20, 0x7E);
   std::string res;
   res.resize(32);
-  std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetSharedRng()); });
+  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });
   return res;
 }
 
 absl::string_view Generator<absl::string_view>::operator()() const {
   static absl::NoDestructor<std::deque<std::string>> arena;
+  absl::InsecureBitGen gen;
   // NOLINTNEXTLINE(runtime/int)
   std::uniform_int_distribution<short> chars(0x20, 0x7E);
   arena->emplace_back();
   auto& res = arena->back();
   res.resize(32);
-  std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetSharedRng()); });
+  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });
   return res;
 }
 
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h
index 05be8ef..14c878e 100644
--- a/absl/container/internal/hash_generator_testing.h
+++ b/absl/container/internal/hash_generator_testing.h
@@ -23,7 +23,9 @@
 #include <algorithm>
 #include <cassert>
 #include <iosfwd>
+#include <memory>
 #include <random>
+#include <string>
 #include <tuple>
 #include <type_traits>
 #include <utility>
@@ -32,6 +34,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/random.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
@@ -48,8 +51,6 @@
 
 }  // namespace generator_internal
 
-std::mt19937_64* GetSharedRng();
-
 enum Enum : uint64_t {
   kEnumEmpty,
   kEnumDeleted,
@@ -69,29 +70,27 @@
 
 template <class T>
 struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {
-  T operator()() const {
-    std::uniform_int_distribution<T> dist;
-    return dist(*GetSharedRng());
-  }
+  T operator()() const { return dist(gen); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<T> dist;
 };
 
 template <>
 struct Generator<Enum> {
-  Enum operator()() const {
-    std::uniform_int_distribution<typename std::underlying_type<Enum>::type>
-        dist;
-    return static_cast<Enum>(dist(*GetSharedRng()));
-  }
+  Enum operator()() const { return static_cast<Enum>(dist(gen)); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<
+      typename std::underlying_type<Enum>::type>
+      dist;
 };
 
 template <>
 struct Generator<EnumClass> {
-  EnumClass operator()() const {
-    std::uniform_int_distribution<
-        typename std::underlying_type<EnumClass>::type>
-        dist;
-    return static_cast<EnumClass>(dist(*GetSharedRng()));
-  }
+  EnumClass operator()() const { return static_cast<EnumClass>(dist(gen)); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<
+      typename std::underlying_type<EnumClass>::type>
+      dist;
 };
 
 template <>
@@ -135,17 +134,17 @@
 
 template <class U>
 struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()),
-                                decltype(std::declval<U&>().value())>>
+                                 decltype(std::declval<U&>().value())>>
     : Generator<std::pair<
           typename std::decay<decltype(std::declval<U&>().key())>::type,
           typename std::decay<decltype(std::declval<U&>().value())>::type>> {};
 
 template <class Container>
-using GeneratedType = decltype(
-    std::declval<const Generator<
-        typename std::conditional<generator_internal::IsMap<Container>::value,
-                                  typename Container::value_type,
-                                  typename Container::key_type>::type>&>()());
+using GeneratedType =
+    decltype(std::declval<const Generator<typename std::conditional<
+                 generator_internal::IsMap<Container>::value,
+                 typename Container::value_type,
+                 typename Container::key_type>::type>&>()());
 
 // Naive wrapper that performs a linear search of previous values.
 // Beware this is O(SQR), which is reasonable for smaller kMaxValues.
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 24d3bc4..0de1e29 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/profiling/internal/sample_recorder.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/blocking_counter.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
@@ -439,8 +440,7 @@
     const size_t value_size = 13 + i % 5;
     pool.Schedule([&sampler, &stop, sampling_stride, elt_size, key_size,
                    value_size]() {
-      std::random_device rd;
-      std::mt19937 gen(rd());
+      absl::InsecureBitGen gen;
 
       std::vector<HashtablezInfo*> infoz;
       while (!stop.HasBeenNotified()) {
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index adba8b1..f66f486 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -32,7 +32,6 @@
 #include "absl/container/internal/raw_hash_set_resize_impl.h"
 #include "absl/functional/function_ref.h"
 #include "absl/hash/hash.h"
-#include "absl/numeric/bits.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -190,15 +189,8 @@
   return capacity < Group::kWidth - 1;
 }
 
-}  // namespace
-
-FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
-  return find_first_non_full_from_h1(common.control(), H1(hash, common.seed()),
-                                     common.capacity());
-}
-
-void IterateOverFullSlots(const CommonFields& c, size_t slot_size,
-                          absl::FunctionRef<void(const ctrl_t*, void*)> cb) {
+template <class Fn>
+void IterateOverFullSlotsImpl(const CommonFields& c, size_t slot_size, Fn cb) {
   const size_t cap = c.capacity();
   const ctrl_t* ctrl = c.control();
   void* slot = c.slot_array();
@@ -245,6 +237,8 @@
                          "hash table was modified unexpectedly");
 }
 
+}  // namespace
+
 void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
   ABSL_SWISSTABLE_ASSERT(ctrl[capacity] == ctrl_t::kSentinel);
   ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
@@ -256,6 +250,16 @@
   ctrl[capacity] = ctrl_t::kSentinel;
 }
 
+FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
+  return find_first_non_full_from_h1(common.control(), H1(hash, common.seed()),
+                                     common.capacity());
+}
+
+void IterateOverFullSlots(const CommonFields& c, size_t slot_size,
+                          absl::FunctionRef<void(const ctrl_t*, void*)> cb) {
+  IterateOverFullSlotsImpl(c, slot_size, cb);
+}
+
 namespace {
 
 void ResetGrowthLeft(GrowthInfo& growth_info, size_t capacity, size_t size) {
@@ -761,6 +765,7 @@
   if (has_infoz) {
     common.set_has_infoz();
     common.set_infoz(infoz);
+    infoz.RecordStorageChanged(common.size(), new_capacity);
   }
 }
 
@@ -1630,6 +1635,81 @@
   }
 }
 
+void Copy(CommonFields& common, const PolicyFunctions& policy,
+          const CommonFields& other,
+          absl::FunctionRef<void(void*, const void*)> copy_fn) {
+  const size_t size = other.size();
+  ABSL_SWISSTABLE_ASSERT(size > 0);
+  const size_t soo_capacity = policy.soo_capacity;
+  const size_t slot_size = policy.slot_size;
+  if (size <= soo_capacity) {
+    ABSL_SWISSTABLE_ASSERT(size == 1);
+    common.set_full_soo();
+    const void* other_slot =
+        other.capacity() <= soo_capacity
+            ? other.soo_data()
+            : SlotAddress(
+                  other.slot_array(),
+                  FindFirstFullSlot(0, other.capacity(), other.control()),
+                  slot_size);
+    copy_fn(common.soo_data(), other_slot);
+
+    if (policy.is_hashtablez_eligible && ShouldSampleNextTable()) {
+      GrowFullSooTableToNextCapacityForceSampling(common, policy);
+    }
+    return;
+  }
+
+  ReserveTableToFitNewSize(common, policy, size);
+  auto infoz = common.infoz();
+  ABSL_SWISSTABLE_ASSERT(other.capacity() > soo_capacity);
+  const size_t cap = common.capacity();
+  ABSL_SWISSTABLE_ASSERT(cap > soo_capacity);
+  // Note about single group tables:
+  // 1. It is correct to have any order of elements.
+  // 2. Order has to be non deterministic.
+  // 3. We are assigning elements with arbitrary `shift` starting from
+  //    `capacity + shift` position.
+  // 4. `shift` must be coprime with `capacity + 1` in order to be able to use
+  //     modular arithmetic to traverse all positions, instead of cycling
+  //     through a subset of positions. Odd numbers are coprime with any
+  //     `capacity + 1` (2^N).
+  size_t offset = cap;
+  const size_t shift = is_single_group(cap) ? (common.seed().seed() | 1) : 0;
+  const void* hash_fn = policy.hash_fn(common);
+  auto hasher = policy.hash_slot;
+  IterateOverFullSlotsImpl(
+      other, slot_size, [&](const ctrl_t* that_ctrl, void* that_slot) {
+        if (shift == 0) {
+          // Big tables case. Position must be searched via probing.
+          // The table is guaranteed to be empty, so we can do faster than
+          // a full `insert`.
+          const size_t hash = (*hasher)(hash_fn, that_slot);
+          FindInfo target = find_first_non_full(common, hash);
+          infoz.RecordInsert(hash, target.probe_length);
+          offset = target.offset;
+        } else {
+          // Small tables case. Next position is computed via shift.
+          offset = (offset + shift) & cap;
+        }
+        const h2_t h2 = static_cast<h2_t>(*that_ctrl);
+        // We rely on the hash not changing for small tables.
+        ABSL_SWISSTABLE_ASSERT(
+            H2((*hasher)(hash_fn, that_slot)) == h2 &&
+            "hash function value changed unexpectedly during the copy");
+        SetCtrl(common, offset, h2, slot_size);
+        copy_fn(SlotAddress(common.slot_array(), offset, slot_size), that_slot);
+        common.maybe_increment_generation_on_insert();
+      });
+  if (shift != 0) {
+    // On small table copy we do not record individual inserts.
+    // RecordInsert requires hash, but it is unknown for small tables.
+    infoz.RecordStorageChanged(size, cap);
+  }
+  common.increment_size(size);
+  common.growth_info().OverwriteManyEmptyAsFull(size);
+}
+
 void ReserveTableToFitNewSize(CommonFields& common,
                               const PolicyFunctions& policy, size_t new_size) {
   common.reset_reserved_growth(new_size);
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index b22f817..f8c0731 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1753,6 +1753,11 @@
 // Type erased version of raw_hash_set::rehash.
 void Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n);
 
+// Type erased version of copy constructor.
+void Copy(CommonFields& common, const PolicyFunctions& policy,
+          const CommonFields& other,
+          absl::FunctionRef<void(void*, const void*)> copy_fn);
+
 // Returns the optimal size for memcpy when transferring SOO slot.
 // Otherwise, returns the optimal size for memcpy SOO slot transfer
 // to SooSlotIndex().
@@ -2166,7 +2171,7 @@
       std::is_nothrow_default_constructible<key_equal>::value &&
       std::is_nothrow_default_constructible<allocator_type>::value) {}
 
-  ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
+  explicit raw_hash_set(
       size_t bucket_count, const hasher& hash = hasher(),
       const key_equal& eq = key_equal(),
       const allocator_type& alloc = allocator_type())
@@ -2278,73 +2283,17 @@
                                allocator_type(that.char_alloc_ref()))) {}
 
   raw_hash_set(const raw_hash_set& that, const allocator_type& a)
-      : raw_hash_set(SizeToCapacity(that.size()), that.hash_ref(),
-                     that.eq_ref(), a) {
+      : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {
     that.AssertNotDebugCapacity();
-    const size_t size = that.size();
-    if (size == 0) {
-      return;
-    }
-    // We don't use `that.is_soo()` here because `that` can have non-SOO
-    // capacity but have a size that fits into SOO capacity.
-    if (fits_in_soo(size)) {
-      ABSL_SWISSTABLE_ASSERT(size == 1);
-      common().set_full_soo();
-      emplace_at(soo_iterator(), *that.begin());
-      if (should_sample_soo()) {
-        GrowFullSooTableToNextCapacityForceSampling(common(),
-                                                    GetPolicyFunctions());
-      }
-      return;
-    }
-    ABSL_SWISSTABLE_ASSERT(!that.is_soo());
-    const size_t cap = capacity();
-    // Note about single group tables:
-    // 1. It is correct to have any order of elements.
-    // 2. Order has to be non deterministic.
-    // 3. We are assigning elements with arbitrary `shift` starting from
-    //    `capacity + shift` position.
-    // 4. `shift` must be coprime with `capacity + 1` in order to be able to use
-    //     modular arithmetic to traverse all positions, instead if cycling
-    //     through a subset of positions. Odd numbers are coprime with any
-    //     `capacity + 1` (2^N).
-    size_t offset = cap;
-    const size_t shift =
-        is_single_group(cap) ? (common().seed().seed() | 1) : 0;
-    IterateOverFullSlots(
-        that.common(), sizeof(slot_type),
-        [&](const ctrl_t* that_ctrl, void* that_slot_void) {
-          slot_type* that_slot = static_cast<slot_type*>(that_slot_void);
-          if (shift == 0) {
-            // Big tables case. Position must be searched via probing.
-            // The table is guaranteed to be empty, so we can do faster than
-            // a full `insert`.
-            const size_t hash = PolicyTraits::apply(
-                HashElement{hash_ref()}, PolicyTraits::element(that_slot));
-            FindInfo target = find_first_non_full(common(), hash);
-            infoz().RecordInsert(hash, target.probe_length);
-            offset = target.offset;
-          } else {
-            // Small tables case. Next position is computed via shift.
-            offset = (offset + shift) & cap;
-          }
-          const h2_t h2 = static_cast<h2_t>(*that_ctrl);
-          ABSL_SWISSTABLE_ASSERT(  // We rely that hash is not changed for small
-                                   // tables.
-              H2(PolicyTraits::apply(HashElement{hash_ref()},
-                                     PolicyTraits::element(that_slot))) == h2 &&
-              "hash function value changed unexpectedly during the copy");
-          SetCtrl(common(), offset, h2, sizeof(slot_type));
-          emplace_at(iterator_at(offset), PolicyTraits::element(that_slot));
-          common().maybe_increment_generation_on_insert();
-        });
-    if (shift != 0) {
-      // On small table copy we do not record individual inserts.
-      // RecordInsert requires hash, but it is unknown for small tables.
-      infoz().RecordStorageChanged(size, cap);
-    }
-    common().increment_size(size);
-    growth_info().OverwriteManyEmptyAsFull(size);
+    if (that.empty()) return;
+    Copy(common(), GetPolicyFunctions(), that.common(),
+         [this](void* dst, const void* src) {
+           // TODO(b/413598253): type erase for trivially copyable types via
+           // PolicyTraits.
+           construct(to_slot(dst),
+                     PolicyTraits::element(
+                         static_cast<slot_type*>(const_cast<void*>(src))));
+         });
   }
 
   ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
@@ -2414,7 +2363,7 @@
 
   iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
     if (ABSL_PREDICT_FALSE(empty())) return end();
-    if (is_soo()) return soo_iterator();
+    if (capacity() == 1) return single_iterator();
     iterator it = {control(), common().slots_union(),
                    common().generation_ptr()};
     it.skip_empty_or_deleted();
@@ -2883,7 +2832,7 @@
     // Avoid probing if we won't be able to prefetch the addresses received.
 #ifdef ABSL_HAVE_PREFETCH
     prefetch_heap_block();
-    auto seq = probe(common(), hash_ref()(key));
+    auto seq = probe(common(), hash_of(key));
     PrefetchToLocalCache(control() + seq.offset());
     PrefetchToLocalCache(slot_array() + seq.offset());
 #endif  // ABSL_HAVE_PREFETCH
@@ -2900,9 +2849,9 @@
   template <class K = key_type>
   iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     AssertOnFind(key);
-    if (is_soo()) return find_soo(key);
+    if (capacity() <= 1) return find_small(key);
     prefetch_heap_block();
-    return find_non_soo(key, hash_ref()(key));
+    return find_large(key, hash_of(key));
   }
 
   template <class K = key_type>
@@ -3079,16 +3028,18 @@
   // TODO(b/289225379): consider having a helper class that has the impls for
   // SOO functionality.
   template <class K = key_type>
-  iterator find_soo(const key_arg<K>& key) {
-    ABSL_SWISSTABLE_ASSERT(is_soo());
-    return empty() || !PolicyTraits::apply(EqualElement<K>{key, eq_ref()},
-                                           PolicyTraits::element(soo_slot()))
+  iterator find_small(const key_arg<K>& key) {
+    ABSL_SWISSTABLE_ASSERT(capacity() <= 1);
+    return empty() || !PolicyTraits::apply(
+                          EqualElement<K>{key, eq_ref()},
+                          PolicyTraits::element(single_slot()))
                ? end()
-               : soo_iterator();
+               : single_iterator();
   }
 
   template <class K = key_type>
-  iterator find_non_soo(const key_arg<K>& key, size_t hash) {
+  iterator find_large(const key_arg<K>& key, size_t hash) {
+    ABSL_SWISSTABLE_ASSERT(capacity() > 1);
     ABSL_SWISSTABLE_ASSERT(!is_soo());
     auto seq = probe(common(), hash);
     const h2_t h2 = H2(hash);
@@ -3178,6 +3129,10 @@
                   sizeof(slot_type));
   }
 
+  template <class K>
+  size_t hash_of(const K& key) const {
+    return hash_ref()(key);
+  }
   size_t hash_of(slot_type* slot) const {
     return PolicyTraits::apply(HashElement{hash_ref()},
                                PolicyTraits::element(slot));
@@ -3310,7 +3265,7 @@
         PolicyTraits::transfer_uses_memcpy() && SooEnabled();
     size_t index = GrowSooTableToNextCapacityAndPrepareInsert<
         kUseMemcpy ? OptimalMemcpySizeForSooSlotTransfer(sizeof(slot_type)) : 0,
-        kUseMemcpy>(common(), GetPolicyFunctions(), hash_ref()(key),
+        kUseMemcpy>(common(), GetPolicyFunctions(), hash_of(key),
                     soo_slot_ctrl);
     return {iterator_at(index), true};
   }
@@ -3319,7 +3274,7 @@
   std::pair<iterator, bool> find_or_prepare_insert_non_soo(const K& key) {
     ABSL_SWISSTABLE_ASSERT(!is_soo());
     prefetch_heap_block();
-    const size_t hash = hash_ref()(key);
+    const size_t hash = hash_of(key);
     auto seq = probe(common(), hash);
     const h2_t h2 = H2(hash);
     const ctrl_t* ctrl = control();
@@ -3404,7 +3359,7 @@
     }
     if (empty()) return;
 
-    const size_t hash_of_arg = hash_ref()(key);
+    const size_t hash_of_arg = hash_of(key);
     const auto assert_consistent = [&](const ctrl_t*, void* slot) {
       const value_type& element =
           PolicyTraits::element(static_cast<slot_type*>(slot));
@@ -3452,7 +3407,10 @@
   void emplace_at(iterator iter, Args&&... args) {
     construct(iter.slot(), std::forward<Args>(args)...);
 
-    assert(PolicyTraits::apply(FindElement{*this}, *iter) == iter &&
+    // When capacity is 1, find calls find_small and if size is 0, then it will
+    // return an end iterator. This can happen in the raw_hash_set copy ctor.
+    assert((capacity() == 1 ||
+            PolicyTraits::apply(FindElement{*this}, *iter) == iter) &&
            "constructed value does not match the lookup key");
   }
 
@@ -3528,6 +3486,20 @@
   const_iterator soo_iterator() const {
     return const_cast<raw_hash_set*>(this)->soo_iterator();
   }
+  slot_type* single_slot() {
+    ABSL_SWISSTABLE_ASSERT(capacity() <= 1);
+    return SooEnabled() ? soo_slot() : slot_array();
+  }
+  const slot_type* single_slot() const {
+    return const_cast<raw_hash_set*>(this)->single_slot();
+  }
+  iterator single_iterator() {
+    return {SooEnabled() ? SooControl() : control(), single_slot(),
+            common().generation_ptr()};
+  }
+  const_iterator single_iterator() const {
+    return const_cast<raw_hash_set*>(this)->single_iterator();
+  }
   HashtablezInfoHandle infoz() {
     ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().infoz();
@@ -3749,7 +3721,7 @@
                              const typename Set::key_type& key) {
     if (set.is_soo()) return 0;
     size_t num_probes = 0;
-    const size_t hash = set.hash_ref()(key);
+    const size_t hash = set.hash_of(key);
     auto seq = probe(set.common(), hash);
     const h2_t h2 = H2(hash);
     const ctrl_t* ctrl = set.control();
diff --git a/absl/container/internal/raw_hash_set_benchmark.cc b/absl/container/internal/raw_hash_set_benchmark.cc
index b593283..ac94877 100644
--- a/absl/container/internal/raw_hash_set_benchmark.cc
+++ b/absl/container/internal/raw_hash_set_benchmark.cc
@@ -172,8 +172,7 @@
 //
 // On a table of size N, keep deleting the LRU entry and add a random one.
 void BM_CacheInSteadyState(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   string_generator gen{12};
   StringTable t;
   std::deque<std::string> keys;
@@ -250,8 +249,7 @@
 BENCHMARK(BM_EndComparison);
 
 void BM_Iteration(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   string_generator gen{12};
   StringTable t;
 
@@ -293,8 +291,7 @@
     ->ArgPair(1000, 10);
 
 void BM_CopyCtorSparseInt(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -312,8 +309,7 @@
 BENCHMARK(BM_CopyCtorSparseInt)->Range(1, 4096);
 
 void BM_CopyCtorInt(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -330,8 +326,7 @@
 BENCHMARK(BM_CopyCtorInt)->Range(0, 4096);
 
 void BM_CopyCtorString(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   StringTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -348,8 +343,7 @@
 BENCHMARK(BM_CopyCtorString)->Range(0, 4096);
 
 void BM_CopyAssign(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
   while (t.size() < state.range(0)) {
@@ -365,8 +359,7 @@
 BENCHMARK(BM_CopyAssign)->Range(128, 4096);
 
 void BM_RangeCtor(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
   std::vector<int> values;
   const size_t desired_size = state.range(0);
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 2359269..404d1eb 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -53,6 +53,7 @@
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"
 #include "absl/container/internal/hash_policy_testing.h"
+#include "absl/random/random.h"
 // TODO(b/382423690): Separate tests that depend only on
 // hashtable_control_bytes.
 #include "absl/container/internal/hashtable_control_bytes.h"
@@ -995,6 +996,21 @@
   EXPECT_TRUE(t.empty());
 }
 
+TEST(Table, Prefetch) {
+  IntTable t;
+  t.emplace(1);
+  // Works for both present and absent keys.
+  t.prefetch(1);
+  t.prefetch(2);
+
+  static constexpr int size = 10;
+  for (int i = 0; i < size; ++i) t.insert(i);
+  for (int i = 0; i < size; ++i) {
+    t.prefetch(i);
+    ASSERT_TRUE(t.find(i) != t.end()) << i;
+  }
+}
+
 TYPED_TEST(SooTest, LookupEmpty) {
   TypeParam t;
   auto it = t.find(0);
@@ -1922,8 +1938,7 @@
     const std::vector<int64_t>& keys, size_t num_iters) {
   ProbeStats stats;
 
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; };
   std::uniform_int_distribution<size_t> dist(0, keys.size() - 1);
   while (num_iters--) {
@@ -3012,7 +3027,7 @@
   SetSamplingRateTo1Percent();
 
   auto& sampler = GlobalHashtablezSampler();
-  size_t start_size = 0;
+  int64_t start_size = 0;
   // Reserve the table, so that if it sampled, it'll be preexisting.
   absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);
   start_size += sampler.Iterate([&](const HashtablezInfo& info) {
@@ -3025,7 +3040,7 @@
     tables.emplace_back();
     mutate_table(tables.back());
   }
-  size_t end_size = 0;
+  int64_t end_size = 0;
   std::vector<const HashtablezInfo*> infos;
   end_size += sampler.Iterate([&](const HashtablezInfo& info) {
     ++end_size;
@@ -3107,6 +3122,29 @@
   }
 }
 
+TEST(RawHashSamplerTest, SooTableSampleOnCopy) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+
+  SooInt32Table t_orig;
+  t_orig.insert(1);
+
+  std::vector<const HashtablezInfo*> infos =
+      SampleSooMutation([&t_orig](SooInt32Table& t) {
+        t = t_orig;
+      });
+
+  for (const HashtablezInfo* info : infos) {
+    ASSERT_EQ(info->inline_element_size,
+              sizeof(typename SooInt32Table::value_type));
+    ASSERT_EQ(info->soo_capacity, SooCapacity());
+    ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
+    ASSERT_EQ(info->size, 1);
+  }
+}
+
 // This tests that rehash(0) on a sampled table with size that fits in SOO
 // doesn't incorrectly result in losing sampling.
 TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {
@@ -3141,15 +3179,16 @@
   SetSamplingRateTo1Percent();
 
   auto& sampler = GlobalHashtablezSampler();
-  size_t start_size = 0;
+  int64_t start_size = 0;
   start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
 
   std::vector<CustomAllocIntTable> tables;
   for (int i = 0; i < 100000; ++i) {
     tables.emplace_back();
     tables.back().insert(1);
+    tables.push_back(tables.back());  // Copies the table.
   }
-  size_t end_size = 0;
+  int64_t end_size = 0;
   end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
 
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
@@ -3660,16 +3699,16 @@
     t.insert(1);
     EXPECT_EQ(HashCount(t), 1);
     t.erase(1);
-    EXPECT_EQ(HashCount(t), 2);
+    EXPECT_LE(HashCount(t), 2);
   }
   {
     Table t;
     t.insert(3);
     EXPECT_EQ(HashCount(t), 1);
     auto node = t.extract(3);
-    EXPECT_EQ(HashCount(t), 2);
+    EXPECT_LE(HashCount(t), 2);
     t.insert(std::move(node));
-    EXPECT_EQ(HashCount(t), 3);
+    EXPECT_LE(HashCount(t), 3);
   }
   {
     Table t;
diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc
index d396c58..25073f7 100644
--- a/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -126,6 +126,7 @@
       if (pre_signal_frame_pointer >= old_frame_pointer) {
         new_frame_pointer = pre_signal_frame_pointer;
       }
+    }
   }
 #endif
 
@@ -137,7 +138,7 @@
   // prevent "double fault" in case we hit the first fault due to e.g.
   // stack corruption.
   if (!absl::debugging_internal::AddressIsReadable(
-          new_frame_pointer))
+          new_frame_pointer)) {
     return nullptr;
   }
 
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index c1b1f66..c7916b5 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -28,13 +28,25 @@
 // defined.
 #include "absl/base/config.h"
 
+// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
+// <version> instead, even though <version> is not available in C++17 mode prior
+// to GCC9.
+#if defined(__has_include)
+#if __has_include(<version>)
+#define ABSL_INTERNAL_VERSION_HEADER_AVAILABLE 1
+#endif
+#endif
+
 // For feature testing and determining which headers can be included.
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || \
+    ABSL_INTERNAL_VERSION_HEADER_AVAILABLE
 #include <version>
 #else
 #include <ciso646>
 #endif
 
+#undef ABSL_INTERNAL_VERSION_HEADER_AVAILABLE
+
 #include <algorithm>
 #include <array>
 #include <bitset>
@@ -84,10 +96,6 @@
 #include <string_view>
 #endif
 
-#ifdef __ARM_ACLE
-#include <arm_acle.h>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -1081,8 +1089,7 @@
   };
 
   static constexpr uint64_t kMul =
-  sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
-                      : uint64_t{0xdcb22ca68cb134ed};
+   uint64_t{0xdcb22ca68cb134ed};
 
   template <typename T>
   using IntegralFastPath =
@@ -1140,10 +1147,9 @@
       MixingHashState hash_state, WeaklyMixedInteger value) {
     // Some transformation for the value is needed to make an empty
     // string/container change the mixing hash state.
-    // Seed() is most likely already in a register.
-    // TODO(b/384509507): experiment with using kMul or last 31 bits of kMul.
-    // See https://godbolt.org/z/6cM77s3PW for ideas.
-    return MixingHashState{hash_state.state_ + (Seed() + value.value)};
+    // We use constant smaller than 8 bits to make compiler use
+    // `add` with an immediate operand with 1 byte value.
+    return MixingHashState{hash_state.state_ + (0x57 + value.value)};
   }
 
   template <typename CombinerT>
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel
index c052105..44ec71b 100644
--- a/absl/log/internal/BUILD.bazel
+++ b/absl/log/internal/BUILD.bazel
@@ -425,10 +425,6 @@
     hdrs = ["proto.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        ":internal_users",
-        ":structured_proto_users",
-    ],
     deps = [
         "//absl/base",
         "//absl/base:config",
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index 3c7a02f..f455d1e 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -124,6 +124,7 @@
     deps = [
         ":int128",
         "//absl/base:config",
+        "//absl/random",
         "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc
index e2e2de5..c37abec 100644
--- a/absl/numeric/int128_benchmark.cc
+++ b/absl/numeric/int128_benchmark.cc
@@ -13,31 +13,29 @@
 // limitations under the License.
 
 #include <algorithm>
+#include <cstddef>
 #include <cstdint>
 #include <limits>
 #include <random>
+#include <type_traits>
+#include <utility>
 #include <vector>
 
 #include "absl/base/config.h"
 #include "absl/numeric/int128.h"
+#include "absl/random/random.h"
 #include "benchmark/benchmark.h"
 
 namespace {
 
 constexpr size_t kSampleSize = 1000000;
 
-std::mt19937 MakeRandomEngine() {
-  std::random_device r;
-  std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
-  return std::mt19937(seed);
-}
-
 template <typename T,
           typename H = typename std::conditional<
               std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
 std::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() {
   std::vector<std::pair<T, T>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -77,7 +75,7 @@
               std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
 std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() {
   std::vector<std::pair<T, H>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -114,7 +112,7 @@
 
 std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
   std::vector<std::pair<absl::uint128, absl::uint128>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<uint64_t> uniform_uint64;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -155,7 +153,8 @@
 class UniformIntDistribution128 {
  public:
   // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
-  T operator()(std::mt19937& generator) {
+  template <class URBG>
+  T operator()(URBG& generator) {
     return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);
   }
 
@@ -168,7 +167,7 @@
               std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
 std::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() {
   std::vector<std::pair<T, T>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<T> uniform_128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -209,7 +208,7 @@
               std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
 std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() {
   std::vector<std::pair<T, H>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<T> uniform_int128;
   std::uniform_int_distribution<H> uniform_int64;
   values.reserve(kSampleSize);
@@ -246,9 +245,9 @@
 BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128);
 
 std::vector<std::pair<unsigned __int128, unsigned __int128>>
-      GetRandomIntrinsic128Sample() {
+GetRandomIntrinsic128Sample() {
   std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<unsigned __int128> uniform_uint128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
diff --git a/absl/profiling/BUILD.bazel b/absl/profiling/BUILD.bazel
index c5e3b00..ee4800d 100644
--- a/absl/profiling/BUILD.bazel
+++ b/absl/profiling/BUILD.bazel
@@ -56,6 +56,7 @@
     deps = [
         ":sample_recorder",
         "//absl/base:core_headers",
+        "//absl/random",
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
diff --git a/absl/profiling/CMakeLists.txt b/absl/profiling/CMakeLists.txt
index 9b3a710..84b8b3b 100644
--- a/absl/profiling/CMakeLists.txt
+++ b/absl/profiling/CMakeLists.txt
@@ -32,6 +32,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::random_random
     absl::sample_recorder
     absl::time
     GTest::gmock_main
diff --git a/absl/profiling/internal/sample_recorder_test.cc b/absl/profiling/internal/sample_recorder_test.cc
index 3373329..a037f9d 100644
--- a/absl/profiling/internal/sample_recorder_test.cc
+++ b/absl/profiling/internal/sample_recorder_test.cc
@@ -15,14 +15,20 @@
 #include "absl/profiling/internal/sample_recorder.h"
 
 #include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
 #include <random>
 #include <vector>
 
 #include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "absl/base/thread_annotations.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
 #include "absl/time/time.h"
 
 namespace absl {
@@ -112,9 +118,7 @@
 
   for (int i = 0; i < 10; ++i) {
     pool.Schedule([&sampler, &stop, i]() {
-      std::random_device rd;
-      std::mt19937 gen(rd());
-
+      absl::InsecureBitGen gen;
       std::vector<Info*> infoz;
       while (!stop.HasBeenNotified()) {
         if (infoz.empty()) {
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 3b0aab5..49562f7 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -250,6 +250,7 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
+        "//absl/random",
         "@google_benchmark//:benchmark_main",
     ],
 )
@@ -360,6 +361,7 @@
         ":strings",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
+        "//absl/random",
         "@google_benchmark//:benchmark_main",
     ],
 )
@@ -1358,6 +1360,7 @@
         ":str_format",
         ":str_format_internal",
         ":strings",
+        "//absl/random",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index ec731d8..ee73860 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -545,6 +545,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::random_random
     absl::str_format
     absl::str_format_internal
     absl::strings
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc
index a839019..435090d 100644
--- a/absl/strings/ascii_benchmark.cc
+++ b/absl/strings/ascii_benchmark.cc
@@ -16,9 +16,9 @@
 #include <array>
 #include <cctype>
 #include <cstddef>
-#include <random>
 #include <string>
 
+#include "absl/random/random.h"
 #include "absl/strings/ascii.h"
 #include "benchmark/benchmark.h"
 
@@ -27,10 +27,8 @@
 std::array<unsigned char, 256> MakeShuffledBytes() {
   std::array<unsigned char, 256> bytes;
   for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i);
-  std::random_device rd;
-  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
-  std::mt19937 g(seed);
-  std::shuffle(bytes.begin(), bytes.end(), g);
+  absl::InsecureBitGen gen;
+  std::shuffle(bytes.begin(), bytes.end(), gen);
   return bytes;
 }
 
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 694c126..fc4dc4f 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -16,11 +16,13 @@
 
 #include "absl/strings/internal/str_format/extension.h"
 
+#include <cstddef>
 #include <random>
 #include <string>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
 
@@ -44,8 +46,7 @@
 namespace {
 
 std::string MakeRandomString(size_t len) {
-  std::random_device rd;
-  std::mt19937 gen(rd());
+  absl::InsecureBitGen gen;
   std::uniform_int_distribution<> dis('a', 'z');
   std::string s(len, '0');
   for (char& c : s) {
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 3d9a173..1a82087 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -41,7 +41,6 @@
 #include "gtest/gtest.h"
 #include "absl/log/log.h"
 #include "absl/numeric/int128.h"
-#include "absl/random/distributions.h"
 #include "absl/random/random.h"
 #include "absl/strings/internal/numbers_test_common.h"
 #include "absl/strings/internal/ostringstream.h"
@@ -1368,13 +1367,10 @@
 
 const size_t kNumRandomTests = 10000;
 
-template <typename IntType>
-void test_random_integer_parse_base(bool (*parse_func)(absl::string_view,
-                                                       IntType* value,
-                                                       int base)) {
-  using RandomEngine = std::minstd_rand0;
-  std::random_device rd;
-  RandomEngine rng(rd());
+template <typename IntType,
+          bool parse_func(absl::string_view, IntType* value, int base)>
+void test_random_integer_parse_base() {
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<IntType> random_int(
       std::numeric_limits<IntType>::min());
   std::uniform_int_distribution<int> random_base(2, 36);
@@ -1406,34 +1402,32 @@
 }
 
 TEST(stringtest, safe_strto16_random) {
-  test_random_integer_parse_base<int16_t>(&safe_strto16_base);
+  test_random_integer_parse_base<int16_t, safe_strto16_base>();
 }
 TEST(stringtest, safe_strto32_random) {
-  test_random_integer_parse_base<int32_t>(&safe_strto32_base);
+  test_random_integer_parse_base<int32_t, safe_strto32_base>();
 }
 TEST(stringtest, safe_strto64_random) {
-  test_random_integer_parse_base<int64_t>(&safe_strto64_base);
+  test_random_integer_parse_base<int64_t, safe_strto64_base>();
 }
 TEST(stringtest, safe_strtou16_random) {
-  test_random_integer_parse_base<uint16_t>(&safe_strtou16_base);
+  test_random_integer_parse_base<uint16_t, safe_strtou16_base>();
 }
 TEST(stringtest, safe_strtou32_random) {
-  test_random_integer_parse_base<uint32_t>(&safe_strtou32_base);
+  test_random_integer_parse_base<uint32_t, safe_strtou32_base>();
 }
 TEST(stringtest, safe_strtou64_random) {
-  test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
+  test_random_integer_parse_base<uint64_t, safe_strtou64_base>();
 }
 TEST(stringtest, safe_strtou128_random) {
   // random number generators don't work for uint128 so this code must be custom
   // implemented for uint128, but is generally the same as what's above.
   // test_random_integer_parse_base<absl::uint128>(
   //     &absl::numbers_internal::safe_strtou128_base);
-  using RandomEngine = std::minstd_rand0;
   using IntType = absl::uint128;
   constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
 
-  std::random_device rd;
-  RandomEngine rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<uint64_t> random_uint64(
       std::numeric_limits<uint64_t>::min());
   std::uniform_int_distribution<int> random_base(2, 36);
@@ -1464,12 +1458,10 @@
   // implemented for int128, but is generally the same as what's above.
   // test_random_integer_parse_base<absl::int128>(
   //     &absl::numbers_internal::safe_strto128_base);
-  using RandomEngine = std::minstd_rand0;
   using IntType = absl::int128;
   constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
 
-  std::random_device rd;
-  RandomEngine rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<int64_t> random_int64(
       std::numeric_limits<int64_t>::min());
   std::uniform_int_distribution<uint64_t> random_uint64(
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index 4e36687..546f6ed 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -24,6 +24,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "benchmark/benchmark.h"
@@ -286,9 +287,7 @@
                          "found", "a",      "large",    "mushroom", "and",
                          "a",     "couple", "crickets", "eating",   "pie"};
   // Create some keys that consist of words in random order.
-  std::random_device r;
-  std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
-  std::mt19937 rng(seed);
+  absl::InsecureBitGen rng;
   std::vector<std::string> keys(table_size);
   std::vector<int> all_indices;
   const int kBlockSize = 1 << 12;
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index c3c271e..920928e 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -266,6 +266,7 @@
         "//absl/log",
         "//absl/log:check",
         "//absl/memory",
+        "//absl/random",
         "//absl/time",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index 4d21067..9d4844d 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -193,6 +193,7 @@
     absl::core_headers
     absl::log
     absl::memory
+    absl::random_random
     absl::time
     GTest::gmock_main
 )
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index d8c4fdf..a3eb3db 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -36,6 +36,7 @@
 #include "absl/log/check.h"
 #include "absl/log/log.h"
 #include "absl/memory/memory.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/internal/create_thread_identity.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/time/clock.h"
@@ -1064,8 +1065,7 @@
 
 static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
                                      int *running) {
-  std::random_device dev;
-  std::mt19937 gen(dev());
+  absl::InsecureBitGen gen;
   std::uniform_int_distribution<int> random_millis(0, 15);
   mu->ReaderLock();
   while (*running == 3) {
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 445bdcc..ad0313c 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -99,6 +99,7 @@
         "//absl/base:core_headers",
         "//absl/hash:hash_testing",
         "//absl/numeric:int128",
+        "//absl/random",
         "//absl/strings:str_format",
         "//absl/time/internal/cctz:time_zone",
         "@googletest//:gtest",
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index a48689c..ea91ba3 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -49,7 +49,7 @@
     "internal/cctz/include/cctz/civil_time.h"
     "internal/cctz/include/cctz/civil_time_detail.h"
   SRCS
-  "internal/cctz/src/civil_time_detail.cc"
+    "internal/cctz/src/civil_time_detail.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
 )
@@ -122,6 +122,7 @@
     absl::config
     absl::core_headers
     absl::hash_testing
+    absl::random_random
     absl::strings
     absl::str_format
     absl::time_zone
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 573a76a..1e3fe67 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -40,6 +40,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_format.h"
 #include "absl/time/time.h"
 
@@ -1514,9 +1515,7 @@
 }
 
 TEST(Duration, ToDoubleSecondsCheckRandom) {
-  std::random_device rd;
-  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
-  std::mt19937_64 gen(seed);
+  absl::InsecureBitGen gen;
   // We want doubles distributed from 1/8ns up to 2^63, where
   // as many values are tested from 1ns to 2ns as from 1sec to 2sec,
   // so even distribute along a log-scale of those values, and