about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2018-05-31T19·26-0700
committerMark Barolak <mbar@google.com>2018-05-31T19·58-0400
commit7aacab8ae05d7115049923da9cfbf584dc1f8338 (patch)
tree4394fc5eeed08a356d02ccfef33d1201f21b0dc3
parent99477fa9f1e89a7d8253c8aeee331864710d080c (diff)
- e2f6b8ac647271815b4fed2991f405524dd762c3 Release cctz microbenchmarks. by Alex Strelnikov <strel@google.com>
  - 924ba2a3f9fca695d73c6bf491d20669e2b96b8e Changed RawPtr to use std::addressof() instead of operato... by Abseil Team <absl-team@google.com>
  - e8cf67f9fa74d4c5632da35547025ad2301c6819 Import of CCTZ from GitHub. by Alex Strelnikov <strel@google.com>
  - 2ece8a96611afcddd7b91e0197dadb896248250c Abandon ".inc" files in favor of ".h" headers. by Jorg Brown <jorg@google.com>
  - 37f5ed5da4058f90fb3e6a2733fce5b1fd0aaedf Add exception safety tests for absl::optional<T> by Abseil Team <absl-team@google.com>
  - 337f995a866b8f905f64ca6b271b5fec8f248a60 Update WORKSPACE to grab specific commits of dependencies... by Alex Strelnikov <strel@google.com>
  - 93e5b134607a554993387ad913e6c1621606004b Release Charmap microbenchmark. by Alex Strelnikov <strel@google.com>
  - 95c2e29b6d93ec1334484ee37d91f63101c45307 Release OStringStream microbenchmarks. by Alex Strelnikov <strel@google.com>
  - 250f51839ed26dd1e6b658d35aa291413e5f4825 Internal change by Greg Falcon <gfalcon@google.com>
  - ce34900fa3d1a95a8446bc943cdd801fac95be25 Improve compatibility of cctz cc_test targets for portabl... by Shaindel Schwartz <shaindel@google.com>
  - ce7e31dbf2c1ee93c79aae5b7dc7c603cb4babcf Improve portability of cc_tests. (Mark more tests that ca... by Abseil Team <absl-team@google.com>
  - dfcd4e455923703c1a1dcd523c5f915f7990fa2a Accept strings with custom allocators as arguments to abs... by Greg Falcon <gfalcon@google.com>
  - 2946b41ed3d5b8b5a8dc11182e443cf1ab6e3bde Link against benchmark_main instead of using BENCHMARK_MA... by Alex Strelnikov <strel@google.com>
  - f09de9e03bf8edd363069c4b352d8009423f531c Adds link to doc about the formats allowed by SimpleAtof(... by Greg Miller <jgm@google.com>
  - 59b0977e7a308e0800277886cf60226b2cc426a1 Simplify the HideMask() calculation so that it doesn't us... by Jorg Brown <jorg@google.com>

GitOrigin-RevId: e2f6b8ac647271815b4fed2991f405524dd762c3
Change-Id: Ib9c8547ed7fe217fad6cb3ab1362e96181aa5cfa
-rw-r--r--WORKSPACE12
-rw-r--r--absl/algorithm/BUILD.bazel2
-rw-r--r--absl/algorithm/equal_benchmark.cc2
-rw-r--r--absl/base/BUILD.bazel7
-rw-r--r--absl/base/internal/hide_ptr.h4
-rw-r--r--absl/base/internal/thread_identity_benchmark.cc2
-rw-r--r--absl/container/BUILD.bazel9
-rw-r--r--absl/container/fixed_array_benchmark.cc2
-rw-r--r--absl/container/inlined_vector_benchmark.cc2
-rw-r--r--absl/memory/memory.h4
-rw-r--r--absl/strings/BUILD.bazel41
-rw-r--r--absl/strings/escaping_benchmark.cc6
-rw-r--r--absl/strings/escaping_test.cc4
-rw-r--r--absl/strings/internal/char_map_benchmark.cc61
-rw-r--r--absl/strings/internal/escaping_test_common.h131
-rw-r--r--absl/strings/internal/escaping_test_common.inc113
-rw-r--r--absl/strings/internal/numbers_test_common.h178
-rw-r--r--absl/strings/internal/numbers_test_common.inc156
-rw-r--r--absl/strings/internal/ostringstream_benchmark.cc106
-rw-r--r--absl/strings/numbers.h4
-rw-r--r--absl/strings/numbers_test.cc21
-rw-r--r--absl/strings/str_cat_benchmark.cc2
-rw-r--r--absl/strings/str_join_benchmark.cc2
-rw-r--r--absl/strings/str_replace_benchmark.cc2
-rw-r--r--absl/strings/str_split_benchmark.cc2
-rw-r--r--absl/strings/string_view_benchmark.cc2
-rw-r--r--absl/strings/substitute.h5
-rw-r--r--absl/synchronization/BUILD.bazel4
-rw-r--r--absl/synchronization/internal/graphcycles_benchmark.cc2
-rw-r--r--absl/synchronization/mutex_benchmark.cc2
-rw-r--r--absl/time/BUILD.bazel4
-rw-r--r--absl/time/internal/cctz/BUILD.bazel28
-rw-r--r--absl/time/internal/cctz/src/cctz_benchmark.cc982
-rw-r--r--absl/time/internal/cctz/src/time_zone_format_test.cc9
-rw-r--r--absl/types/BUILD.bazel14
-rw-r--r--absl/types/CMakeLists.txt17
-rw-r--r--absl/types/optional_exception_safety_test.cc284
37 files changed, 1879 insertions, 349 deletions
diff --git a/WORKSPACE b/WORKSPACE
index 064459306de3..9c9506508723 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -13,20 +13,20 @@ http_archive(
 # GoogleTest/GoogleMock framework. Used by most unit-tests.
 http_archive(
      name = "com_google_googletest",
-     urls = ["https://github.com/google/googletest/archive/master.zip"],
-     strip_prefix = "googletest-master",
+     urls = ["https://github.com/google/googletest/archive/4e4df226fc197c0dda6e37f5c8c3845ca1e73a49.zip"],
+     strip_prefix = "googletest-4e4df226fc197c0dda6e37f5c8c3845ca1e73a49",
 )
 
 # Google benchmark.
 http_archive(
     name = "com_github_google_benchmark",
-    urls = ["https://github.com/google/benchmark/archive/master.zip"],
-    strip_prefix = "benchmark-master",
+    urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
+    strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
 )
 
 # RE2 regular-expression framework. Used by some unit-tests.
 http_archive(
     name = "com_googlesource_code_re2",
-    urls = ["https://github.com/google/re2/archive/master.zip"],
-    strip_prefix = "re2-master",
+    urls = ["https://github.com/google/re2/archive/6cf8ccd82dbaab2668e9b13596c68183c9ecd13f.zip"],
+    strip_prefix = "re2-6cf8ccd82dbaab2668e9b13596c68183c9ecd13f",
 )
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 3b24ce12029c..d04dc71206e8 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -49,7 +49,7 @@ cc_test(
     deps = [
         ":algorithm",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc
index 9af36ce79f6c..19c0780ccd17 100644
--- a/absl/algorithm/equal_benchmark.cc
+++ b/absl/algorithm/equal_benchmark.cc
@@ -124,5 +124,3 @@ BENCHMARK_TEMPLATE(BM_absl_equal_self_benchmark, EightBits)
     ->Range(kMinBenchmarkSize, kMaxBenchmarkSize);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 748f2f9f2154..1e93d97ebd40 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -392,11 +392,6 @@ cc_test(
         "//absl:windows": [],
         "//conditions:default": ["-pthread"],
     }),
-    tags = [
-        "no_test_android_arm",
-        "no_test_android_arm64",
-        "no_test_android_x86",
-    ],
     deps = [":malloc_internal"],
 )
 
@@ -426,6 +421,6 @@ cc_test(
     deps = [
         ":base",
         "//absl/synchronization",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h
index 2c2e11f679a0..45cf438912c2 100644
--- a/absl/base/internal/hide_ptr.h
+++ b/absl/base/internal/hide_ptr.h
@@ -23,9 +23,7 @@ namespace base_internal {
 // Arbitrary value with high bits set. Xor'ing with it is unlikely
 // to map one valid pointer to another valid pointer.
 constexpr uintptr_t HideMask() {
-  static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
-                "uintptr_t must be 32 or 64 bits");
-  return sizeof(uintptr_t) == 8 ? 0xF03A5F7BF03A5F7BULL : 0xF03A5F7BUL;
+  return (uintptr_t{0xF03A5F7BU} << (sizeof(uintptr_t) - 4) * 8) | 0xF03A5F7BU;
 }
 
 // Hide a pointer from the leak checker. For internal use only.
diff --git a/absl/base/internal/thread_identity_benchmark.cc b/absl/base/internal/thread_identity_benchmark.cc
index fe22e4cff172..242522b4418a 100644
--- a/absl/base/internal/thread_identity_benchmark.cc
+++ b/absl/base/internal/thread_identity_benchmark.cc
@@ -36,5 +36,3 @@ void BM_UnsafeCurrentThreadIdentity(benchmark::State& state) {
 BENCHMARK(BM_UnsafeCurrentThreadIdentity);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 897be90fc9e4..119d5c88de2a 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -42,11 +42,6 @@ cc_test(
     name = "fixed_array_test",
     srcs = ["fixed_array_test.cc"],
     copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
-    tags = [
-        "no_test_android_arm",
-        "no_test_android_arm64",
-        "no_test_android_x86",
-    ],
     deps = [
         ":fixed_array",
         "//absl/base:exception_testing",
@@ -74,7 +69,7 @@ cc_test(
     tags = ["benchmark"],
     deps = [
         ":fixed_array",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -131,7 +126,7 @@ cc_test(
         ":inlined_vector",
         "//absl/base",
         "//absl/strings",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
diff --git a/absl/container/fixed_array_benchmark.cc b/absl/container/fixed_array_benchmark.cc
index 2d39898d8a5f..b4f0cf2aeb04 100644
--- a/absl/container/fixed_array_benchmark.cc
+++ b/absl/container/fixed_array_benchmark.cc
@@ -64,5 +64,3 @@ BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 256)->Range(0, 1 << 16);
 BENCHMARK_TEMPLATE(BM_FixedArray, std::string, 65536)->Range(0, 1 << 16);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index c6bc5cd96dc8..5977bc934f0e 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -372,5 +372,3 @@ void BM_StdVectorEmpty(benchmark::State& state) {
 BENCHMARK(BM_StdVectorEmpty);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 055d88e001b3..cd818cff4ffa 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -179,9 +179,9 @@ typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
 // useful within templates that need to handle a complement of raw pointers,
 // `std::nullptr_t`, and smart pointers.
 template <typename T>
-auto RawPtr(T&& ptr) -> decltype(&*ptr) {
+auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) {
   // ptr is a forwarding reference to support Ts with non-const operators.
-  return (ptr != nullptr) ? &*ptr : nullptr;
+  return (ptr != nullptr) ? std::addressof(*ptr) : nullptr;
 }
 inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
 
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index e6bb7ff530e4..d1c6878c41e4 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -111,7 +111,7 @@ cc_test(
     size = "small",
     srcs = [
         "escaping_test.cc",
-        "internal/escaping_test_common.inc",
+        "internal/escaping_test_common.h",
     ],
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
@@ -127,7 +127,7 @@ cc_test(
     name = "escaping_benchmark",
     srcs = [
         "escaping_benchmark.cc",
-        "internal/escaping_test_common.inc",
+        "internal/escaping_test_common.h",
     ],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
@@ -135,7 +135,7 @@ cc_test(
     deps = [
         ":strings",
         "//absl/base",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -199,7 +199,7 @@ cc_test(
         ":strings",
         "//absl/base",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -240,7 +240,7 @@ cc_test(
     deps = [
         ":strings",
         "//absl/base",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -278,7 +278,7 @@ cc_test(
     deps = [
         ":strings",
         "//absl/base",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -295,6 +295,18 @@ cc_test(
 )
 
 cc_test(
+    name = "ostringstream_benchmark",
+    srcs = ["internal/ostringstream_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":internal",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_test(
     name = "resize_uninitialized_test",
     size = "small",
     srcs = [
@@ -333,7 +345,7 @@ cc_test(
     deps = [
         ":strings",
         "//absl/memory",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -358,7 +370,7 @@ cc_test(
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -366,7 +378,7 @@ cc_test(
     name = "numbers_test",
     size = "small",
     srcs = [
-        "internal/numbers_test_common.inc",
+        "internal/numbers_test_common.h",
         "numbers_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
@@ -411,3 +423,14 @@ cc_test(
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_test(
+    name = "char_map_benchmark",
+    srcs = ["internal/char_map_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    tags = ["benchmark"],
+    deps = [
+        ":internal",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/absl/strings/escaping_benchmark.cc b/absl/strings/escaping_benchmark.cc
index 26ddc2d5f318..0f791f4e8750 100644
--- a/absl/strings/escaping_benchmark.cc
+++ b/absl/strings/escaping_benchmark.cc
@@ -20,7 +20,7 @@
 
 #include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
-#include "absl/strings/internal/escaping_test_common.inc"
+#include "absl/strings/internal/escaping_test_common.h"
 
 namespace {
 
@@ -39,7 +39,7 @@ BENCHMARK(BM_CUnescapeHexString);
 void BM_WebSafeBase64Escape_string(benchmark::State& state) {
   std::string raw;
   for (int i = 0; i < 10; ++i) {
-    for (const auto& test_set : base64_strings) {
+    for (const auto& test_set : absl::strings_internal::base64_strings()) {
       raw += std::string(test_set.plaintext);
     }
   }
@@ -92,5 +92,3 @@ void BM_CEscape_MostEscaped(benchmark::State& state) {
 BENCHMARK(BM_CEscape_MostEscaped)->Range(1, 1 << 14);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 982989b8b4a4..3f65ec107f45 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -25,7 +25,7 @@
 #include "absl/container/fixed_array.h"
 #include "absl/strings/str_cat.h"
 
-#include "absl/strings/internal/escaping_test_common.inc"
+#include "absl/strings/internal/escaping_test_common.h"
 
 namespace {
 
@@ -575,7 +575,7 @@ TEST(Base64, EscapeAndUnescape) {
   }
 
   // Now try the long strings, this tests the streaming
-  for (const auto& tc : base64_strings) {
+  for (const auto& tc : absl::strings_internal::base64_strings()) {
     std::string buffer;
     absl::WebSafeBase64Escape(tc.plaintext, &buffer);
     EXPECT_EQ(tc.cyphertext, buffer);
diff --git a/absl/strings/internal/char_map_benchmark.cc b/absl/strings/internal/char_map_benchmark.cc
new file mode 100644
index 000000000000..c45f3157c291
--- /dev/null
+++ b/absl/strings/internal/char_map_benchmark.cc
@@ -0,0 +1,61 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/char_map.h"
+
+#include <cstdint>
+
+#include "benchmark/benchmark.h"
+
+namespace {
+
+absl::strings_internal::Charmap MakeBenchmarkMap() {
+  absl::strings_internal::Charmap m;
+  uint32_t x[] = {0x0, 0x1, 0x2, 0x3, 0xf, 0xe, 0xd, 0xc};
+  for (uint32_t& t : x) t *= static_cast<uint32_t>(0x11111111UL);
+  for (uint32_t i = 0; i < 256; ++i) {
+    if ((x[i / 32] >> (i % 32)) & 1)
+      m = m | absl::strings_internal::Charmap::Char(i);
+  }
+  return m;
+}
+
+// Micro-benchmark for Charmap::contains.
+void BM_Contains(benchmark::State& state) {
+  // Loop-body replicated 10 times to increase time per iteration.
+  // Argument continuously changed to avoid generating common subexpressions.
+  const absl::strings_internal::Charmap benchmark_map = MakeBenchmarkMap();
+  unsigned char c = 0;
+  int ops = 0;
+  for (auto _ : state) {
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+    ops += benchmark_map.contains(c++);
+  }
+  benchmark::DoNotOptimize(ops);
+}
+BENCHMARK(BM_Contains);
+
+// We don't bother benchmarking Charmap::IsZero or Charmap::IntersectsWith;
+// their running time is data-dependent and it is not worth characterizing
+// "typical" data.
+
+}  // namespace
diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h
new file mode 100644
index 000000000000..cc41f4312c7c
--- /dev/null
+++ b/absl/strings/internal/escaping_test_common.h
@@ -0,0 +1,131 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This test contains common things needed by both escaping_test.cc and
+// escaping_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+
+#include <array>
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace strings_internal {
+
+struct base64_testcase {
+  absl::string_view plaintext;
+  absl::string_view cyphertext;
+};
+
+inline const std::array<base64_testcase, 5>& base64_strings() {
+  static const std::array<base64_testcase, 5> testcase{{
+      // Some google quotes
+      // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+      // (Note that we're testing the websafe encoding, though, so if
+      // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+      { "I was always good at math and science, and I never realized "
+        "that was unusual or somehow undesirable. So one of the things "
+        "I care a lot about is helping to remove that stigma, "
+        "to show girls that you can be feminine, you can like the things "
+        "that girls like, but you can also be really good at technology. "
+        "You can be really good at building things."
+        " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+        "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+        "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+        "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+        "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+        "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+        "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+        "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+        "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+        "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+      { "Typical first year for a new cluster: "
+        "~0.5 overheating "
+        "~1 PDU failure "
+        "~1 rack-move "
+        "~1 network rewiring "
+        "~20 rack failures "
+        "~5 racks go wonky "
+        "~8 network maintenances "
+        "~12 router reloads "
+        "~3 router failures "
+        "~dozens of minor 30-second blips for dns "
+        "~1000 individual machine failures "
+        "~thousands of hard drive failures "
+        "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+        " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+        "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+        "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+        "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+        "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+        "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+        "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+        "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+        "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+        "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+        "ZWFsIEhhcmR3YXJlCg" },
+
+      { "I'm the head of the webspam team at Google.  "
+        "That means that if you type your name into Google and get porn back, "
+        "it's my fault. Unless you're a porn star, in which case porn is a "
+        "completely reasonable response."
+        " - Matt Cutts, Google Plus" "\n",
+
+        "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+        "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+        "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+        "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+        "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+        "IEdvb2dsZSBQbHVzCg" },
+
+      { "It will still be a long time before machines approach human "
+        "intelligence. "
+        "But luckily, machines don't actually have to be intelligent; "
+        "they just have to fake it. Access to a wealth of information, "
+        "combined with a rudimentary decision-making capacity, "
+        "can often be almost as useful. Of course, the results are better yet "
+        "when coupled with intelligence. A reference librarian with access to "
+        "a good search engine is a formidable tool."
+        " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
+        "\n",
+
+        "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+        "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+        "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+        "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+        "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+        "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+        "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+        "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+        "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+        "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+        "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+        "NAo" },
+
+      // Degenerate edge case
+      { "",
+        "" },
+  }};
+
+  return testcase;
+}
+
+}  // namespace strings_internal
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/absl/strings/internal/escaping_test_common.inc b/absl/strings/internal/escaping_test_common.inc
deleted file mode 100644
index 6f29140e3584..000000000000
--- a/absl/strings/internal/escaping_test_common.inc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This test contains common things needed by both escaping_test.cc and
-// escaping_benchmark.cc.
-
-namespace {
-
-struct {
-  absl::string_view plaintext;
-  absl::string_view cyphertext;
-} const base64_strings[] = {
-  // Some google quotes
-  // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
-  // (Note that we're testing the websafe encoding, though, so if
-  // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
-  { "I was always good at math and science, and I never realized "
-    "that was unusual or somehow undesirable. So one of the things "
-    "I care a lot about is helping to remove that stigma, "
-    "to show girls that you can be feminine, you can like the things "
-    "that girls like, but you can also be really good at technology. "
-    "You can be really good at building things."
-    " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
-
-    "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
-    "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
-    "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
-    "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
-    "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
-    "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
-    "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
-    "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
-    "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
-
-  { "Typical first year for a new cluster: "
-    "~0.5 overheating "
-    "~1 PDU failure "
-    "~1 rack-move "
-    "~1 network rewiring "
-    "~20 rack failures "
-    "~5 racks go wonky "
-    "~8 network maintenances "
-    "~12 router reloads "
-    "~3 router failures "
-    "~dozens of minor 30-second blips for dns "
-    "~1000 individual machine failures "
-    "~thousands of hard drive failures "
-    "slow disks, bad memory, misconfigured machines, flaky machines, etc."
-    " - Jeff Dean, The Joys of Real Hardware" "\n",
-
-    "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
-    "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
-    "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
-    "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
-    "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
-    "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
-    "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
-    "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
-    "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
-    "ZWFsIEhhcmR3YXJlCg" },
-
-  { "I'm the head of the webspam team at Google.  "
-    "That means that if you type your name into Google and get porn back, "
-    "it's my fault. Unless you're a porn star, in which case porn is a "
-    "completely reasonable response."
-    " - Matt Cutts, Google Plus" "\n",
-
-    "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
-    "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
-    "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
-    "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
-    "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
-    "IEdvb2dsZSBQbHVzCg" },
-
-  { "It will still be a long time before machines approach human intelligence. "
-    "But luckily, machines don't actually have to be intelligent; "
-    "they just have to fake it. Access to a wealth of information, "
-    "combined with a rudimentary decision-making capacity, "
-    "can often be almost as useful. Of course, the results are better yet "
-    "when coupled with intelligence. A reference librarian with access to "
-    "a good search engine is a formidable tool."
-    " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n",
-
-    "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
-    "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
-    "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
-    "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
-    "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
-    "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
-    "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
-    "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
-    "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
-    "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
-    "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
-    "NAo" },
-
-  // Degenerate edge case
-  { "",
-    "" },
-};
-
-}  // namespace
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
new file mode 100644
index 000000000000..20e3af51141e
--- /dev/null
+++ b/absl/strings/internal/numbers_test_common.h
@@ -0,0 +1,178 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file contains common things needed by numbers_test.cc,
+// numbers_legacy_test.cc and numbers_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+
+#include <array>
+#include <cstdint>
+#include <limits>
+#include <string>
+
+namespace absl {
+namespace strings_internal {
+
+template <typename IntType>
+inline bool Itoa(IntType value, int base, std::string* destination) {
+  destination->clear();
+  if (base <= 1 || base > 36) {
+    return false;
+  }
+
+  if (value == 0) {
+    destination->push_back('0');
+    return true;
+  }
+
+  bool negative = value < 0;
+  while (value != 0) {
+    const IntType next_value = value / base;
+    // Can't use std::abs here because of problems when IntType is unsigned.
+    int remainder = value > next_value * base ? value - next_value * base
+                                              : next_value * base - value;
+    char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
+    destination->insert(0, 1, c);
+    value = next_value;
+  }
+
+  if (negative) {
+    destination->insert(0, 1, '-');
+  }
+  return true;
+}
+
+struct uint32_test_case {
+  const char* str;
+  bool expect_ok;
+  int base;  // base to pass to the conversion function
+  uint32_t expected;
+};
+
+inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
+  static const std::array<uint32_test_case, 27> test_cases{{
+      {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {"0x34234324", true, 16, 0x34234324},
+      {"34234324", true, 16, 0x34234324},
+      {"0", true, 16, 0},
+      {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {" \f\v 46", true, 10, 46},  // must accept weird whitespace
+      {" \t\n 72717222", true, 8, 072717222},
+      {" \t\n 072717222", true, 8, 072717222},
+      {" \t\n 072717228", false, 8, 07271722},
+      {"0", true, 0, 0},
+
+      // Base-10 version.
+      {"34234324", true, 0, 34234324},
+      {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
+      {"34234324 \n\t", true, 10, 34234324},
+
+      // Unusual base
+      {"0", true, 3, 0},
+      {"2", true, 3, 2},
+      {"11", true, 3, 4},
+
+      // Invalid uints.
+      {"", false, 0, 0},
+      {"  ", false, 0, 0},
+      {"abc", false, 0, 0},  // would be valid hex, but prefix is missing
+      {"34234324a", false, 0, 34234324},
+      {"34234.3", false, 0, 34234},
+      {"-1", false, 0, 0},
+      {"   -123", false, 0, 0},
+      {" \t\n -123", false, 0, 0},
+
+      // Out of bounds.
+      {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
+      {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
+      {nullptr, false, 0, 0},
+  }};
+  return test_cases;
+}
+
+struct uint64_test_case {
+  const char* str;
+  bool expect_ok;
+  int base;
+  uint64_t expected;
+};
+
+inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
+  static const std::array<uint64_test_case, 34> test_cases{{
+      {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
+      {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
+
+      {"0", true, 16, 0},
+      {"000", true, 0, 0},
+      {"0", true, 0, 0},
+      {" \t\n 0xffffffffffffffff", true, 16,
+       std::numeric_limits<uint64_t>::max()},
+
+      {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
+      {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
+
+      {"12845670123456701234", false, 8, 0},
+
+      // Base-10 version.
+      {"34234324487834466", true, 0, int64_t{34234324487834466}},
+
+      {" \t\n 18446744073709551615", true, 0,
+       std::numeric_limits<uint64_t>::max()},
+
+      {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
+
+      {" \f\v 46", true, 10, 46},  // must accept weird whitespace
+
+      // Unusual base
+      {"0", true, 3, 0},
+      {"2", true, 3, 2},
+      {"11", true, 3, 4},
+
+      {"0", true, 0, 0},
+
+      // Invalid uints.
+      {"", false, 0, 0},
+      {"  ", false, 0, 0},
+      {"abc", false, 0, 0},
+      {"34234324487834466a", false, 0, 0},
+      {"34234487834466.3", false, 0, 0},
+      {"-1", false, 0, 0},
+      {"   -123", false, 0, 0},
+      {" \t\n -123", false, 0, 0},
+
+      // Out of bounds.
+      {"18446744073709551616", false, 10, 0},
+      {"18446744073709551616", false, 0, 0},
+      {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
+      {"0X10000000000000000", false, 16,
+       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
+      {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
+      {"0X10000000000000000", false, 0,
+       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
+
+      {"0x1234", true, 16, 0x1234},
+
+      // Base-10 std::string version.
+      {"1234", true, 0, 1234},
+      {nullptr, false, 0, 0},
+  }};
+  return test_cases;
+}
+
+}  // namespace strings_internal
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/absl/strings/internal/numbers_test_common.inc b/absl/strings/internal/numbers_test_common.inc
deleted file mode 100644
index 81d2a1b70510..000000000000
--- a/absl/strings/internal/numbers_test_common.inc
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This file contains common things needed by numbers_test.cc,
-// numbers_legacy_test.cc and numbers_benchmark.cc.
-
-namespace {
-
-template <typename IntType>
-bool Itoa(IntType value, int base, std::string* destination) {
-  destination->clear();
-  if (base <= 1 || base > 36) {
-    return false;
-  }
-
-  if (value == 0) {
-    destination->push_back('0');
-    return true;
-  }
-
-  bool negative = value < 0;
-  while (value != 0) {
-    const IntType next_value = value / base;
-    // Can't use std::abs here because of problems when IntType is unsigned.
-    int remainder = value > next_value * base ? value - next_value * base
-                                              : next_value * base - value;
-    char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
-    destination->insert(0, 1, c);
-    value = next_value;
-  }
-
-  if (negative) {
-    destination->insert(0, 1, '-');
-  }
-  return true;
-}
-
-struct uint32_test_case {
-  const char* str;
-  bool expect_ok;
-  int base;  // base to pass to the conversion function
-  uint32_t expected;
-} const strtouint32_test_cases[] = {
-    {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
-    {"0x34234324", true, 16, 0x34234324},
-    {"34234324", true, 16, 0x34234324},
-    {"0", true, 16, 0},
-    {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
-    {" \f\v 46", true, 10, 46},  // must accept weird whitespace
-    {" \t\n 72717222", true, 8, 072717222},
-    {" \t\n 072717222", true, 8, 072717222},
-    {" \t\n 072717228", false, 8, 07271722},
-    {"0", true, 0, 0},
-
-    // Base-10 version.
-    {"34234324", true, 0, 34234324},
-    {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
-    {"34234324 \n\t", true, 10, 34234324},
-
-    // Unusual base
-    {"0", true, 3, 0},
-    {"2", true, 3, 2},
-    {"11", true, 3, 4},
-
-    // Invalid uints.
-    {"", false, 0, 0},
-    {"  ", false, 0, 0},
-    {"abc", false, 0, 0},  // would be valid hex, but prefix is missing
-    {"34234324a", false, 0, 34234324},
-    {"34234.3", false, 0, 34234},
-    {"-1", false, 0, 0},
-    {"   -123", false, 0, 0},
-    {" \t\n -123", false, 0, 0},
-
-    // Out of bounds.
-    {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
-    {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
-    {nullptr, false, 0, 0},
-};
-
-struct uint64_test_case {
-  const char* str;
-  bool expect_ok;
-  int base;
-  uint64_t expected;
-} const strtouint64_test_cases[] = {
-    {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
-    {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
-
-    {"0", true, 16, 0},
-    {"000", true, 0, 0},
-    {"0", true, 0, 0},
-    {" \t\n 0xffffffffffffffff", true, 16,
-     std::numeric_limits<uint64_t>::max()},
-
-    {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
-    {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
-
-    {"12845670123456701234", false, 8, 0},
-
-    // Base-10 version.
-    {"34234324487834466", true, 0, int64_t{34234324487834466}},
-
-    {" \t\n 18446744073709551615", true, 0,
-     std::numeric_limits<uint64_t>::max()},
-
-    {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
-
-    {" \f\v 46", true, 10, 46},  // must accept weird whitespace
-
-    // Unusual base
-    {"0", true, 3, 0},
-    {"2", true, 3, 2},
-    {"11", true, 3, 4},
-
-    {"0", true, 0, 0},
-
-    // Invalid uints.
-    {"", false, 0, 0},
-    {"  ", false, 0, 0},
-    {"abc", false, 0, 0},
-    {"34234324487834466a", false, 0, 0},
-    {"34234487834466.3", false, 0, 0},
-    {"-1", false, 0, 0},
-    {"   -123", false, 0, 0},
-    {" \t\n -123", false, 0, 0},
-
-    // Out of bounds.
-    {"18446744073709551616", false, 10, 0},
-    {"18446744073709551616", false, 0, 0},
-    {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
-    {"0X10000000000000000", false, 16,
-     std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
-    {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
-    {"0X10000000000000000", false, 0,
-     std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
-
-    {"0x1234", true, 16, 0x1234},
-
-    // Base-10 std::string version.
-    {"1234", true, 0, 1234},
-    {nullptr, false, 0, 0},
-};
-
-}  // namespace
diff --git a/absl/strings/internal/ostringstream_benchmark.cc b/absl/strings/internal/ostringstream_benchmark.cc
new file mode 100644
index 000000000000..c93f96909d8b
--- /dev/null
+++ b/absl/strings/internal/ostringstream_benchmark.cc
@@ -0,0 +1,106 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/ostringstream.h"
+
+#include <sstream>
+#include <string>
+
+#include "benchmark/benchmark.h"
+
+namespace {
+
+enum StringType {
+  kNone,
+  kStdString,
+};
+
+// Benchmarks for std::ostringstream.
+template <StringType kOutput>
+void BM_StdStream(benchmark::State& state) {
+  const int num_writes = state.range(0);
+  const int bytes_per_write = state.range(1);
+  const std::string payload(bytes_per_write, 'x');
+  for (auto _ : state) {
+    std::ostringstream strm;
+    benchmark::DoNotOptimize(strm);
+    for (int i = 0; i != num_writes; ++i) {
+      strm << payload;
+    }
+    switch (kOutput) {
+      case kNone: {
+        break;
+      }
+      case kStdString: {
+        std::string s = strm.str();
+        benchmark::DoNotOptimize(s);
+        break;
+      }
+    }
+  }
+}
+
+// Create the stream, optionally write to it, then destroy it.
+BENCHMARK_TEMPLATE(BM_StdStream, kNone)
+    ->ArgPair(0, 0)
+    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO
+    ->ArgPair(1, 256)  // 256 bytes requires heap allocation
+    ->ArgPair(1024, 256);
+// Create the stream, write to it, get std::string out, then destroy.
+BENCHMARK_TEMPLATE(BM_StdStream, kStdString)
+    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO
+    ->ArgPair(1, 256)  // 256 bytes requires heap allocation
+    ->ArgPair(1024, 256);
+
+// Benchmarks for OStringStream.
+template <StringType kOutput>
+void BM_CustomStream(benchmark::State& state) {
+  const int num_writes = state.range(0);
+  const int bytes_per_write = state.range(1);
+  const std::string payload(bytes_per_write, 'x');
+  for (auto _ : state) {
+    std::string out;
+    absl::strings_internal::OStringStream strm(&out);
+    benchmark::DoNotOptimize(strm);
+    for (int i = 0; i != num_writes; ++i) {
+      strm << payload;
+    }
+    switch (kOutput) {
+      case kNone: {
+        break;
+      }
+      case kStdString: {
+        std::string s = out;
+        benchmark::DoNotOptimize(s);
+        break;
+      }
+    }
+  }
+}
+
+// Create the stream, optionally write to it, then destroy it.
+BENCHMARK_TEMPLATE(BM_CustomStream, kNone)
+    ->ArgPair(0, 0)
+    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO
+    ->ArgPair(1, 256)  // 256 bytes requires heap allocation
+    ->ArgPair(1024, 256);
+// Create the stream, write to it, get std::string out, then destroy.
+// It's not useful in practice to extract std::string from OStringStream; we
+// measure it for completeness.
+BENCHMARK_TEMPLATE(BM_CustomStream, kStdString)
+    ->ArgPair(1, 16)   // 16 bytes is small enough for SSO
+    ->ArgPair(1, 256)  // 256 bytes requires heap allocation
+    ->ArgPair(1024, 256);
+
+}  // namespace
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 75925e61f2c0..cf3c597266cf 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -52,12 +52,16 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
 //
 // Converts the given std::string (optionally followed or preceded by ASCII
 // whitespace) into a float, which may be rounded on overflow or underflow.
+// See http://en.cppreference.com/w/c/std::string/byte/strtof for details about the
+// allowed formats for `str`.
 ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* value);
 
 // SimpleAtod()
 //
 // Converts the given std::string (optionally followed or preceded by ASCII
 // whitespace) into a double, which may be rounded on overflow or underflow.
+// See http://en.cppreference.com/w/c/std::string/byte/strtof for details about the
+// allowed formats for `str`.
 ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* value);
 
 // SimpleAtob()
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index e372eea14ca8..24e7138cfae2 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -38,7 +38,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/strings/str_cat.h"
 
-#include "absl/strings/internal/numbers_test_common.inc"
+#include "absl/strings/internal/numbers_test_common.h"
 
 namespace {
 
@@ -48,6 +48,9 @@ using absl::numbers_internal::safe_strto64_base;
 using absl::numbers_internal::safe_strtou32_base;
 using absl::numbers_internal::safe_strtou64_base;
 using absl::numbers_internal::SixDigitsToBuffer;
+using absl::strings_internal::Itoa;
+using absl::strings_internal::strtouint32_test_cases;
+using absl::strings_internal::strtouint64_test_cases;
 using absl::SimpleAtoi;
 using testing::Eq;
 using testing::MatchesRegex;
@@ -654,8 +657,8 @@ TEST(stringtest, safe_strtou64_random) {
 }
 
 TEST(stringtest, safe_strtou32_base) {
-  for (int i = 0; strtouint32_test_cases[i].str != nullptr; ++i) {
-    const auto& e = strtouint32_test_cases[i];
+  for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
+    const auto& e = strtouint32_test_cases()[i];
     uint32_t value;
     EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base))
         << "str=\"" << e.str << "\" base=" << e.base;
@@ -667,8 +670,8 @@ TEST(stringtest, safe_strtou32_base) {
 }
 
 TEST(stringtest, safe_strtou32_base_length_delimited) {
-  for (int i = 0; strtouint32_test_cases[i].str != nullptr; ++i) {
-    const auto& e = strtouint32_test_cases[i];
+  for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
+    const auto& e = strtouint32_test_cases()[i];
     std::string tmp(e.str);
     tmp.append("12");  // Adds garbage at the end.
 
@@ -685,8 +688,8 @@ TEST(stringtest, safe_strtou32_base_length_delimited) {
 }
 
 TEST(stringtest, safe_strtou64_base) {
-  for (int i = 0; strtouint64_test_cases[i].str != nullptr; ++i) {
-    const auto& e = strtouint64_test_cases[i];
+  for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
+    const auto& e = strtouint64_test_cases()[i];
     uint64_t value;
     EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base))
         << "str=\"" << e.str << "\" base=" << e.base;
@@ -697,8 +700,8 @@ TEST(stringtest, safe_strtou64_base) {
 }
 
 TEST(stringtest, safe_strtou64_base_length_delimited) {
-  for (int i = 0; strtouint64_test_cases[i].str != nullptr; ++i) {
-    const auto& e = strtouint64_test_cases[i];
+  for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
+    const auto& e = strtouint64_test_cases()[i];
     std::string tmp(e.str);
     tmp.append("12");  // Adds garbage at the end.
 
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index 1791410c6e3a..b6df9e309c4f 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -138,5 +138,3 @@ void BM_DoubleToString_By_SixDigits(benchmark::State& state) {
 BENCHMARK(BM_DoubleToString_By_SixDigits);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_join_benchmark.cc b/absl/strings/str_join_benchmark.cc
index 79cad5e39300..7fb0e4973cb4 100644
--- a/absl/strings/str_join_benchmark.cc
+++ b/absl/strings/str_join_benchmark.cc
@@ -94,5 +94,3 @@ BENCHMARK(BM_JoinStreamable)
     ->ArgPair(256, 256);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 9dd72eb6e77c..e608de8d19e4 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -120,5 +120,3 @@ void BM_StrReplaceAll(benchmark::State& state) {
 BENCHMARK(BM_StrReplaceAll);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc
index c35787b7ef4b..326ff744ebd9 100644
--- a/absl/strings/str_split_benchmark.cc
+++ b/absl/strings/str_split_benchmark.cc
@@ -154,5 +154,3 @@ BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral);
 BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index c66f0fbd5430..fb46db18b3c3 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -327,5 +327,3 @@ void BM_AppendToStringNative(benchmark::State& state) {
 BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 5747d384d34e..c4b25ba70952 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -99,7 +99,10 @@ class Arg {
   // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
   Arg(const char* value)  // NOLINT(runtime/explicit)
       : piece_(absl::NullSafeStringView(value)) {}
-  Arg(const std::string& value)  // NOLINT(runtime/explicit)
+  template <typename Allocator>
+  Arg(  // NOLINT
+      const std::basic_string<char, std::char_traits<char>, Allocator>&
+          value) noexcept
       : piece_(value) {}
   Arg(absl::string_view value)  // NOLINT(runtime/explicit)
       : piece_(value) {}
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 2502c53fff2b..123536ea4d10 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -130,7 +130,7 @@ cc_test(
     deps = [
         ":graphcycles_internal",
         "//absl/base",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
@@ -176,7 +176,7 @@ cc_test(
         ":synchronization",
         ":thread_pool",
         "//absl/base",
-        "@com_github_google_benchmark//:benchmark",
+        "@com_github_google_benchmark//:benchmark_main",
     ],
 )
 
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index b4a1debe752e..a239c25c3a81 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -42,5 +42,3 @@ void BM_StressTest(benchmark::State& state) {
 BENCHMARK(BM_StressTest)->Range(2048, 1048576);
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index d91071b71bdd..30a523556c3d 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -92,5 +92,3 @@ BENCHMARK(BM_ContendedMutex)->Threads(1);
 BENCHMARK(BM_ContendedMutex)->ThreadPerCpu();
 
 }  // namespace
-
-BENCHMARK_MAIN();
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 7126f1410f8f..64cb99f73716 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -81,10 +81,6 @@ cc_test(
     ],
     copts = ABSL_TEST_COPTS,
     tags = [
-        "no_test_android_arm",
-        "no_test_android_arm64",
-        "no_test_android_x86",
-        "no_test_ios_x86_64",
         "no_test_loonix",
     ],
     deps = [
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 468470b4fb63..9f1ba21cf7e2 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -81,6 +81,11 @@ cc_test(
     size = "small",
     srcs = ["src/time_zone_format_test.cc"],
     data = [":zoneinfo"],
+    tags = [
+        "no_test_android_arm",
+        "no_test_android_arm64",
+        "no_test_android_x86",
+    ],
     deps = [
         ":civil_time",
         ":time_zone",
@@ -93,6 +98,11 @@ cc_test(
     size = "small",
     srcs = ["src/time_zone_lookup_test.cc"],
     data = [":zoneinfo"],
+    tags = [
+        "no_test_android_arm",
+        "no_test_android_arm64",
+        "no_test_android_x86",
+    ],
     deps = [
         ":civil_time",
         ":time_zone",
@@ -102,6 +112,24 @@ cc_test(
 
 ### benchmarks
 
+cc_test(
+    name = "cctz_benchmark",
+    srcs = [
+        "src/cctz_benchmark.cc",
+        "src/time_zone_if.h",
+        "src/time_zone_impl.h",
+        "src/time_zone_info.h",
+        "src/tzfile.h",
+    ],
+    linkstatic = 1,
+    tags = ["benchmark"],
+    deps = [
+        ":civil_time",
+        ":time_zone",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
 ### examples
 
 ### binaries
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
new file mode 100644
index 000000000000..f13cb4ee6b5f
--- /dev/null
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -0,0 +1,982 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <ctime>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
+#include "time_zone_impl.h"
+
+namespace {
+
+namespace cctz = absl::time_internal::cctz;
+
+void BM_Difference_Days(benchmark::State& state) {
+  const cctz::civil_day c(2014, 8, 22);
+  const cctz::civil_day epoch(1970, 1, 1);
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(c - epoch);
+  }
+}
+BENCHMARK(BM_Difference_Days);
+
+void BM_Step_Days(benchmark::State& state) {
+  const cctz::civil_day kStart(2014, 8, 22);
+  cctz::civil_day c = kStart;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(++c);
+  }
+}
+BENCHMARK(BM_Step_Days);
+
+const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+
+const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
+const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
+
+// A list of known time-zone names.
+// TODO: Refactor with src/time_zone_lookup_test.cc.
+const char* const kTimeZoneNames[] = {
+  "Africa/Abidjan",
+  "Africa/Accra",
+  "Africa/Addis_Ababa",
+  "Africa/Algiers",
+  "Africa/Asmara",
+  "Africa/Asmera",
+  "Africa/Bamako",
+  "Africa/Bangui",
+  "Africa/Banjul",
+  "Africa/Bissau",
+  "Africa/Blantyre",
+  "Africa/Brazzaville",
+  "Africa/Bujumbura",
+  "Africa/Cairo",
+  "Africa/Casablanca",
+  "Africa/Ceuta",
+  "Africa/Conakry",
+  "Africa/Dakar",
+  "Africa/Dar_es_Salaam",
+  "Africa/Djibouti",
+  "Africa/Douala",
+  "Africa/El_Aaiun",
+  "Africa/Freetown",
+  "Africa/Gaborone",
+  "Africa/Harare",
+  "Africa/Johannesburg",
+  "Africa/Juba",
+  "Africa/Kampala",
+  "Africa/Khartoum",
+  "Africa/Kigali",
+  "Africa/Kinshasa",
+  "Africa/Lagos",
+  "Africa/Libreville",
+  "Africa/Lome",
+  "Africa/Luanda",
+  "Africa/Lubumbashi",
+  "Africa/Lusaka",
+  "Africa/Malabo",
+  "Africa/Maputo",
+  "Africa/Maseru",
+  "Africa/Mbabane",
+  "Africa/Mogadishu",
+  "Africa/Monrovia",
+  "Africa/Nairobi",
+  "Africa/Ndjamena",
+  "Africa/Niamey",
+  "Africa/Nouakchott",
+  "Africa/Ouagadougou",
+  "Africa/Porto-Novo",
+  "Africa/Sao_Tome",
+  "Africa/Timbuktu",
+  "Africa/Tripoli",
+  "Africa/Tunis",
+  "Africa/Windhoek",
+  "America/Adak",
+  "America/Anchorage",
+  "America/Anguilla",
+  "America/Antigua",
+  "America/Araguaina",
+  "America/Argentina/Buenos_Aires",
+  "America/Argentina/Catamarca",
+  "America/Argentina/ComodRivadavia",
+  "America/Argentina/Cordoba",
+  "America/Argentina/Jujuy",
+  "America/Argentina/La_Rioja",
+  "America/Argentina/Mendoza",
+  "America/Argentina/Rio_Gallegos",
+  "America/Argentina/Salta",
+  "America/Argentina/San_Juan",
+  "America/Argentina/San_Luis",
+  "America/Argentina/Tucuman",
+  "America/Argentina/Ushuaia",
+  "America/Aruba",
+  "America/Asuncion",
+  "America/Atikokan",
+  "America/Atka",
+  "America/Bahia",
+  "America/Bahia_Banderas",
+  "America/Barbados",
+  "America/Belem",
+  "America/Belize",
+  "America/Blanc-Sablon",
+  "America/Boa_Vista",
+  "America/Bogota",
+  "America/Boise",
+  "America/Buenos_Aires",
+  "America/Cambridge_Bay",
+  "America/Campo_Grande",
+  "America/Cancun",
+  "America/Caracas",
+  "America/Catamarca",
+  "America/Cayenne",
+  "America/Cayman",
+  "America/Chicago",
+  "America/Chihuahua",
+  "America/Coral_Harbour",
+  "America/Cordoba",
+  "America/Costa_Rica",
+  "America/Creston",
+  "America/Cuiaba",
+  "America/Curacao",
+  "America/Danmarkshavn",
+  "America/Dawson",
+  "America/Dawson_Creek",
+  "America/Denver",
+  "America/Detroit",
+  "America/Dominica",
+  "America/Edmonton",
+  "America/Eirunepe",
+  "America/El_Salvador",
+  "America/Ensenada",
+  "America/Fort_Nelson",
+  "America/Fort_Wayne",
+  "America/Fortaleza",
+  "America/Glace_Bay",
+  "America/Godthab",
+  "America/Goose_Bay",
+  "America/Grand_Turk",
+  "America/Grenada",
+  "America/Guadeloupe",
+  "America/Guatemala",
+  "America/Guayaquil",
+  "America/Guyana",
+  "America/Halifax",
+  "America/Havana",
+  "America/Hermosillo",
+  "America/Indiana/Indianapolis",
+  "America/Indiana/Knox",
+  "America/Indiana/Marengo",
+  "America/Indiana/Petersburg",
+  "America/Indiana/Tell_City",
+  "America/Indiana/Vevay",
+  "America/Indiana/Vincennes",
+  "America/Indiana/Winamac",
+  "America/Indianapolis",
+  "America/Inuvik",
+  "America/Iqaluit",
+  "America/Jamaica",
+  "America/Jujuy",
+  "America/Juneau",
+  "America/Kentucky/Louisville",
+  "America/Kentucky/Monticello",
+  "America/Knox_IN",
+  "America/Kralendijk",
+  "America/La_Paz",
+  "America/Lima",
+  "America/Los_Angeles",
+  "America/Louisville",
+  "America/Lower_Princes",
+  "America/Maceio",
+  "America/Managua",
+  "America/Manaus",
+  "America/Marigot",
+  "America/Martinique",
+  "America/Matamoros",
+  "America/Mazatlan",
+  "America/Mendoza",
+  "America/Menominee",
+  "America/Merida",
+  "America/Metlakatla",
+  "America/Mexico_City",
+  "America/Miquelon",
+  "America/Moncton",
+  "America/Monterrey",
+  "America/Montevideo",
+  "America/Montreal",
+  "America/Montserrat",
+  "America/Nassau",
+  "America/New_York",
+  "America/Nipigon",
+  "America/Nome",
+  "America/Noronha",
+  "America/North_Dakota/Beulah",
+  "America/North_Dakota/Center",
+  "America/North_Dakota/New_Salem",
+  "America/Ojinaga",
+  "America/Panama",
+  "America/Pangnirtung",
+  "America/Paramaribo",
+  "America/Phoenix",
+  "America/Port-au-Prince",
+  "America/Port_of_Spain",
+  "America/Porto_Acre",
+  "America/Porto_Velho",
+  "America/Puerto_Rico",
+  "America/Punta_Arenas",
+  "America/Rainy_River",
+  "America/Rankin_Inlet",
+  "America/Recife",
+  "America/Regina",
+  "America/Resolute",
+  "America/Rio_Branco",
+  "America/Rosario",
+  "America/Santa_Isabel",
+  "America/Santarem",
+  "America/Santiago",
+  "America/Santo_Domingo",
+  "America/Sao_Paulo",
+  "America/Scoresbysund",
+  "America/Shiprock",
+  "America/Sitka",
+  "America/St_Barthelemy",
+  "America/St_Johns",
+  "America/St_Kitts",
+  "America/St_Lucia",
+  "America/St_Thomas",
+  "America/St_Vincent",
+  "America/Swift_Current",
+  "America/Tegucigalpa",
+  "America/Thule",
+  "America/Thunder_Bay",
+  "America/Tijuana",
+  "America/Toronto",
+  "America/Tortola",
+  "America/Vancouver",
+  "America/Virgin",
+  "America/Whitehorse",
+  "America/Winnipeg",
+  "America/Yakutat",
+  "America/Yellowknife",
+  "Antarctica/Casey",
+  "Antarctica/Davis",
+  "Antarctica/DumontDUrville",
+  "Antarctica/Macquarie",
+  "Antarctica/Mawson",
+  "Antarctica/McMurdo",
+  "Antarctica/Palmer",
+  "Antarctica/Rothera",
+  "Antarctica/South_Pole",
+  "Antarctica/Syowa",
+  "Antarctica/Troll",
+  "Antarctica/Vostok",
+  "Arctic/Longyearbyen",
+  "Asia/Aden",
+  "Asia/Almaty",
+  "Asia/Amman",
+  "Asia/Anadyr",
+  "Asia/Aqtau",
+  "Asia/Aqtobe",
+  "Asia/Ashgabat",
+  "Asia/Ashkhabad",
+  "Asia/Atyrau",
+  "Asia/Baghdad",
+  "Asia/Bahrain",
+  "Asia/Baku",
+  "Asia/Bangkok",
+  "Asia/Barnaul",
+  "Asia/Beirut",
+  "Asia/Bishkek",
+  "Asia/Brunei",
+  "Asia/Calcutta",
+  "Asia/Chita",
+  "Asia/Choibalsan",
+  "Asia/Chongqing",
+  "Asia/Chungking",
+  "Asia/Colombo",
+  "Asia/Dacca",
+  "Asia/Damascus",
+  "Asia/Dhaka",
+  "Asia/Dili",
+  "Asia/Dubai",
+  "Asia/Dushanbe",
+  "Asia/Famagusta",
+  "Asia/Gaza",
+  "Asia/Harbin",
+  "Asia/Hebron",
+  "Asia/Ho_Chi_Minh",
+  "Asia/Hong_Kong",
+  "Asia/Hovd",
+  "Asia/Irkutsk",
+  "Asia/Istanbul",
+  "Asia/Jakarta",
+  "Asia/Jayapura",
+  "Asia/Jerusalem",
+  "Asia/Kabul",
+  "Asia/Kamchatka",
+  "Asia/Karachi",
+  "Asia/Kashgar",
+  "Asia/Kathmandu",
+  "Asia/Katmandu",
+  "Asia/Khandyga",
+  "Asia/Kolkata",
+  "Asia/Krasnoyarsk",
+  "Asia/Kuala_Lumpur",
+  "Asia/Kuching",
+  "Asia/Kuwait",
+  "Asia/Macao",
+  "Asia/Macau",
+  "Asia/Magadan",
+  "Asia/Makassar",
+  "Asia/Manila",
+  "Asia/Muscat",
+  "Asia/Nicosia",
+  "Asia/Novokuznetsk",
+  "Asia/Novosibirsk",
+  "Asia/Omsk",
+  "Asia/Oral",
+  "Asia/Phnom_Penh",
+  "Asia/Pontianak",
+  "Asia/Pyongyang",
+  "Asia/Qatar",
+  "Asia/Qyzylorda",
+  "Asia/Rangoon",
+  "Asia/Riyadh",
+  "Asia/Saigon",
+  "Asia/Sakhalin",
+  "Asia/Samarkand",
+  "Asia/Seoul",
+  "Asia/Shanghai",
+  "Asia/Singapore",
+  "Asia/Srednekolymsk",
+  "Asia/Taipei",
+  "Asia/Tashkent",
+  "Asia/Tbilisi",
+  "Asia/Tehran",
+  "Asia/Tel_Aviv",
+  "Asia/Thimbu",
+  "Asia/Thimphu",
+  "Asia/Tokyo",
+  "Asia/Tomsk",
+  "Asia/Ujung_Pandang",
+  "Asia/Ulaanbaatar",
+  "Asia/Ulan_Bator",
+  "Asia/Urumqi",
+  "Asia/Ust-Nera",
+  "Asia/Vientiane",
+  "Asia/Vladivostok",
+  "Asia/Yakutsk",
+  "Asia/Yangon",
+  "Asia/Yekaterinburg",
+  "Asia/Yerevan",
+  "Atlantic/Azores",
+  "Atlantic/Bermuda",
+  "Atlantic/Canary",
+  "Atlantic/Cape_Verde",
+  "Atlantic/Faeroe",
+  "Atlantic/Faroe",
+  "Atlantic/Jan_Mayen",
+  "Atlantic/Madeira",
+  "Atlantic/Reykjavik",
+  "Atlantic/South_Georgia",
+  "Atlantic/St_Helena",
+  "Atlantic/Stanley",
+  "Australia/ACT",
+  "Australia/Adelaide",
+  "Australia/Brisbane",
+  "Australia/Broken_Hill",
+  "Australia/Canberra",
+  "Australia/Currie",
+  "Australia/Darwin",
+  "Australia/Eucla",
+  "Australia/Hobart",
+  "Australia/LHI",
+  "Australia/Lindeman",
+  "Australia/Lord_Howe",
+  "Australia/Melbourne",
+  "Australia/NSW",
+  "Australia/North",
+  "Australia/Perth",
+  "Australia/Queensland",
+  "Australia/South",
+  "Australia/Sydney",
+  "Australia/Tasmania",
+  "Australia/Victoria",
+  "Australia/West",
+  "Australia/Yancowinna",
+  "Brazil/Acre",
+  "Brazil/DeNoronha",
+  "Brazil/East",
+  "Brazil/West",
+  "CET",
+  "CST6CDT",
+  "Canada/Atlantic",
+  "Canada/Central",
+  "Canada/Eastern",
+  "Canada/Mountain",
+  "Canada/Newfoundland",
+  "Canada/Pacific",
+  "Canada/Saskatchewan",
+  "Canada/Yukon",
+  "Chile/Continental",
+  "Chile/EasterIsland",
+  "Cuba",
+  "EET",
+  "EST",
+  "EST5EDT",
+  "Egypt",
+  "Eire",
+  "Etc/GMT",
+  "Etc/GMT+0",
+  "Etc/GMT+1",
+  "Etc/GMT+10",
+  "Etc/GMT+11",
+  "Etc/GMT+12",
+  "Etc/GMT+2",
+  "Etc/GMT+3",
+  "Etc/GMT+4",
+  "Etc/GMT+5",
+  "Etc/GMT+6",
+  "Etc/GMT+7",
+  "Etc/GMT+8",
+  "Etc/GMT+9",
+  "Etc/GMT-0",
+  "Etc/GMT-1",
+  "Etc/GMT-10",
+  "Etc/GMT-11",
+  "Etc/GMT-12",
+  "Etc/GMT-13",
+  "Etc/GMT-14",
+  "Etc/GMT-2",
+  "Etc/GMT-3",
+  "Etc/GMT-4",
+  "Etc/GMT-5",
+  "Etc/GMT-6",
+  "Etc/GMT-7",
+  "Etc/GMT-8",
+  "Etc/GMT-9",
+  "Etc/GMT0",
+  "Etc/Greenwich",
+  "Etc/UCT",
+  "Etc/UTC",
+  "Etc/Universal",
+  "Etc/Zulu",
+  "Europe/Amsterdam",
+  "Europe/Andorra",
+  "Europe/Astrakhan",
+  "Europe/Athens",
+  "Europe/Belfast",
+  "Europe/Belgrade",
+  "Europe/Berlin",
+  "Europe/Bratislava",
+  "Europe/Brussels",
+  "Europe/Bucharest",
+  "Europe/Budapest",
+  "Europe/Busingen",
+  "Europe/Chisinau",
+  "Europe/Copenhagen",
+  "Europe/Dublin",
+  "Europe/Gibraltar",
+  "Europe/Guernsey",
+  "Europe/Helsinki",
+  "Europe/Isle_of_Man",
+  "Europe/Istanbul",
+  "Europe/Jersey",
+  "Europe/Kaliningrad",
+  "Europe/Kiev",
+  "Europe/Kirov",
+  "Europe/Lisbon",
+  "Europe/Ljubljana",
+  "Europe/London",
+  "Europe/Luxembourg",
+  "Europe/Madrid",
+  "Europe/Malta",
+  "Europe/Mariehamn",
+  "Europe/Minsk",
+  "Europe/Monaco",
+  "Europe/Moscow",
+  "Europe/Nicosia",
+  "Europe/Oslo",
+  "Europe/Paris",
+  "Europe/Podgorica",
+  "Europe/Prague",
+  "Europe/Riga",
+  "Europe/Rome",
+  "Europe/Samara",
+  "Europe/San_Marino",
+  "Europe/Sarajevo",
+  "Europe/Saratov",
+  "Europe/Simferopol",
+  "Europe/Skopje",
+  "Europe/Sofia",
+  "Europe/Stockholm",
+  "Europe/Tallinn",
+  "Europe/Tirane",
+  "Europe/Tiraspol",
+  "Europe/Ulyanovsk",
+  "Europe/Uzhgorod",
+  "Europe/Vaduz",
+  "Europe/Vatican",
+  "Europe/Vienna",
+  "Europe/Vilnius",
+  "Europe/Volgograd",
+  "Europe/Warsaw",
+  "Europe/Zagreb",
+  "Europe/Zaporozhye",
+  "Europe/Zurich",
+  "GB",
+  "GB-Eire",
+  "GMT",
+  "GMT+0",
+  "GMT-0",
+  "GMT0",
+  "Greenwich",
+  "HST",
+  "Hongkong",
+  "Iceland",
+  "Indian/Antananarivo",
+  "Indian/Chagos",
+  "Indian/Christmas",
+  "Indian/Cocos",
+  "Indian/Comoro",
+  "Indian/Kerguelen",
+  "Indian/Mahe",
+  "Indian/Maldives",
+  "Indian/Mauritius",
+  "Indian/Mayotte",
+  "Indian/Reunion",
+  "Iran",
+  "Israel",
+  "Jamaica",
+  "Japan",
+  "Kwajalein",
+  "Libya",
+  "MET",
+  "MST",
+  "MST7MDT",
+  "Mexico/BajaNorte",
+  "Mexico/BajaSur",
+  "Mexico/General",
+  "NZ",
+  "NZ-CHAT",
+  "Navajo",
+  "PRC",
+  "PST8PDT",
+  "Pacific/Apia",
+  "Pacific/Auckland",
+  "Pacific/Bougainville",
+  "Pacific/Chatham",
+  "Pacific/Chuuk",
+  "Pacific/Easter",
+  "Pacific/Efate",
+  "Pacific/Enderbury",
+  "Pacific/Fakaofo",
+  "Pacific/Fiji",
+  "Pacific/Funafuti",
+  "Pacific/Galapagos",
+  "Pacific/Gambier",
+  "Pacific/Guadalcanal",
+  "Pacific/Guam",
+  "Pacific/Honolulu",
+  "Pacific/Johnston",
+  "Pacific/Kiritimati",
+  "Pacific/Kosrae",
+  "Pacific/Kwajalein",
+  "Pacific/Majuro",
+  "Pacific/Marquesas",
+  "Pacific/Midway",
+  "Pacific/Nauru",
+  "Pacific/Niue",
+  "Pacific/Norfolk",
+  "Pacific/Noumea",
+  "Pacific/Pago_Pago",
+  "Pacific/Palau",
+  "Pacific/Pitcairn",
+  "Pacific/Pohnpei",
+  "Pacific/Ponape",
+  "Pacific/Port_Moresby",
+  "Pacific/Rarotonga",
+  "Pacific/Saipan",
+  "Pacific/Samoa",
+  "Pacific/Tahiti",
+  "Pacific/Tarawa",
+  "Pacific/Tongatapu",
+  "Pacific/Truk",
+  "Pacific/Wake",
+  "Pacific/Wallis",
+  "Pacific/Yap",
+  "Poland",
+  "Portugal",
+  "ROC",
+  "ROK",
+  "Singapore",
+  "Turkey",
+  "UCT",
+  "US/Alaska",
+  "US/Aleutian",
+  "US/Arizona",
+  "US/Central",
+  "US/East-Indiana",
+  "US/Eastern",
+  "US/Hawaii",
+  "US/Indiana-Starke",
+  "US/Michigan",
+  "US/Mountain",
+  "US/Pacific",
+  "US/Samoa",
+  "UTC",
+  "Universal",
+  "W-SU",
+  "WET",
+  "Zulu",
+  nullptr
+};
+
+std::vector<std::string> AllTimeZoneNames() {
+  std::vector<std::string> names;
+  for (const char* const* namep = kTimeZoneNames; *namep != nullptr; ++namep) {
+    names.push_back(std::string("file:") + *namep);
+  }
+  assert(!names.empty());
+
+  std::mt19937 urbg(42);  // a UniformRandomBitGenerator with fixed seed
+  std::shuffle(names.begin(), names.end(), urbg);
+  return names;
+}
+
+cctz::time_zone TestTimeZone() {
+  cctz::time_zone tz;
+  cctz::load_time_zone("America/Los_Angeles", &tz);
+  return tz;
+}
+
+void BM_Zone_LoadUTCTimeZoneFirst(benchmark::State& state) {
+  cctz::time_zone tz;
+  cctz::load_time_zone("UTC", &tz);  // in case we're first
+  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadUTCTimeZoneFirst);
+
+void BM_Zone_LoadUTCTimeZoneLast(benchmark::State& state) {
+  cctz::time_zone tz;
+  for (const auto& name : AllTimeZoneNames()) {
+    cctz::load_time_zone(name, &tz);  // prime cache
+  }
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::load_time_zone("UTC", &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadUTCTimeZoneLast);
+
+void BM_Zone_LoadTimeZoneFirst(benchmark::State& state) {
+  cctz::time_zone tz = cctz::utc_time_zone();  // in case we're first
+  const std::string name = "file:America/Los_Angeles";
+  while (state.KeepRunning()) {
+    state.PauseTiming();
+    cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+    state.ResumeTiming();
+    benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadTimeZoneFirst);
+
+void BM_Zone_LoadTimeZoneCached(benchmark::State& state) {
+  cctz::time_zone tz = cctz::utc_time_zone();  // in case we're first
+  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+  const std::string name = "file:America/Los_Angeles";
+  cctz::load_time_zone(name, &tz);  // prime cache
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::load_time_zone(name, &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadTimeZoneCached);
+
+void BM_Zone_LoadLocalTimeZoneCached(benchmark::State& state) {
+  cctz::utc_time_zone();  // in case we're first
+  cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+  cctz::local_time_zone();  // prime cache
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::local_time_zone());
+  }
+}
+BENCHMARK(BM_Zone_LoadLocalTimeZoneCached);
+
+void BM_Zone_LoadAllTimeZonesFirst(benchmark::State& state) {
+  cctz::time_zone tz;
+  const std::vector<std::string> names = AllTimeZoneNames();
+  for (auto index = names.size(); state.KeepRunning(); ++index) {
+    if (index == names.size()) {
+      index = 0;
+    }
+    if (index == 0) {
+      state.PauseTiming();
+      cctz::time_zone::Impl::ClearTimeZoneMapTestOnly();
+      state.ResumeTiming();
+    }
+    benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadAllTimeZonesFirst);
+
+void BM_Zone_LoadAllTimeZonesCached(benchmark::State& state) {
+  cctz::time_zone tz;
+  const std::vector<std::string> names = AllTimeZoneNames();
+  for (const auto& name : names) {
+    cctz::load_time_zone(name, &tz);  // prime cache
+  }
+  for (auto index = names.size(); state.KeepRunning(); ++index) {
+    if (index == names.size()) {
+      index = 0;
+    }
+    benchmark::DoNotOptimize(cctz::load_time_zone(names[index], &tz));
+  }
+}
+BENCHMARK(BM_Zone_LoadAllTimeZonesCached);
+
+void BM_Zone_TimeZoneImplGetImplicit(benchmark::State& state) {
+  cctz::time_zone tz;  // implicit UTC
+  cctz::time_zone::Impl::get(tz);
+  while (state.KeepRunning()) {
+    cctz::time_zone::Impl::get(tz);
+  }
+}
+BENCHMARK(BM_Zone_TimeZoneImplGetImplicit);
+
+void BM_Zone_TimeZoneImplGetExplicit(benchmark::State& state) {
+  cctz::time_zone tz = cctz::utc_time_zone();  // explicit UTC
+  cctz::time_zone::Impl::get(tz);
+  while (state.KeepRunning()) {
+    cctz::time_zone::Impl::get(tz);
+  }
+}
+BENCHMARK(BM_Zone_TimeZoneImplGetExplicit);
+
+void BM_Zone_UTCTimeZone(benchmark::State& state) {
+  cctz::time_zone tz;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::utc_time_zone());
+  }
+}
+BENCHMARK(BM_Zone_UTCTimeZone);
+
+// In each "ToDateTime" benchmark we switch between two instants
+// separated by at least one transition in order to defeat any
+// internal caching of previous results (e.g., see local_time_hint_).
+//
+// The "UTC" variants use UTC instead of the Google/local time zone.
+
+void BM_Time_ToDateTime_CCTZ(benchmark::State& state) {
+  const cctz::time_zone tz = TestTimeZone();
+  std::chrono::system_clock::time_point tp =
+      std::chrono::system_clock::from_time_t(1384569027);
+  std::chrono::system_clock::time_point tp2 =
+      std::chrono::system_clock::from_time_t(1418962578);
+  while (state.KeepRunning()) {
+    std::swap(tp, tp2);
+    tp += std::chrono::seconds(1);
+    benchmark::DoNotOptimize(cctz::convert(tp, tz));
+  }
+}
+BENCHMARK(BM_Time_ToDateTime_CCTZ);
+
+void BM_Time_ToDateTime_Libc(benchmark::State& state) {
+  // No timezone support, so just use localtime.
+  time_t t = 1384569027;
+  time_t t2 = 1418962578;
+  struct tm tm;
+  while (state.KeepRunning()) {
+    std::swap(t, t2);
+    t += 1;
+#if defined(_WIN32) || defined(_WIN64)
+    benchmark::DoNotOptimize(localtime_s(&tm, &t));
+#else
+    benchmark::DoNotOptimize(localtime_r(&t, &tm));
+#endif
+  }
+}
+BENCHMARK(BM_Time_ToDateTime_Libc);
+
+void BM_Time_ToDateTimeUTC_CCTZ(benchmark::State& state) {
+  const cctz::time_zone tz = cctz::utc_time_zone();
+  std::chrono::system_clock::time_point tp =
+      std::chrono::system_clock::from_time_t(1384569027);
+  while (state.KeepRunning()) {
+    tp += std::chrono::seconds(1);
+    benchmark::DoNotOptimize(cctz::convert(tp, tz));
+  }
+}
+BENCHMARK(BM_Time_ToDateTimeUTC_CCTZ);
+
+void BM_Time_ToDateTimeUTC_Libc(benchmark::State& state) {
+  time_t t = 1384569027;
+  struct tm tm;
+  while (state.KeepRunning()) {
+    t += 1;
+#if defined(_WIN32) || defined(_WIN64)
+    benchmark::DoNotOptimize(gmtime_s(&tm, &t));
+#else
+    benchmark::DoNotOptimize(gmtime_r(&t, &tm));
+#endif
+  }
+}
+BENCHMARK(BM_Time_ToDateTimeUTC_Libc);
+
+// In each "FromDateTime" benchmark we switch between two YMDhms
+// values separated by at least one transition in order to defeat any
+// internal caching of previous results (e.g., see time_local_hint_).
+//
+// The "UTC" variants use UTC instead of the Google/local time zone.
+// The "Day0" variants require normalization of the day of month.
+
+void BM_Time_FromDateTime_CCTZ(benchmark::State& state) {
+  const cctz::time_zone tz = TestTimeZone();
+  int i = 0;
+  while (state.KeepRunning()) {
+    if ((i++ & 1) == 0) {
+      benchmark::DoNotOptimize(
+          cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));
+    } else {
+      benchmark::DoNotOptimize(
+          cctz::convert(cctz::civil_second(2013, 11, 15, 18, 30, 27), tz));
+    }
+  }
+}
+BENCHMARK(BM_Time_FromDateTime_CCTZ);
+
+void BM_Time_FromDateTime_Libc(benchmark::State& state) {
+  // No timezone support, so just use localtime.
+  int i = 0;
+  while (state.KeepRunning()) {
+    struct tm tm;
+    if ((i++ & 1) == 0) {
+      tm.tm_year = 2014 - 1900;
+      tm.tm_mon = 12 - 1;
+      tm.tm_mday = 18;
+      tm.tm_hour = 20;
+      tm.tm_min = 16;
+      tm.tm_sec = 18;
+    } else {
+      tm.tm_year = 2013 - 1900;
+      tm.tm_mon = 11 - 1;
+      tm.tm_mday = 15;
+      tm.tm_hour = 18;
+      tm.tm_min = 30;
+      tm.tm_sec = 27;
+    }
+    tm.tm_isdst = -1;
+    benchmark::DoNotOptimize(mktime(&tm));
+  }
+}
+BENCHMARK(BM_Time_FromDateTime_Libc);
+
+void BM_Time_FromDateTimeUTC_CCTZ(benchmark::State& state) {
+  const cctz::time_zone tz = cctz::utc_time_zone();
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(
+        cctz::convert(cctz::civil_second(2014, 12, 18, 20, 16, 18), tz));
+  }
+}
+BENCHMARK(BM_Time_FromDateTimeUTC_CCTZ);
+
+// There is no BM_Time_FromDateTimeUTC_Libc.
+
+void BM_Time_FromDateTimeDay0_CCTZ(benchmark::State& state) {
+  const cctz::time_zone tz = TestTimeZone();
+  int i = 0;
+  while (state.KeepRunning()) {
+    if ((i++ & 1) == 0) {
+      benchmark::DoNotOptimize(
+          cctz::convert(cctz::civil_second(2014, 12, 0, 20, 16, 18), tz));
+    } else {
+      benchmark::DoNotOptimize(
+          cctz::convert(cctz::civil_second(2013, 11, 0, 18, 30, 27), tz));
+    }
+  }
+}
+BENCHMARK(BM_Time_FromDateTimeDay0_CCTZ);
+
+void BM_Time_FromDateTimeDay0_Libc(benchmark::State& state) {
+  // No timezone support, so just use localtime.
+  int i = 0;
+  while (state.KeepRunning()) {
+    struct tm tm;
+    if ((i++ & 1) == 0) {
+      tm.tm_year = 2014 - 1900;
+      tm.tm_mon = 12 - 1;
+      tm.tm_mday = 0;
+      tm.tm_hour = 20;
+      tm.tm_min = 16;
+      tm.tm_sec = 18;
+    } else {
+      tm.tm_year = 2013 - 1900;
+      tm.tm_mon = 11 - 1;
+      tm.tm_mday = 0;
+      tm.tm_hour = 18;
+      tm.tm_min = 30;
+      tm.tm_sec = 27;
+    }
+    tm.tm_isdst = -1;
+    benchmark::DoNotOptimize(mktime(&tm));
+  }
+}
+BENCHMARK(BM_Time_FromDateTimeDay0_Libc);
+
+const char* const kFormats[] = {
+    RFC1123_full,         // 0
+    RFC1123_no_wday,      // 1
+    RFC3339_full,         // 2
+    RFC3339_sec,          // 3
+    "%Y-%m-%dT%H:%M:%S",  // 4
+    "%Y-%m-%d",           // 5
+};
+const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
+
+void BM_Format_FormatTime(benchmark::State& state) {
+  const std::string fmt = kFormats[state.range(0)];
+  state.SetLabel(fmt);
+  const cctz::time_zone tz = TestTimeZone();
+  const std::chrono::system_clock::time_point tp =
+      cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +
+      std::chrono::microseconds(1);
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::format(fmt, tp, tz));
+  }
+}
+BENCHMARK(BM_Format_FormatTime)->DenseRange(0, kNumFormats - 1);
+
+void BM_Format_ParseTime(benchmark::State& state) {
+  const std::string fmt = kFormats[state.range(0)];
+  state.SetLabel(fmt);
+  const cctz::time_zone tz = TestTimeZone();
+  std::chrono::system_clock::time_point tp =
+      cctz::convert(cctz::civil_second(1977, 6, 28, 9, 8, 7), tz) +
+      std::chrono::microseconds(1);
+  const std::string when = cctz::format(fmt, tp, tz);
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(cctz::parse(fmt, when, tz, &tp));
+  }
+}
+BENCHMARK(BM_Format_ParseTime)->DenseRange(0, kNumFormats - 1);
+
+}  // namespace
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 6cea0360dd0e..3a5f19ac8b1f 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -463,8 +463,13 @@ TEST(Format, ExtendedSecondOffset) {
 
   EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
   tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
-  TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
-  TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
+  if (tz.lookup(tp).offset == 4 * 60 * 60) {
+    // We're likely dealing with zoneinfo that doesn't support really old
+    // timestamps, so Europe/Moscow never looks to be on local mean time.
+  } else {
+    TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
+    TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
+  }
   tp += seconds(1);
   TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
 }
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index f8d53c263bab..c26c68d0b35f 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -193,6 +193,20 @@ cc_test(
     ],
 )
 
+cc_test(
+    name = "optional_exception_safety_test",
+    srcs = [
+        "optional_exception_safety_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
+    deps = [
+        ":optional",
+        "//absl/base:exception_safety_testing",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+
 cc_library(
     name = "variant",
     srcs = ["internal/variant.h"],
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index fbd8374031da..2f2e3a778089 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -209,3 +209,20 @@ absl_test(
 )
 
 
+# test optional_exception_safety_test
+set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
+set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
+  absl::optional
+  absl_base_internal_exception_safety_testing
+)
+
+absl_test(
+  TARGET
+    optional_exception_safety_test
+  SOURCES
+    ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
+  PUBLIC_LIBRARIES
+    ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
+  PRIVATE_COMPILE_FLAGS
+    ${ABSL_EXCEPTIONS_FLAG}
+)
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
new file mode 100644
index 000000000000..7f6348e1b8e1
--- /dev/null
+++ b/absl/types/optional_exception_safety_test.cc
@@ -0,0 +1,284 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/optional.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/exception_safety_testing.h"
+
+namespace absl {
+
+namespace {
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::MakeExceptionSafetyTester;
+
+using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using Optional = absl::optional<Thrower>;
+
+using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveOptional = absl::optional<MoveThrower>;
+
+constexpr int kInitialInteger = 5;
+constexpr int kUpdatedInteger = 10;
+
+template <typename OptionalT>
+bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try {
+  return (static_cast<void>(optional.value()), false);
+} catch (absl::bad_optional_access) {
+  return true;
+}
+
+template <typename OptionalT>
+AssertionResult CheckInvariants(OptionalT* optional_ptr) {
+  // Check the current state post-throw for validity
+  auto& optional = *optional_ptr;
+
+  if (optional.has_value() && ValueThrowsBadOptionalAccess(optional)) {
+    return AssertionFailure()
+           << "Optional with value should not throw bad_optional_access when "
+              "accessing the value.";
+  }
+  if (!optional.has_value() && !ValueThrowsBadOptionalAccess(optional)) {
+    return AssertionFailure()
+           << "Optional without a value should throw bad_optional_access when "
+              "accessing the value.";
+  }
+
+  // Reset to a known state
+  optional.reset();
+
+  // Confirm that the known post-reset state is valid
+  if (optional.has_value()) {
+    return AssertionFailure()
+           << "Optional should not contain a value after being reset.";
+  }
+  if (!ValueThrowsBadOptionalAccess(optional)) {
+    return AssertionFailure() << "Optional should throw bad_optional_access "
+                                 "when accessing the value after being reset.";
+  }
+
+  return AssertionSuccess();
+}
+
+template <typename OptionalT>
+AssertionResult CheckDisengaged(OptionalT* optional_ptr) {
+  auto& optional = *optional_ptr;
+
+  if (optional.has_value()) {
+    return AssertionFailure()
+           << "Expected optional to not contain a value but a value was found.";
+  }
+
+  return AssertionSuccess();
+}
+
+template <typename OptionalT>
+AssertionResult CheckEngaged(OptionalT* optional_ptr) {
+  auto& optional = *optional_ptr;
+
+  if (!optional.has_value()) {
+    return AssertionFailure()
+           << "Expected optional to contain a value but no value was found.";
+  }
+
+  return AssertionSuccess();
+}
+
+TEST(OptionalExceptionSafety, ThrowingConstructors) {
+  auto thrower_nonempty = Optional(Thrower(kInitialInteger));
+  testing::TestThrowingCtor<Optional>(thrower_nonempty);
+
+  auto integer_nonempty = absl::optional<int>(kInitialInteger);
+  testing::TestThrowingCtor<Optional>(integer_nonempty);
+  testing::TestThrowingCtor<Optional>(std::move(integer_nonempty));  // NOLINT
+
+  testing::TestThrowingCtor<Optional>(kInitialInteger);
+  using ThrowerVec = std::vector<Thrower, testing::ThrowingAllocator<Thrower>>;
+  testing::TestThrowingCtor<absl::optional<ThrowerVec>>(
+      absl::in_place,
+      std::initializer_list<Thrower>{Thrower(), Thrower(), Thrower()},
+      testing::ThrowingAllocator<Thrower>());
+}
+
+TEST(OptionalExceptionSafety, NothrowConstructors) {
+  // This constructor is marked noexcept. If it throws, the program will
+  // terminate.
+  testing::TestThrowingCtor<MoveOptional>(MoveOptional(kUpdatedInteger));
+}
+
+TEST(OptionalExceptionSafety, Emplace) {
+  // Test the basic guarantee plus test the result of optional::has_value()
+  // is false in all cases
+  auto disengaged_test = MakeExceptionSafetyTester().WithInvariants(
+      CheckInvariants<Optional>, CheckDisengaged<Optional>);
+  auto disengaged_test_empty = disengaged_test.WithInitialValue(Optional());
+  auto disengaged_test_nonempty =
+      disengaged_test.WithInitialValue(Optional(kInitialInteger));
+
+  auto emplace_thrower_directly = [](Optional* optional_ptr) {
+    optional_ptr->emplace(kUpdatedInteger);
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_directly));
+  EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_directly));
+
+  auto emplace_thrower_copy = [](Optional* optional_ptr) {
+    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+    optional_ptr->emplace(thrower);
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_copy));
+  EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_copy));
+}
+
+TEST(OptionalExceptionSafety, EverythingThrowsSwap) {
+  // Test the basic guarantee plus test the result of optional::has_value()
+  // remains the same
+  auto test =
+      MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+  auto disengaged_test_empty = test.WithInitialValue(Optional())
+                                   .WithInvariants(CheckDisengaged<Optional>);
+  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+                                   .WithInvariants(CheckEngaged<Optional>);
+
+  auto swap_empty = [](Optional* optional_ptr) {
+    auto empty = Optional();
+    optional_ptr->swap(empty);
+  };
+  EXPECT_TRUE(engaged_test_nonempty.Test(swap_empty));
+
+  auto swap_nonempty = [](Optional* optional_ptr) {
+    auto nonempty =
+        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+    optional_ptr->swap(nonempty);
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(swap_nonempty));
+  EXPECT_TRUE(engaged_test_nonempty.Test(swap_nonempty));
+}
+
+TEST(OptionalExceptionSafety, NoThrowMoveSwap) {
+  // Tests the nothrow guarantee for optional of T with non-throwing move
+  auto nothrow_test =
+      MakeExceptionSafetyTester().WithInvariants(testing::nothrow_guarantee);
+  auto nothrow_test_empty = nothrow_test.WithInitialValue(MoveOptional());
+  auto nothrow_test_nonempty =
+      nothrow_test.WithInitialValue(MoveOptional(kInitialInteger));
+
+  auto swap_empty = [](MoveOptional* optional_ptr) {
+    auto empty = MoveOptional();
+    optional_ptr->swap(empty);
+  };
+  EXPECT_TRUE(nothrow_test_nonempty.Test(swap_empty));
+
+  auto swap_nonempty = [](MoveOptional* optional_ptr) {
+    auto nonempty =
+        MoveOptional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+    optional_ptr->swap(nonempty);
+  };
+  EXPECT_TRUE(nothrow_test_empty.Test(swap_nonempty));
+  EXPECT_TRUE(nothrow_test_nonempty.Test(swap_nonempty));
+}
+
+TEST(OptionalExceptionSafety, CopyAssign) {
+  // Test the basic guarantee plus test the result of optional::has_value()
+  // remains the same
+  auto test =
+      MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+  auto disengaged_test_empty = test.WithInitialValue(Optional())
+                                   .WithInvariants(CheckDisengaged<Optional>);
+  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+                                   .WithInvariants(CheckEngaged<Optional>);
+
+  auto copyassign_nonempty = [](Optional* optional_ptr) {
+    auto nonempty =
+        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = nonempty;
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(copyassign_nonempty));
+  EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_nonempty));
+
+  auto copyassign_thrower = [](Optional* optional_ptr) {
+    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = thrower;
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(copyassign_thrower));
+  EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_thrower));
+}
+
+TEST(OptionalExceptionSafety, MoveAssign) {
+  // Test the basic guarantee plus test the result of optional::has_value()
+  // remains the same
+  auto test =
+      MakeExceptionSafetyTester().WithInvariants(CheckInvariants<Optional>);
+  auto disengaged_test_empty = test.WithInitialValue(Optional())
+                                   .WithInvariants(CheckDisengaged<Optional>);
+  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
+                                   .WithInvariants(CheckEngaged<Optional>);
+
+  auto moveassign_empty = [](Optional* optional_ptr) {
+    auto empty = Optional();
+    *optional_ptr = std::move(empty);
+  };
+  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_empty));
+
+  auto moveassign_nonempty = [](Optional* optional_ptr) {
+    auto nonempty =
+        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = std::move(nonempty);
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(moveassign_nonempty));
+  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_nonempty));
+
+  auto moveassign_thrower = [](Optional* optional_ptr) {
+    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = std::move(thrower);
+  };
+  EXPECT_TRUE(disengaged_test_empty.Test(moveassign_thrower));
+  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_thrower));
+}
+
+TEST(OptionalExceptionSafety, NothrowMoveAssign) {
+  // Tests the nothrow guarantee for optional of T with non-throwing move
+  auto nothrow_test =
+      MakeExceptionSafetyTester().WithInvariants(testing::nothrow_guarantee);
+  auto nothrow_test_empty = nothrow_test.WithInitialValue(MoveOptional());
+  auto nothrow_test_nonempty =
+      nothrow_test.WithInitialValue(MoveOptional(kInitialInteger));
+
+  auto moveassign_empty = [](MoveOptional* optional_ptr) {
+    auto empty = MoveOptional();
+    *optional_ptr = std::move(empty);
+  };
+  EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_empty));
+
+  auto moveassign_nonempty = [](MoveOptional* optional_ptr) {
+    auto nonempty =
+        MoveOptional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = std::move(nonempty);
+  };
+  EXPECT_TRUE(nothrow_test_empty.Test(moveassign_nonempty));
+  EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_nonempty));
+
+  auto moveassign_thrower = [](MoveOptional* optional_ptr) {
+    auto thrower = MoveThrower(kUpdatedInteger, testing::nothrow_ctor);
+    *optional_ptr = std::move(thrower);
+  };
+  EXPECT_TRUE(nothrow_test_empty.Test(moveassign_thrower));
+  EXPECT_TRUE(nothrow_test_nonempty.Test(moveassign_thrower));
+}
+
+}  // namespace
+
+}  // namespace absl