diff --git a/DEPS b/DEPS index 25a2a93e60..d8f7915f29 100644 --- a/DEPS +++ b/DEPS @@ -10,7 +10,7 @@ vars = { 'checkout_configuration': 'default', 'checkout_instrumented_libraries': 'checkout_linux and checkout_configuration == "default"', 'webrtc_git': 'https://webrtc.googlesource.com', - 'chromium_revision': '039110971be048779a21200d0e98d22da689278a', + 'chromium_revision': '52f78b1683a099f282aa06aea703d5e2c5ee59c0', 'boringssl_git': 'https://boringssl.googlesource.com', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client @@ -27,7 +27,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '7ca7a59f02029679bb68bcf5a79be7db1bbc3c3d', + 'catapult_revision': '1986f5a957da5e610ede36e73263e361b672e7a9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -43,15 +43,15 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Chromium third_party # and whatever else without interference from each other. - 'chromium_third_party_revision': 'cc1af829342dfa24713f9a914e5f0065e5bd02ec', + 'chromium_third_party_revision': '008fb7071ceda627d6917b925776a7a411b660ec', } deps = { # TODO(kjellander): Move this to be Android-only once the libevent dependency # in base/third_party/libevent is solved. 'src/base': - Var('chromium_git') + '/chromium/src/base' + '@' + '8e89780685c3230cd700003a0e0d5e45d08f1664', + Var('chromium_git') + '/chromium/src/base' + '@' + '40343e3fbc1e4835145f125adedcf15a2eb4542f', 'src/build': - Var('chromium_git') + '/chromium/src/build' + '@' + '66897e4d729dfaeeb84e058290ff0300ca813291', + Var('chromium_git') + '/chromium/src/build' + '@' + 'bd04ef72331a12d57056e95fd13d186739893d37', 'src/buildtools': Var('chromium_git') + '/chromium/buildtools.git' + '@' + '94288c26d2ffe3aec9848c147839afee597acefd', # Gradle 4.3-rc4. Used for testing Android Studio project generation for WebRTC. @@ -61,11 +61,11 @@ deps = { 'condition': 'checkout_android', }, 'src/ios': { - 'url': Var('chromium_git') + '/chromium/src/ios' + '@' + '02a22b39007fed435fa0b1582ad77bf6255a89e5', + 'url': Var('chromium_git') + '/chromium/src/ios' + '@' + 'de97874e2535ead371aa55350919daddd16ca1b2', 'condition': 'checkout_ios', }, 'src/testing': - Var('chromium_git') + '/chromium/src/testing' + '@' + '671c6a45223774a8131ea94e519163257e688018', + Var('chromium_git') + '/chromium/src/testing' + '@' + 'b4c21a01c2e3d2a21deb39a13b75927cc9cd52e3', # This entry is used for chromium third_party rolling into webrtc third_party only. 'src/third_party_chromium': { 'url': Var('chromium_git') + '/chromium/src/third_party' + '@' + Var('chromium_third_party_revision'), @@ -94,7 +94,7 @@ deps = { 'src/third_party/colorama/src': Var('chromium_git') + '/external/colorama.git' + '@' + '799604a1041e9b3bc5d2789ecbd7e8db2e18e6b8', 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '083eb25f9acbe034db94a1bd5c1659125b6ebf98', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4e9b50ab86b9b9f8ebf0b9ba6bd4954217ebeff9', 'src/third_party/errorprone/lib': { 'url': Var('chromium_git') + '/chromium/third_party/errorprone.git' + '@' + '980d49e839aa4984015efed34b0134d4b2c9b6d7', 'condition': 'checkout_android', @@ -113,7 +113,7 @@ deps = { 'src/third_party/gtest-parallel': Var('chromium_git') + '/external/github.com/google/gtest-parallel' + '@' + 'cb3514a0858be0f66281d892e2242d1073fd75fe', 'src/third_party/googletest/src': - Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + '08d5b1f33af8c18785fb8ca02792b5fac81e248f', + Var('chromium_git') + '/external/github.com/google/googletest.git' + '@' + '145d05750b15324899473340c8dd5af50d125d33', 'src/third_party/icu': { 'url': Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'f61e46dbee9d539a32551493e3bcc1dea92f83ec', }, @@ -135,7 +135,7 @@ deps = { 'src/third_party/libsrtp': Var('chromium_git') + '/chromium/deps/libsrtp.git' + '@' + 'fc2345089a6b3c5aca9ecd2e1941871a78a13e9c', 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'd99abe9a9ad78b765386d0ee62559de184ba581e', + Var('chromium_git') + '/webm/libvpx.git' + '@' + 'e27a331778c4c99ec37262ea786a3b4cc2a491ac', 'src/third_party/libyuv': Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'a9626b9daf62a9b260737e9c2de821ad087b19a1', 'src/third_party/lss': { @@ -175,7 +175,7 @@ deps = { 'src/third_party/yasm/source/patched-yasm': Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + 'b98114e18d8b9b84586b10d24353ab8616d4c5fc', 'src/tools': - Var('chromium_git') + '/chromium/src/tools' + '@' + 'ff5c71196bbccefb5eb237db626dc7d4f59b00ac', + Var('chromium_git') + '/chromium/src/tools' + '@' + 'c923d1173c6773018f6e68dfe64542e8c10780f2', 'src/tools/gyp': Var('chromium_git') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb', 'src/tools/swarming_client': diff --git a/third_party/PRESUBMIT.py b/third_party/PRESUBMIT.py index 29773fabc4..4dd12626b2 100644 --- a/third_party/PRESUBMIT.py +++ b/third_party/PRESUBMIT.py @@ -50,7 +50,13 @@ def _CheckThirdPartyReadmesUpdated(input_api, output_api): not local_path.startswith('third_party' + input_api.os_path.sep + 'mojo' + input_api.os_path.sep) and not local_path.startswith('third_party' + input_api.os_path.sep + - 'boringssl' + input_api.os_path.sep)): + 'boringssl' + input_api.os_path.sep) and + not local_path.startswith('third_party' + input_api.os_path.sep + + 'closure_compiler' + input_api.os_path.sep + + 'externs' + input_api.os_path.sep) and + not local_path.startswith('third_party' + input_api.os_path.sep + + 'closure_compiler' + input_api.os_path.sep + + 'interfaces' + input_api.os_path.sep)): files.append(f) if local_path.endswith("README.chromium"): readmes.append(f) diff --git a/third_party/abseil-cpp/CMakeLists.txt b/third_party/abseil-cpp/CMakeLists.txt index 744241efc1..89a3386f7e 100644 --- a/third_party/abseil-cpp/CMakeLists.txt +++ b/third_party/abseil-cpp/CMakeLists.txt @@ -13,7 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. # -cmake_minimum_required(VERSION 2.8.12) + +# We require 3.0 for modern, target-based CMake. We require 3.1 for the use of +# CXX_STANDARD in our targets. +cmake_minimum_required(VERSION 3.1) project(absl) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake) diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index 84f9b0b665..92298aca30 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium @@ -4,7 +4,7 @@ URL: https://github.com/abseil/abseil-cpp License: Apache 2.0 License File: LICENSE Version: 0 -Revision: 30de20488bb88dc22d23521c5c222ec6d924e289 +Revision: 014f02a3eca93ef88163c3b408c86998ecf6572c Security Critical: yes Description: diff --git a/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel index 5c05c67831..3d3c7aea57 100644 --- a/third_party/abseil-cpp/absl/base/BUILD.bazel +++ b/third_party/abseil-cpp/absl/base/BUILD.bazel @@ -102,6 +102,7 @@ cc_library( cc_library( name = "base_internal", hdrs = [ + "internal/hide_ptr.h", "internal/identity.h", "internal/inline_variable.h", "internal/invoke.h", diff --git a/third_party/abseil-cpp/absl/base/BUILD.gn b/third_party/abseil-cpp/absl/base/BUILD.gn index 657be869de..b4b12e01b9 100644 --- a/third_party/abseil-cpp/absl/base/BUILD.gn +++ b/third_party/abseil-cpp/absl/base/BUILD.gn @@ -131,6 +131,7 @@ source_set("base_internal") { ] public_configs = [ "//third_party/abseil-cpp:absl_include_config" ] public = [ + "internal/hide_ptr.h", "internal/identity.h", "internal/inline_variable.h", "internal/invoke.h", diff --git a/third_party/abseil-cpp/absl/base/CMakeLists.txt b/third_party/abseil-cpp/absl/base/CMakeLists.txt index 4564056278..303533e26d 100644 --- a/third_party/abseil-cpp/absl/base/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/base/CMakeLists.txt @@ -36,6 +36,7 @@ list(APPEND BASE_INTERNAL_HEADERS "internal/endian.h" "internal/exception_testing.h" "internal/exception_safety_testing.h" + "internal/hide_ptr.h" "internal/identity.h" "internal/invoke.h" "internal/inline_variable.h" diff --git a/third_party/abseil-cpp/absl/base/dynamic_annotations.cc b/third_party/abseil-cpp/absl/base/dynamic_annotations.cc index ae6ec0f775..b97fa3a8b4 100644 --- a/third_party/abseil-cpp/absl/base/dynamic_annotations.cc +++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.cc @@ -32,7 +32,7 @@ /* Each function is empty and called (via a macro) only in debug mode. The arguments are captured by dynamic tools at runtime. */ -#if ABSL_DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 +#if ABSL_DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__) #if __has_feature(memory_sanitizer) #include diff --git a/third_party/abseil-cpp/absl/base/internal/hide_ptr.h b/third_party/abseil-cpp/absl/base/internal/hide_ptr.h new file mode 100644 index 0000000000..2c2e11f679 --- /dev/null +++ b/third_party/abseil-cpp/absl/base/internal/hide_ptr.h @@ -0,0 +1,49 @@ +// 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. + +#ifndef ABSL_BASE_INTERNAL_HIDE_PTR_H_ +#define ABSL_BASE_INTERNAL_HIDE_PTR_H_ + +#include + +namespace absl { +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; +} + +// Hide a pointer from the leak checker. For internal use only. +// Differs from absl::IgnoreLeak(ptr) in that absl::IgnoreLeak(ptr) causes ptr +// and all objects reachable from ptr to be ignored by the leak checker. +template +inline uintptr_t HidePtr(T* ptr) { + return reinterpret_cast(ptr) ^ HideMask(); +} + +// Return a pointer that has been hidden from the leak checker. +// For internal use only. +template +inline T* UnhidePtr(uintptr_t hidden) { + return reinterpret_cast(hidden ^ HideMask()); +} + +} // namespace base_internal +} // namespace absl + +#endif // ABSL_BASE_INTERNAL_HIDE_PTR_H_ diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc index 46ef7b8f5a..4c131fe07e 100644 --- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc +++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc @@ -158,6 +158,8 @@ static bool SetupAlternateStackOnce() { #endif +#ifdef ABSL_HAVE_SIGACTION + // Sets up an alternate stack for signal handlers once. // Returns the appropriate flag for sig_action.sa_flags // if the system supports using an alternate stack. @@ -170,8 +172,6 @@ static int MaybeSetupAlternateStack() { #endif } -#ifdef ABSL_HAVE_SIGACTION - static void InstallOneFailureHandler(FailureSignalData* data, void (*handler)(int, siginfo_t*, void*)) { struct sigaction act; diff --git a/third_party/abseil-cpp/absl/memory/memory.h b/third_party/abseil-cpp/absl/memory/memory.h index 2220ee4e41..055d88e001 100644 --- a/third_party/abseil-cpp/absl/memory/memory.h +++ b/third_party/abseil-cpp/absl/memory/memory.h @@ -40,7 +40,8 @@ namespace absl { // ----------------------------------------------------------------------------- // // Adopts ownership from a raw pointer and transfers it to the returned -// `std::unique_ptr`, whose type is deduced. +// `std::unique_ptr`, whose type is deduced. DO NOT specify the template type T +// when calling WrapUnique. // // Example: // X* NewX(int, int); diff --git a/third_party/abseil-cpp/absl/numeric/BUILD.bazel b/third_party/abseil-cpp/absl/numeric/BUILD.bazel index 4a24a879c0..0791145d0f 100644 --- a/third_party/abseil-cpp/absl/numeric/BUILD.bazel +++ b/third_party/abseil-cpp/absl/numeric/BUILD.bazel @@ -1,3 +1,17 @@ +# 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. + load( "//absl:copts.bzl", "ABSL_DEFAULT_COPTS", diff --git a/third_party/abseil-cpp/absl/strings/BUILD.bazel b/third_party/abseil-cpp/absl/strings/BUILD.bazel index 1e52312b47..28cf2d2eba 100644 --- a/third_party/abseil-cpp/absl/strings/BUILD.bazel +++ b/third_party/abseil-cpp/absl/strings/BUILD.bazel @@ -13,10 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# -*- mode: python; -*- -# Libraries in this low-level package may not depend on libraries in packages -# that are not low level. For more information, including how to submit -# changes to this file, see http://www/eng/howto/build-monitors.html load( "//absl:copts.bzl", @@ -172,6 +168,20 @@ cc_test( ], ) +cc_test( + name = "string_view_benchmark", + srcs = ["string_view_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "//absl/base", + "//absl/base:core_headers", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "string_view_test", size = "small", @@ -200,6 +210,19 @@ cc_test( ], ) +cc_test( + name = "str_replace_benchmark", + srcs = ["str_replace_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "//absl/base", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "str_replace_test", size = "small", @@ -225,6 +248,19 @@ cc_test( ], ) +cc_test( + name = "str_split_benchmark", + srcs = ["str_split_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "//absl/base", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "ostringstream_test", size = "small", @@ -267,6 +303,19 @@ cc_test( ], ) +cc_test( + name = "str_join_benchmark", + srcs = ["str_join_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "//absl/memory", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "str_cat_test", size = "small", @@ -280,6 +329,18 @@ cc_test( ], ) +cc_test( + name = "str_cat_benchmark", + srcs = ["str_cat_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strings", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "numbers_test", size = "small", diff --git a/third_party/abseil-cpp/absl/strings/numbers.h b/third_party/abseil-cpp/absl/strings/numbers.h index adf706a4e2..75925e61f2 100644 --- a/third_party/abseil-cpp/absl/strings/numbers.h +++ b/third_party/abseil-cpp/absl/strings/numbers.h @@ -124,17 +124,11 @@ char* FastIntToBuffer(int_type i, char* buffer) { } } -} // namespace numbers_internal - -// SimpleAtoi() -// -// Converts a std::string to an integer, using `safe_strto?()` functions for actual -// parsing, returning `true` if successful. The `safe_strto?()` functions apply -// strict checking; the std::string must be a base-10 integer, optionally followed or -// preceded by ASCII whitespace, with a value in the range of the corresponding -// integer type. +// Implementation of SimpleAtoi, generalized to support arbitrary base (used +// with base different from 10 elsewhere in Abseil implementation). template -ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out) { +ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out, + int base) { static_assert(sizeof(*out) == 4 || sizeof(*out) == 8, "SimpleAtoi works only with 32-bit or 64-bit integers."); static_assert(!std::is_floating_point::value, @@ -146,27 +140,41 @@ ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out) { if (static_cast(1) - 2 < 0) { // Signed if (sizeof(*out) == 64 / 8) { // 64-bit int64_t val; - parsed = numbers_internal::safe_strto64_base(s, &val, 10); + parsed = numbers_internal::safe_strto64_base(s, &val, base); *out = static_cast(val); } else { // 32-bit int32_t val; - parsed = numbers_internal::safe_strto32_base(s, &val, 10); + parsed = numbers_internal::safe_strto32_base(s, &val, base); *out = static_cast(val); } } else { // Unsigned if (sizeof(*out) == 64 / 8) { // 64-bit uint64_t val; - parsed = numbers_internal::safe_strtou64_base(s, &val, 10); + parsed = numbers_internal::safe_strtou64_base(s, &val, base); *out = static_cast(val); } else { // 32-bit uint32_t val; - parsed = numbers_internal::safe_strtou32_base(s, &val, 10); + parsed = numbers_internal::safe_strtou32_base(s, &val, base); *out = static_cast(val); } } return parsed; } +} // namespace numbers_internal + +// SimpleAtoi() +// +// Converts a std::string to an integer, using `safe_strto?()` functions for actual +// parsing, returning `true` if successful. The `safe_strto?()` functions apply +// strict checking; the std::string must be a base-10 integer, optionally followed or +// preceded by ASCII whitespace, with a value in the range of the corresponding +// integer type. +template +ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out) { + return numbers_internal::safe_strtoi_base(s, out, 10); +} + } // namespace absl #endif // ABSL_STRINGS_NUMBERS_H_ diff --git a/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc new file mode 100644 index 0000000000..1791410c6e --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc @@ -0,0 +1,142 @@ +// 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/str_cat.h" + +#include +#include + +#include "benchmark/benchmark.h" +#include "absl/strings/substitute.h" + +namespace { + +const char kStringOne[] = "Once Upon A Time, "; +const char kStringTwo[] = "There was a std::string benchmark"; + +// We want to include negative numbers in the benchmark, so this function +// is used to count 0, 1, -1, 2, -2, 3, -3, ... +inline int IncrementAlternatingSign(int i) { + return i > 0 ? -i : 1 - i; +} + +void BM_Sum_By_StrCat(benchmark::State& state) { + int i = 0; + char foo[100]; + for (auto _ : state) { + // NOLINTNEXTLINE(runtime/printf) + strcpy(foo, absl::StrCat(kStringOne, i, kStringTwo, i * 65536ULL).c_str()); + int sum = 0; + for (char* f = &foo[0]; *f != 0; ++f) { + sum += *f; + } + benchmark::DoNotOptimize(sum); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_Sum_By_StrCat); + +void BM_StrCat_By_snprintf(benchmark::State& state) { + int i = 0; + char on_stack[1000]; + for (auto _ : state) { + snprintf(on_stack, sizeof(on_stack), "%s %s:%d", kStringOne, kStringTwo, i); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_StrCat_By_snprintf); + +void BM_StrCat_By_Strings(benchmark::State& state) { + int i = 0; + for (auto _ : state) { + std::string result = + std::string(kStringOne) + " " + kStringTwo + ":" + absl::StrCat(i); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_StrCat_By_Strings); + +void BM_StrCat_By_StringOpPlus(benchmark::State& state) { + int i = 0; + for (auto _ : state) { + std::string result = kStringOne; + result += " "; + result += kStringTwo; + result += ":"; + result += absl::StrCat(i); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_StrCat_By_StringOpPlus); + +void BM_StrCat_By_StrCat(benchmark::State& state) { + int i = 0; + for (auto _ : state) { + std::string result = absl::StrCat(kStringOne, " ", kStringTwo, ":", i); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_StrCat_By_StrCat); + +void BM_HexCat_By_StrCat(benchmark::State& state) { + int i = 0; + for (auto _ : state) { + std::string result = + absl::StrCat(kStringOne, " ", absl::Hex(int64_t{i} + 0x10000000)); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_HexCat_By_StrCat); + +void BM_HexCat_By_Substitute(benchmark::State& state) { + int i = 0; + for (auto _ : state) { + std::string result = absl::Substitute( + "$0 $1", kStringOne, reinterpret_cast(int64_t{i} + 0x10000000)); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_HexCat_By_Substitute); + +void BM_FloatToString_By_StrCat(benchmark::State& state) { + int i = 0; + float foo = 0.0f; + for (auto _ : state) { + std::string result = absl::StrCat(foo += 1.001f, " != ", int64_t{i}); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_FloatToString_By_StrCat); + +void BM_DoubleToString_By_SixDigits(benchmark::State& state) { + int i = 0; + double foo = 0.0; + for (auto _ : state) { + std::string result = + absl::StrCat(absl::SixDigits(foo += 1.001), " != ", int64_t{i}); + benchmark::DoNotOptimize(result); + i = IncrementAlternatingSign(i); + } +} +BENCHMARK(BM_DoubleToString_By_SixDigits); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/strings/str_join_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_join_benchmark.cc new file mode 100644 index 0000000000..79cad5e393 --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/str_join_benchmark.cc @@ -0,0 +1,98 @@ +// +// 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/str_join.h" + +#include +#include +#include + +#include "benchmark/benchmark.h" + +namespace { + +void BM_Join2_Strings(benchmark::State& state) { + const int string_len = state.range(0); + const int num_strings = state.range(1); + const std::string s(string_len, 'x'); + const std::vector v(num_strings, s); + for (auto _ : state) { + std::string s = absl::StrJoin(v, "-"); + benchmark::DoNotOptimize(s); + } +} +BENCHMARK(BM_Join2_Strings) + ->ArgPair(1 << 0, 1 << 3) + ->ArgPair(1 << 10, 1 << 3) + ->ArgPair(1 << 13, 1 << 3) + ->ArgPair(1 << 0, 1 << 10) + ->ArgPair(1 << 10, 1 << 10) + ->ArgPair(1 << 13, 1 << 10) + ->ArgPair(1 << 0, 1 << 13) + ->ArgPair(1 << 10, 1 << 13) + ->ArgPair(1 << 13, 1 << 13); + +void BM_Join2_Ints(benchmark::State& state) { + const int num_ints = state.range(0); + const std::vector v(num_ints, 42); + for (auto _ : state) { + std::string s = absl::StrJoin(v, "-"); + benchmark::DoNotOptimize(s); + } +} +BENCHMARK(BM_Join2_Ints)->Range(0, 1 << 13); + +void BM_Join2_KeysAndValues(benchmark::State& state) { + const int string_len = state.range(0); + const int num_pairs = state.range(1); + const std::string s(string_len, 'x'); + const std::vector> v(num_pairs, std::make_pair(s, 42)); + for (auto _ : state) { + std::string s = absl::StrJoin(v, ",", absl::PairFormatter("=")); + benchmark::DoNotOptimize(s); + } +} +BENCHMARK(BM_Join2_KeysAndValues) + ->ArgPair(1 << 0, 1 << 3) + ->ArgPair(1 << 10, 1 << 3) + ->ArgPair(1 << 13, 1 << 3) + ->ArgPair(1 << 0, 1 << 10) + ->ArgPair(1 << 10, 1 << 10) + ->ArgPair(1 << 13, 1 << 10) + ->ArgPair(1 << 0, 1 << 13) + ->ArgPair(1 << 10, 1 << 13) + ->ArgPair(1 << 13, 1 << 13); + +void BM_JoinStreamable(benchmark::State& state) { + const int string_len = state.range(0); + const int num_strings = state.range(1); + const std::vector v(num_strings, std::string(string_len, 'x')); + for (auto _ : state) { + std::string s = absl::StrJoin(v, "", absl::StreamFormatter()); + benchmark::DoNotOptimize(s); + } +} +BENCHMARK(BM_JoinStreamable) + ->ArgPair(0, 0) + ->ArgPair(16, 1) + ->ArgPair(256, 1) + ->ArgPair(16, 16) + ->ArgPair(256, 16) + ->ArgPair(16, 256) + ->ArgPair(256, 256); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc new file mode 100644 index 0000000000..9dd72eb6e7 --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc @@ -0,0 +1,124 @@ +// 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/str_replace.h" + +#include +#include + +#include "benchmark/benchmark.h" +#include "absl/base/internal/raw_logging.h" + +namespace { + +std::string* big_string; +std::string* after_replacing_the; +std::string* after_replacing_many; + +struct Replacement { + const char* needle; + const char* replacement; +} replacements[] = { + {"the", "box"}, // + {"brown", "quick"}, // + {"jumped", "liquored"}, // + {"dozen", "brown"}, // + {"lazy", "pack"}, // + {"liquor", "shakes"}, // +}; + +// Here, we set up a std::string for use in global-replace benchmarks. +// We started with a million blanks, and then deterministically insert +// 10,000 copies each of two pangrams. The result is a std::string that is +// 40% blank space and 60% these words. 'the' occurs 18,247 times and +// all the substitutions together occur 49,004 times. +// +// We then create "after_replacing_the" to be a std::string that is a result of +// replacing "the" with "box" in big_string. +// +// And then we create "after_replacing_many" to be a std::string that is result +// of preferring several substitutions. +void SetUpStrings() { + if (big_string == nullptr) { + size_t r = 0; + big_string = new std::string(1000 * 1000, ' '); + for (std::string phrase : {"the quick brown fox jumped over the lazy dogs", + "pack my box with the five dozen liquor jugs"}) { + for (int i = 0; i < 10 * 1000; ++i) { + r = r * 237 + 41; // not very random. + memcpy(&(*big_string)[r % (big_string->size() - phrase.size())], + phrase.data(), phrase.size()); + } + } + // big_string->resize(50); + // OK, we've set up the std::string, now let's set up expectations - first by + // just replacing "the" with "box" + after_replacing_the = new std::string(*big_string); + for (size_t pos = 0; + (pos = after_replacing_the->find("the", pos)) != std::string::npos;) { + memcpy(&(*after_replacing_the)[pos], "box", 3); + } + // And then with all the replacements. + after_replacing_many = new std::string(*big_string); + for (size_t pos = 0;;) { + size_t next_pos = static_cast(-1); + const char* needle_string = nullptr; + const char* replacement_string = nullptr; + for (const auto& r : replacements) { + auto needlepos = after_replacing_many->find(r.needle, pos); + if (needlepos != std::string::npos && needlepos < next_pos) { + next_pos = needlepos; + needle_string = r.needle; + replacement_string = r.replacement; + } + } + if (next_pos > after_replacing_many->size()) break; + after_replacing_many->replace(next_pos, strlen(needle_string), + replacement_string); + next_pos += strlen(replacement_string); + pos = next_pos; + } + } +} + +void BM_StrReplaceAllOneReplacement(benchmark::State& state) { + SetUpStrings(); + std::string src = *big_string; + for (auto _ : state) { + std::string dest = absl::StrReplaceAll(src, {{"the", "box"}}); + ABSL_RAW_CHECK(dest == *after_replacing_the, + "not benchmarking intended behavior"); + } +} +BENCHMARK(BM_StrReplaceAllOneReplacement); + +void BM_StrReplaceAll(benchmark::State& state) { + SetUpStrings(); + std::string src = *big_string; + for (auto _ : state) { + std::string dest = absl::StrReplaceAll(src, {{"the", "box"}, + {"brown", "quick"}, + {"jumped", "liquored"}, + {"dozen", "brown"}, + {"lazy", "pack"}, + {"liquor", "shakes"}}); + ABSL_RAW_CHECK(dest == *after_replacing_many, + "not benchmarking intended behavior"); + } +} +BENCHMARK(BM_StrReplaceAll); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/strings/str_split_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_split_benchmark.cc new file mode 100644 index 0000000000..c35787b7ef --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/str_split_benchmark.cc @@ -0,0 +1,158 @@ +// 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/str_split.h" + +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "absl/base/internal/raw_logging.h" +#include "absl/strings/string_view.h" + +namespace { + +std::string MakeTestString(int desired_length) { + static const int kAverageValueLen = 25; + std::string test(desired_length * kAverageValueLen, 'x'); + for (int i = 1; i < test.size(); i += kAverageValueLen) { + test[i] = ';'; + } + return test; +} + +void BM_Split2StringPiece(benchmark::State& state) { + std::string test = MakeTestString(state.range(0)); + for (auto _ : state) { + std::vector result = absl::StrSplit(test, ';'); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_Split2StringPiece, 0, 1 << 20); + +void BM_Split2StringPieceLifted(benchmark::State& state) { + std::string test = MakeTestString(state.range(0)); + std::vector result; + for (auto _ : state) { + result = absl::StrSplit(test, ';'); + } + benchmark::DoNotOptimize(result); +} +BENCHMARK_RANGE(BM_Split2StringPieceLifted, 0, 1 << 20); + +void BM_Split2String(benchmark::State& state) { + std::string test = MakeTestString(state.range(0)); + for (auto _ : state) { + std::vector result = absl::StrSplit(test, ';'); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20); + +// This benchmark is for comparing Split2 to Split1 (SplitStringUsing). In +// particular, this benchmark uses SkipEmpty() to match SplitStringUsing's +// behavior. +void BM_Split2SplitStringUsing(benchmark::State& state) { + std::string test = MakeTestString(state.range(0)); + for (auto _ : state) { + std::vector result = absl::StrSplit(test, ';', absl::SkipEmpty()); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_Split2SplitStringUsing, 0, 1 << 20); + +void BM_SplitStringToUnorderedSet(benchmark::State& state) { + const int len = state.range(0); + std::string test(len, 'x'); + for (int i = 1; i < len; i += 2) { + test[i] = ';'; + } + for (auto _ : state) { + std::unordered_set result = + absl::StrSplit(test, ':', absl::SkipEmpty()); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_SplitStringToUnorderedSet, 0, 1 << 20); + +void BM_SplitStringToUnorderedMap(benchmark::State& state) { + const int len = state.range(0); + std::string test(len, 'x'); + for (int i = 1; i < len; i += 2) { + test[i] = ';'; + } + for (auto _ : state) { + std::unordered_map result = + absl::StrSplit(test, ':', absl::SkipEmpty()); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_SplitStringToUnorderedMap, 0, 1 << 20); + +void BM_SplitStringAllowEmpty(benchmark::State& state) { + const int len = state.range(0); + std::string test(len, 'x'); + for (int i = 1; i < len; i += 2) { + test[i] = ';'; + } + for (auto _ : state) { + std::vector result = absl::StrSplit(test, ';'); + benchmark::DoNotOptimize(result); + } +} +BENCHMARK_RANGE(BM_SplitStringAllowEmpty, 0, 1 << 20); + +struct OneCharLiteral { + char operator()() const { return 'X'; } +}; + +struct OneCharStringLiteral { + const char* operator()() const { return "X"; } +}; + +template +void BM_SplitStringWithOneChar(benchmark::State& state) { + const auto delimiter = DelimiterFactory()(); + std::vector pieces; + size_t v = 0; + for (auto _ : state) { + pieces = absl::StrSplit("The quick brown fox jumps over the lazy dog", + delimiter); + v += pieces.size(); + } + ABSL_RAW_CHECK(v == state.iterations(), ""); +} +BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharLiteral); +BENCHMARK_TEMPLATE(BM_SplitStringWithOneChar, OneCharStringLiteral); + +template +void BM_SplitStringWithOneCharNoVector(benchmark::State& state) { + const auto delimiter = DelimiterFactory()(); + size_t v = 0; + for (auto _ : state) { + auto splitter = absl::StrSplit( + "The quick brown fox jumps over the lazy dog", delimiter); + v += std::distance(splitter.begin(), splitter.end()); + } + ABSL_RAW_CHECK(v == state.iterations(), ""); +} +BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharLiteral); +BENCHMARK_TEMPLATE(BM_SplitStringWithOneCharNoVector, OneCharStringLiteral); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/strings/string_view_benchmark.cc b/third_party/abseil-cpp/absl/strings/string_view_benchmark.cc new file mode 100644 index 0000000000..c66f0fbd54 --- /dev/null +++ b/third_party/abseil-cpp/absl/strings/string_view_benchmark.cc @@ -0,0 +1,331 @@ +// 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/string_view.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "absl/base/attributes.h" +#include "absl/base/internal/raw_logging.h" +#include "absl/base/macros.h" +#include "absl/strings/str_cat.h" + +namespace { + +// Provide a forcibly out-of-line wrapper for operator== that can be used in +// benchmarks to measure the impact of inlining. +ABSL_ATTRIBUTE_NOINLINE +bool NonInlinedEq(absl::string_view a, absl::string_view b) { return a == b; } + +// We use functions that cannot be inlined to perform the comparison loops so +// that inlining of the operator== can't optimize away *everything*. +ABSL_ATTRIBUTE_NOINLINE +void DoEqualityComparisons(benchmark::State& state, absl::string_view a, + absl::string_view b) { + for (auto _ : state) { + benchmark::DoNotOptimize(a == b); + } +} + +void BM_EqualIdentical(benchmark::State& state) { + std::string x(state.range(0), 'a'); + DoEqualityComparisons(state, x, x); +} +BENCHMARK(BM_EqualIdentical)->DenseRange(0, 3)->Range(4, 1 << 10); + +void BM_EqualSame(benchmark::State& state) { + std::string x(state.range(0), 'a'); + std::string y = x; + DoEqualityComparisons(state, x, y); +} +BENCHMARK(BM_EqualSame) + ->DenseRange(0, 10) + ->Arg(20) + ->Arg(40) + ->Arg(70) + ->Arg(110) + ->Range(160, 4096); + +void BM_EqualDifferent(benchmark::State& state) { + const int len = state.range(0); + std::string x(len, 'a'); + std::string y = x; + if (len > 0) { + y[len - 1] = 'b'; + } + DoEqualityComparisons(state, x, y); +} +BENCHMARK(BM_EqualDifferent)->DenseRange(0, 3)->Range(4, 1 << 10); + +// This benchmark is intended to check that important simplifications can be +// made with absl::string_view comparisons against constant strings. The idea is +// that if constant strings cause redundant components of the comparison, the +// compiler should detect and eliminate them. Here we use 8 different strings, +// each with the same size. Provided our comparison makes the implementation +// inline-able by the compiler, it should fold all of these away into a single +// size check once per loop iteration. +ABSL_ATTRIBUTE_NOINLINE +void DoConstantSizeInlinedEqualityComparisons(benchmark::State& state, + absl::string_view a) { + for (auto _ : state) { + benchmark::DoNotOptimize(a == "aaa"); + benchmark::DoNotOptimize(a == "bbb"); + benchmark::DoNotOptimize(a == "ccc"); + benchmark::DoNotOptimize(a == "ddd"); + benchmark::DoNotOptimize(a == "eee"); + benchmark::DoNotOptimize(a == "fff"); + benchmark::DoNotOptimize(a == "ggg"); + benchmark::DoNotOptimize(a == "hhh"); + } +} +void BM_EqualConstantSizeInlined(benchmark::State& state) { + std::string x(state.range(0), 'a'); + DoConstantSizeInlinedEqualityComparisons(state, x); +} +// We only need to check for size of 3, and <> 3 as this benchmark only has to +// do with size differences. +BENCHMARK(BM_EqualConstantSizeInlined)->DenseRange(2, 4); + +// This benchmark exists purely to give context to the above timings: this is +// what they would look like if the compiler is completely unable to simplify +// between two comparisons when they are comparing against constant strings. +ABSL_ATTRIBUTE_NOINLINE +void DoConstantSizeNonInlinedEqualityComparisons(benchmark::State& state, + absl::string_view a) { + for (auto _ : state) { + // Force these out-of-line to compare with the above function. + benchmark::DoNotOptimize(NonInlinedEq(a, "aaa")); + benchmark::DoNotOptimize(NonInlinedEq(a, "bbb")); + benchmark::DoNotOptimize(NonInlinedEq(a, "ccc")); + benchmark::DoNotOptimize(NonInlinedEq(a, "ddd")); + benchmark::DoNotOptimize(NonInlinedEq(a, "eee")); + benchmark::DoNotOptimize(NonInlinedEq(a, "fff")); + benchmark::DoNotOptimize(NonInlinedEq(a, "ggg")); + benchmark::DoNotOptimize(NonInlinedEq(a, "hhh")); + } +} + +void BM_EqualConstantSizeNonInlined(benchmark::State& state) { + std::string x(state.range(0), 'a'); + DoConstantSizeNonInlinedEqualityComparisons(state, x); +} +// We only need to check for size of 3, and <> 3 as this benchmark only has to +// do with size differences. +BENCHMARK(BM_EqualConstantSizeNonInlined)->DenseRange(2, 4); + +void BM_CompareSame(benchmark::State& state) { + const int len = state.range(0); + std::string x; + for (int i = 0; i < len; i++) { + x += 'a'; + } + std::string y = x; + absl::string_view a = x; + absl::string_view b = y; + + for (auto _ : state) { + benchmark::DoNotOptimize(a.compare(b)); + } +} +BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10); + +void BM_find_string_view_len_one(benchmark::State& state) { + std::string haystack(state.range(0), '0'); + absl::string_view s(haystack); + for (auto _ : state) { + s.find("x"); // not present; length 1 + } +} +BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20); + +void BM_find_string_view_len_two(benchmark::State& state) { + std::string haystack(state.range(0), '0'); + absl::string_view s(haystack); + for (auto _ : state) { + s.find("xx"); // not present; length 2 + } +} +BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20); + +void BM_find_one_char(benchmark::State& state) { + std::string haystack(state.range(0), '0'); + absl::string_view s(haystack); + for (auto _ : state) { + s.find('x'); // not present + } +} +BENCHMARK(BM_find_one_char)->Range(1, 1 << 20); + +void BM_rfind_one_char(benchmark::State& state) { + std::string haystack(state.range(0), '0'); + absl::string_view s(haystack); + for (auto _ : state) { + s.rfind('x'); // not present + } +} +BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20); + +void BM_worst_case_find_first_of(benchmark::State& state, int haystack_len) { + const int needle_len = state.range(0); + std::string needle; + for (int i = 0; i < needle_len; ++i) { + needle += 'a' + i; + } + std::string haystack(haystack_len, '0'); // 1000 zeros. + + absl::string_view s(haystack); + for (auto _ : state) { + s.find_first_of(needle); + } +} + +void BM_find_first_of_short(benchmark::State& state) { + BM_worst_case_find_first_of(state, 10); +} + +void BM_find_first_of_medium(benchmark::State& state) { + BM_worst_case_find_first_of(state, 100); +} + +void BM_find_first_of_long(benchmark::State& state) { + BM_worst_case_find_first_of(state, 1000); +} + +BENCHMARK(BM_find_first_of_short)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); +BENCHMARK(BM_find_first_of_medium)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); +BENCHMARK(BM_find_first_of_long)->DenseRange(0, 4)->Arg(8)->Arg(16)->Arg(32); + +struct EasyMap : public std::map { + explicit EasyMap(size_t) {} +}; + +// This templated benchmark helper function is intended to stress operator== or +// operator< in a realistic test. It surely isn't entirely realistic, but it's +// a start. The test creates a map of type Map, a template arg, and populates +// it with table_size key/value pairs. Each key has WordsPerKey words. After +// creating the map, a number of lookups are done in random order. Some keys +// are used much more frequently than others in this phase of the test. +template +void StringViewMapBenchmark(benchmark::State& state) { + const int table_size = state.range(0); + const double kFractionOfKeysThatAreHot = 0.2; + const int kNumLookupsOfHotKeys = 20; + const int kNumLookupsOfColdKeys = 1; + const char* words[] = {"the", "quick", "brown", "fox", "jumped", + "over", "the", "lazy", "dog", "and", + "found", "a", "large", "mushroom", "and", + "a", "couple", "crickets", "eating", "pie"}; + // Create some keys that consist of words in random order. + std::random_device r; + std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); + std::mt19937 rng(seed); + std::vector keys(table_size); + std::vector all_indices; + const int kBlockSize = 1 << 12; + std::unordered_set t(kBlockSize); + std::uniform_int_distribution uniform(0, ABSL_ARRAYSIZE(words) - 1); + for (int i = 0; i < table_size; i++) { + all_indices.push_back(i); + do { + keys[i].clear(); + for (int j = 0; j < WordsPerKey; j++) { + absl::StrAppend(&keys[i], j > 0 ? " " : "", words[uniform(rng)]); + } + } while (!t.insert(keys[i]).second); + } + + // Create a list of strings to lookup: a permutation of the array of + // keys we just created, with repeats. "Hot" keys get repeated more. + std::shuffle(all_indices.begin(), all_indices.end(), rng); + const int num_hot = table_size * kFractionOfKeysThatAreHot; + const int num_cold = table_size - num_hot; + std::vector hot_indices(all_indices.begin(), + all_indices.begin() + num_hot); + std::vector indices; + for (int i = 0; i < kNumLookupsOfColdKeys; i++) { + indices.insert(indices.end(), all_indices.begin(), all_indices.end()); + } + for (int i = 0; i < kNumLookupsOfHotKeys - kNumLookupsOfColdKeys; i++) { + indices.insert(indices.end(), hot_indices.begin(), hot_indices.end()); + } + std::shuffle(indices.begin(), indices.end(), rng); + ABSL_RAW_CHECK( + num_cold * kNumLookupsOfColdKeys + num_hot * kNumLookupsOfHotKeys == + indices.size(), + ""); + // After constructing the array we probe it with absl::string_views built from + // test_strings. This means operator== won't see equal pointers, so + // it'll have to check for equal lengths and equal characters. + std::vector test_strings(indices.size()); + for (int i = 0; i < indices.size(); i++) { + test_strings[i] = keys[indices[i]]; + } + + // Run the benchmark. It includes map construction but is mostly + // map lookups. + for (auto _ : state) { + Map h(table_size); + for (int i = 0; i < table_size; i++) { + h[keys[i]] = i * 2; + } + ABSL_RAW_CHECK(h.size() == table_size, ""); + uint64_t sum = 0; + for (int i = 0; i < indices.size(); i++) { + sum += h[test_strings[i]]; + } + benchmark::DoNotOptimize(sum); + } +} + +void BM_StdMap_4(benchmark::State& state) { + StringViewMapBenchmark(state); +} +BENCHMARK(BM_StdMap_4)->Range(1 << 10, 1 << 16); + +void BM_StdMap_8(benchmark::State& state) { + StringViewMapBenchmark(state); +} +BENCHMARK(BM_StdMap_8)->Range(1 << 10, 1 << 16); + +void BM_CopyToStringNative(benchmark::State& state) { + std::string src(state.range(0), 'x'); + absl::string_view sv(src); + std::string dst; + for (auto _ : state) { + dst.assign(sv.begin(), sv.end()); + } +} +BENCHMARK(BM_CopyToStringNative)->Range(1 << 3, 1 << 12); + +void BM_AppendToStringNative(benchmark::State& state) { + std::string src(state.range(0), 'x'); + absl::string_view sv(src); + std::string dst; + for (auto _ : state) { + dst.clear(); + dst.insert(dst.end(), sv.begin(), sv.end()); + } +} +BENCHMARK(BM_AppendToStringNative)->Range(1 << 3, 1 << 12); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel index 05376903fe..67ce7ff9bb 100644 --- a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel +++ b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel @@ -39,6 +39,7 @@ cc_library( ], deps = [ "//absl/base", + "//absl/base:base_internal", "//absl/base:core_headers", "//absl/base:malloc_internal", ], @@ -119,6 +120,20 @@ cc_test( ], ) +cc_test( + name = "graphcycles_benchmark", + srcs = ["internal/graphcycles_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = [ + "benchmark", + ], + deps = [ + ":graphcycles_internal", + "//absl/base", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_library( name = "thread_pool", testonly = 1, @@ -148,6 +163,20 @@ cc_test( ], ) +cc_test( + name = "mutex_benchmark", + srcs = ["mutex_benchmark.cc"], + copts = ABSL_TEST_COPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":synchronization", + ":thread_pool", + "//absl/base", + "@com_github_google_benchmark//:benchmark", + ], +) + cc_test( name = "notification_test", size = "small", diff --git a/third_party/abseil-cpp/absl/synchronization/BUILD.gn b/third_party/abseil-cpp/absl/synchronization/BUILD.gn index dfca941366..eb19f0948c 100644 --- a/third_party/abseil-cpp/absl/synchronization/BUILD.gn +++ b/third_party/abseil-cpp/absl/synchronization/BUILD.gn @@ -30,6 +30,7 @@ source_set("graphcycles_internal") { ] deps = [ "../base", + "../base:base_internal", "../base:core_headers", "../base:malloc_internal", ] diff --git a/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc index 28ad172c01..ab1f3f84e7 100644 --- a/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc +++ b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc @@ -37,6 +37,7 @@ #include #include +#include "absl/base/internal/hide_ptr.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" @@ -276,18 +277,6 @@ inline uint32_t NodeVersion(GraphId id) { return static_cast(id.handle >> 32); } -// We need to hide Mutexes (or other deadlock detection's pointers) -// from the leak detector. Xor with an arbitrary number with high bits set. -static const uintptr_t kHideMask = static_cast(0xF03A5F7BF03A5F7Bll); - -static inline uintptr_t MaskPtr(void *ptr) { - return reinterpret_cast(ptr) ^ kHideMask; -} - -static inline void* UnmaskPtr(uintptr_t word) { - return reinterpret_cast(word ^ kHideMask); -} - struct Node { int32_t rank; // rank number assigned by Pearce-Kelly algorithm uint32_t version; // Current version number @@ -309,7 +298,7 @@ class PointerMap { } int32_t Find(void* ptr) { - auto masked = MaskPtr(ptr); + auto masked = base_internal::HidePtr(ptr); for (int32_t i = table_[Hash(ptr)]; i != -1;) { Node* n = (*nodes_)[i]; if (n->masked_ptr == masked) return i; @@ -327,7 +316,7 @@ class PointerMap { int32_t Remove(void* ptr) { // Advance through linked list while keeping track of the // predecessor slot that points to the current entry. - auto masked = MaskPtr(ptr); + auto masked = base_internal::HidePtr(ptr); for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1; ) { int32_t index = *slot; Node* n = (*nodes_)[index]; @@ -395,7 +384,7 @@ bool GraphCycles::CheckInvariants() const { NodeSet ranks; // Set of ranks seen so far. for (uint32_t x = 0; x < r->nodes_.size(); x++) { Node* nx = r->nodes_[x]; - void* ptr = UnmaskPtr(nx->masked_ptr); + void* ptr = base_internal::UnhidePtr(nx->masked_ptr); if (ptr != nullptr && static_cast(r->ptrmap_.Find(ptr)) != x) { ABSL_RAW_LOG(FATAL, "Did not find live node in hash table %u %p", x, ptr); } @@ -427,7 +416,7 @@ GraphId GraphCycles::GetId(void* ptr) { n->version = 1; // Avoid 0 since it is used by InvalidGraphId() n->visited = false; n->rank = rep_->nodes_.size(); - n->masked_ptr = MaskPtr(ptr); + n->masked_ptr = base_internal::HidePtr(ptr); n->nstack = 0; n->priority = 0; rep_->nodes_.push_back(n); @@ -439,7 +428,7 @@ GraphId GraphCycles::GetId(void* ptr) { int32_t r = rep_->free_nodes_.back(); rep_->free_nodes_.pop_back(); Node* n = rep_->nodes_[r]; - n->masked_ptr = MaskPtr(ptr); + n->masked_ptr = base_internal::HidePtr(ptr); n->nstack = 0; n->priority = 0; rep_->ptrmap_.Add(ptr, r); @@ -461,7 +450,7 @@ void GraphCycles::RemoveNode(void* ptr) { } x->in.clear(); x->out.clear(); - x->masked_ptr = MaskPtr(nullptr); + x->masked_ptr = base_internal::HidePtr(nullptr); if (x->version == std::numeric_limits::max()) { // Cannot use x any more } else { @@ -472,7 +461,8 @@ void GraphCycles::RemoveNode(void* ptr) { void* GraphCycles::Ptr(GraphId id) { Node* n = FindNode(rep_, id); - return n == nullptr ? nullptr : UnmaskPtr(n->masked_ptr); + return n == nullptr ? nullptr + : base_internal::UnhidePtr(n->masked_ptr); } bool GraphCycles::HasNode(GraphId node) { diff --git a/third_party/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc new file mode 100644 index 0000000000..b4a1debe75 --- /dev/null +++ b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc @@ -0,0 +1,46 @@ +// 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/synchronization/internal/graphcycles.h" + +#include +#include +#include + +#include "benchmark/benchmark.h" +#include "absl/base/internal/raw_logging.h" + +namespace { + +void BM_StressTest(benchmark::State& state) { + const int num_nodes = state.range(0); + while (state.KeepRunningBatch(num_nodes)) { + absl::synchronization_internal::GraphCycles g; + std::vector nodes(num_nodes); + for (int i = 0; i < num_nodes; i++) { + nodes[i] = g.GetId(reinterpret_cast(static_cast(i))); + } + for (int i = 0; i < num_nodes; i++) { + int end = std::min(num_nodes, i + 5); + for (int j = i + 1; j < end; j++) { + ABSL_RAW_CHECK(g.InsertEdge(nodes[i], nodes[j]), ""); + } + } + } +} +BENCHMARK(BM_StressTest)->Range(2048, 1048576); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.cc b/third_party/abseil-cpp/absl/synchronization/mutex.cc index a207b71fcd..80f34f035f 100644 --- a/third_party/abseil-cpp/absl/synchronization/mutex.cc +++ b/third_party/abseil-cpp/absl/synchronization/mutex.cc @@ -43,6 +43,7 @@ #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/atomic_hook.h" #include "absl/base/internal/cycleclock.h" +#include "absl/base/internal/hide_ptr.h" #include "absl/base/internal/low_level_alloc.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" @@ -272,13 +273,6 @@ static absl::base_internal::SpinLock synch_event_mu( // Can't be too small, as it's used for deadlock detection information. static const uint32_t kNSynchEvent = 1031; -// We need to hide Mutexes (or other deadlock detection's pointers) -// from the leak detector. -static const uintptr_t kHideMask = static_cast(0xF03A5F7BF03A5F7BLL); -static uintptr_t MaskMu(const void *mu) { - return reinterpret_cast(mu) ^ kHideMask; -} - static struct SynchEvent { // this is a trivial hash table for the events // struct is freed when refcount reaches 0 int refcount GUARDED_BY(synch_event_mu); @@ -314,7 +308,8 @@ static SynchEvent *EnsureSynchEvent(std::atomic *addr, SynchEvent *e; // first look for existing SynchEvent struct.. synch_event_mu.Lock(); - for (e = synch_event[h]; e != nullptr && e->masked_addr != MaskMu(addr); + for (e = synch_event[h]; + e != nullptr && e->masked_addr != base_internal::HidePtr(addr); e = e->next) { } if (e == nullptr) { // no SynchEvent struct found; make one. @@ -325,7 +320,7 @@ static SynchEvent *EnsureSynchEvent(std::atomic *addr, e = reinterpret_cast( base_internal::LowLevelAlloc::Alloc(sizeof(*e) + l)); e->refcount = 2; // one for return value, one for linked list - e->masked_addr = MaskMu(addr); + e->masked_addr = base_internal::HidePtr(addr); e->invariant = nullptr; e->arg = nullptr; e->log = false; @@ -367,7 +362,8 @@ static void ForgetSynchEvent(std::atomic *addr, intptr_t bits, SynchEvent *e; synch_event_mu.Lock(); for (pe = &synch_event[h]; - (e = *pe) != nullptr && e->masked_addr != MaskMu(addr); pe = &e->next) { + (e = *pe) != nullptr && e->masked_addr != base_internal::HidePtr(addr); + pe = &e->next) { } bool del = false; if (e != nullptr) { @@ -388,7 +384,8 @@ static SynchEvent *GetSynchEvent(const void *addr) { uint32_t h = reinterpret_cast(addr) % kNSynchEvent; SynchEvent *e; synch_event_mu.Lock(); - for (e = synch_event[h]; e != nullptr && e->masked_addr != MaskMu(addr); + for (e = synch_event[h]; + e != nullptr && e->masked_addr != base_internal::HidePtr(addr); e = e->next) { } if (e != nullptr) { diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.h b/third_party/abseil-cpp/absl/synchronization/mutex.h index 368684bf2e..840b9d6b0e 100644 --- a/third_party/abseil-cpp/absl/synchronization/mutex.h +++ b/third_party/abseil-cpp/absl/synchronization/mutex.h @@ -854,7 +854,7 @@ class SCOPED_LOCKABLE MutexLockMaybe { MutexLockMaybe& operator=(MutexLockMaybe&&) = delete; }; -// ReleaseableMutexLock +// ReleasableMutexLock // // ReleasableMutexLock is like MutexLock, but permits `Release()` of its // mutex before destruction. `Release()` may be called at most once. diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc new file mode 100644 index 0000000000..d91071b71b --- /dev/null +++ b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc @@ -0,0 +1,96 @@ +// 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 + +#include "benchmark/benchmark.h" +#include "absl/base/internal/sysinfo.h" +#include "absl/synchronization/blocking_counter.h" +#include "absl/synchronization/internal/thread_pool.h" +#include "absl/synchronization/mutex.h" + +namespace { + +// Measure the overhead of conditions on mutex release (when they must be +// evaluated). Mutex has (some) support for equivalence classes allowing +// Conditions with the same function/argument to potentially not be multiply +// evaluated. +// +// num_classes==0 is used for the special case of every waiter being distinct. +void BM_ConditionWaiters(benchmark::State& state) { + int num_classes = state.range(0); + int num_waiters = state.range(1); + + struct Helper { + static void Waiter(absl::BlockingCounter* init, absl::Mutex* m, int* p) { + init->DecrementCount(); + m->LockWhen(absl::Condition( + static_cast([](int* v) { return *v == 0; }), p)); + m->Unlock(); + } + }; + + if (num_classes == 0) { + // No equivalence classes. + num_classes = num_waiters; + } + + absl::BlockingCounter init(num_waiters); + absl::Mutex mu; + std::vector equivalence_classes(num_classes, 1); + + // Must be declared last to be destroyed first. + absl::synchronization_internal::ThreadPool pool(num_waiters); + + for (int i = 0; i < num_waiters; i++) { + // Mutex considers Conditions with the same function and argument + // to be equivalent. + pool.Schedule([&, i] { + Helper::Waiter(&init, &mu, &equivalence_classes[i % num_classes]); + }); + } + init.Wait(); + + for (auto _ : state) { + mu.Lock(); + mu.Unlock(); // Each unlock requires Condition evaluation for our waiters. + } + + mu.Lock(); + for (int i = 0; i < num_classes; i++) { + equivalence_classes[i] = 0; + } + mu.Unlock(); +} + +#ifdef THREAD_SANITIZER +// ThreadSanitizer can't handle 8192 threads. +constexpr int kMaxConditionWaiters = 2048; +#else +constexpr int kMaxConditionWaiters = 8192; +#endif +BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters); + +void BM_ContendedMutex(benchmark::State& state) { + static absl::Mutex* mu = new absl::Mutex; + for (auto _ : state) { + absl::MutexLock lock(mu); + } +} +BENCHMARK(BM_ContendedMutex)->Threads(1); +BENCHMARK(BM_ContendedMutex)->ThreadPerCpu(); + +} // namespace + +BENCHMARK_MAIN(); diff --git a/third_party/closure_compiler/externs/OWNERS b/third_party/closure_compiler/externs/OWNERS index 8d19f08198..6d0defff5f 100644 --- a/third_party/closure_compiler/externs/OWNERS +++ b/third_party/closure_compiler/externs/OWNERS @@ -4,3 +4,4 @@ stevenjb@chromium.org per-file accessibility_private.js=file://ui/accessibility/OWNERS per-file automation.js=file://ui/accessibility/OWNERS +per-file file_manager_private.js=file://ui/file_manager/OWNERS diff --git a/third_party/closure_compiler/externs/developer_private.js b/third_party/closure_compiler/externs/developer_private.js index 3de78042ec..5b11c63181 100644 --- a/third_party/closure_compiler/externs/developer_private.js +++ b/third_party/closure_compiler/externs/developer_private.js @@ -803,6 +803,26 @@ chrome.developerPrivate.setShortcutHandlingSuspended = function(isSuspended, cal */ chrome.developerPrivate.updateExtensionCommand = function(update, callback) {}; +/** + * Adds a new host permission to the extension. The extension will only have + * access to the host if it is within the requested permissions. + * @param {string} extensionId The id of the extension to modify. + * @param {string} host The host to add. + * @param {function():void=} callback + * @see https://developer.chrome.com/extensions/developerPrivate#method-addHostPermission + */ +chrome.developerPrivate.addHostPermission = function(extensionId, host, callback) {}; + +/** + * Removes a host permission from the extension. This should only be called with + * a host that the extension has access to. + * @param {string} extensionId The id of the extension to modify. + * @param {string} host The host to remove. + * @param {function():void=} callback + * @see https://developer.chrome.com/extensions/developerPrivate#method-removeHostPermission + */ +chrome.developerPrivate.removeHostPermission = function(extensionId, host, callback) {}; + /** * @param {string} id * @param {boolean} enabled diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js index ea7ef4df7a..abe57e041c 100644 --- a/third_party/closure_compiler/externs/file_manager_private.js +++ b/third_party/closure_compiler/externs/file_manager_private.js @@ -31,6 +31,7 @@ var IconSet; * croppedThumbnailUrl: (string|undefined), * externalFileUrl: (string|undefined), * alternateUrl: (string|undefined), + * shareUrl: (string|undefined), * imageWidth: (number|undefined), * imageHeight: (number|undefined), * imageRotation: (number|undefined), diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 507ca26d78..3fb61e4b51 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium @@ -5,9 +5,9 @@ License: BSD License File: source/libvpx/LICENSE Security Critical: yes -Date: Tuesday May 15 2018 +Date: Monday May 21 2018 Branch: master -Commit: d99abe9a9ad78b765386d0ee62559de184ba581e +Commit: e27a331778c4c99ec37262ea786a3b4cc2a491ac Description: Contains the sources used to compile libvpx binaries used by Google Chrome and diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index 49c8845560..d208d662f3 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h @@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 7 #define VERSION_PATCH 0 -#define VERSION_EXTRA "377-gd99abe9a9" +#define VERSION_EXTRA "387-ge27a33177" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.7.0-377-gd99abe9a9" -#define VERSION_STRING " v1.7.0-377-gd99abe9a9" +#define VERSION_STRING_NOSP "v1.7.0-387-ge27a33177" +#define VERSION_STRING " v1.7.0-387-ge27a33177"