Commit 59ae4d5a by Abseil Team Committed by jueminyang

- a4e14440b870dbf7b36975eaebf783a70a7fcee4 Release string_view…

  - a4e14440b870dbf7b36975eaebf783a70a7fcee4 Release string_view microbenchmarks. by Alex Strelnikov <strel@google.com>
  - 7cec68e37e16fb4e266368236ae1de6419f6946a Increase Abseil's minimum supported cmake version to 3.1.... by Jon Cohen <cohenjon@google.com>
  - b977456175c8db380676bd56c44b32efbfc6f606 Fix a typo in the mutex.h comments. by Abseil Team <absl-team@google.com>
  - 3d30cec131d08b066bc1cf877e4f661e8ee0584c Release StrSplit microbenchmarks. by Alex Strelnikov <strel@google.com>
  - dddece6031feac1cca4689e623462f895f28d019 Release StrReplace microbenchmarks. by Alex Strelnikov <strel@google.com>
  - ac3b40e1694f74bdcf31b8d1152481e92edfd441 Internal Change by Abseil Team <absl-team@google.com>
  - d0e69ad6ddf0e59596a02ccab0253967f2909cdb Release StrCat microbenchmarks. by Alex Strelnikov <strel@google.com>
  - db4d471030fa320d2b9d2ce241610333f0eb7a50 Release StrJoin microbenchmarks. by Alex Strelnikov <strel@google.com>

GitOrigin-RevId: a4e14440b870dbf7b36975eaebf783a70a7fcee4
Change-Id: I3f12700aafce677049f4d1a6e09ea821963a8c9e
parent 30de2048
...@@ -13,7 +13,10 @@ ...@@ -13,7 +13,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # 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) project(absl)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake) list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake)
......
...@@ -173,6 +173,20 @@ cc_test( ...@@ -173,6 +173,20 @@ cc_test(
) )
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", name = "string_view_test",
size = "small", size = "small",
srcs = ["string_view_test.cc"], srcs = ["string_view_test.cc"],
...@@ -201,6 +215,19 @@ cc_test( ...@@ -201,6 +215,19 @@ cc_test(
) )
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", name = "str_replace_test",
size = "small", size = "small",
srcs = ["str_replace_test.cc"], srcs = ["str_replace_test.cc"],
...@@ -226,6 +253,19 @@ cc_test( ...@@ -226,6 +253,19 @@ cc_test(
) )
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", name = "ostringstream_test",
size = "small", size = "small",
srcs = ["internal/ostringstream_test.cc"], srcs = ["internal/ostringstream_test.cc"],
...@@ -268,6 +308,19 @@ cc_test( ...@@ -268,6 +308,19 @@ cc_test(
) )
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", name = "str_cat_test",
size = "small", size = "small",
srcs = ["str_cat_test.cc"], srcs = ["str_cat_test.cc"],
...@@ -281,6 +334,18 @@ cc_test( ...@@ -281,6 +334,18 @@ cc_test(
) )
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", name = "numbers_test",
size = "small", size = "small",
srcs = [ srcs = [
......
// 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 <cstdint>
#include <string>
#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<void*>(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();
//
// 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 <string>
#include <vector>
#include <utility>
#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<std::string> 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<int> 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<std::pair<std::string, int>> 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<std::string> 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();
// 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 <cstring>
#include <string>
#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<size_t>(-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();
// 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 <iterator>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#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<absl::string_view> 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<absl::string_view> 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<std::string> 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<std::string> 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<std::string> 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<std::string, std::string> 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<std::string> 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 <typename DelimiterFactory>
void BM_SplitStringWithOneChar(benchmark::State& state) {
const auto delimiter = DelimiterFactory()();
std::vector<absl::string_view> 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 <typename DelimiterFactory>
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();
...@@ -854,7 +854,7 @@ class SCOPED_LOCKABLE MutexLockMaybe { ...@@ -854,7 +854,7 @@ class SCOPED_LOCKABLE MutexLockMaybe {
MutexLockMaybe& operator=(MutexLockMaybe&&) = delete; MutexLockMaybe& operator=(MutexLockMaybe&&) = delete;
}; };
// ReleaseableMutexLock // ReleasableMutexLock
// //
// ReleasableMutexLock is like MutexLock, but permits `Release()` of its // ReleasableMutexLock is like MutexLock, but permits `Release()` of its
// mutex before destruction. `Release()` may be called at most once. // mutex before destruction. `Release()` may be called at most once.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment