// 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/internal/memutil.h" #include #include #include "benchmark/benchmark.h" #include "absl/strings/ascii.h" // We fill the haystack with aaaaaaaaaaaaaaaaaa...aaaab. // That gives us: // - an easy search: 'b' // - a medium search: 'ab'. That means every letter is a possible match. // - a pathological search: 'aaaaaa.......aaaaab' (half as many a's as haytack) namespace { constexpr int kHaystackSize = 10000; constexpr int64_t kHaystackSize64 = kHaystackSize; const char* MakeHaystack() { char* haystack = new char[kHaystackSize]; for (int i = 0; i < kHaystackSize - 1; ++i) haystack[i] = 'a'; haystack[kHaystackSize - 1] = 'b'; return haystack; } const char* const kHaystack = MakeHaystack(); bool case_eq(const char a, const char b) { return absl::ascii_tolower(a) == absl::ascii_tolower(b); } void BM_Searchcase(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, kHaystack + kHaystackSize - 1, kHaystack + kHaystackSize, case_eq)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_Searchcase); void BM_SearchcaseMedium(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, kHaystack + kHaystackSize - 2, kHaystack + kHaystackSize, case_eq)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_SearchcaseMedium); void BM_SearchcasePathological(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(std::search(kHaystack, kHaystack + kHaystackSize, kHaystack + kHaystackSize / 2, kHaystack + kHaystackSize, case_eq)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_SearchcasePathological); char* memcasechr(const char* s, int c, size_t slen) { c = absl::ascii_tolower(c); for (; slen; ++s, --slen) { if (absl::ascii_tolower(*s) == c) return const_cast(s); } return nullptr; } const char* memcasematch(const char* phaystack, size_t haylen, const char* pneedle, size_t neelen) { if (0 == neelen) { return phaystack; // even if haylen is 0 } if (haylen < neelen) return nullptr; const char* match; const char* hayend = phaystack + haylen - neelen + 1; while ((match = static_cast( memcasechr(phaystack, pneedle[0], hayend - phaystack)))) { if (absl::strings_internal::memcasecmp(match, pneedle, neelen) == 0) return match; else phaystack = match + 1; } return nullptr; } void BM_Memcasematch(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "b", 1)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_Memcasematch); void BM_MemcasematchMedium(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, "ab", 2)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_MemcasematchMedium); void BM_MemcasematchPathological(benchmark::State& state) { for (auto _ : state) { benchmark::DoNotOptimize(memcasematch(kHaystack, kHaystackSize, kHaystack + kHaystackSize / 2, kHaystackSize - kHaystackSize / 2)); } state.SetBytesProcessed(kHaystackSize64 * state.iterations()); } BENCHMARK(BM_MemcasematchPathological); } // namespace