You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
122 lines
4.4 KiB
122 lines
4.4 KiB
// 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 |
|
// |
|
// https://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 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 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 string that is a result of |
|
// replacing "the" with "box" in big_string. |
|
// |
|
// And then we create "after_replacing_many" to be a 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 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
|
|
|