Commit 32f414f4 by Andy Getzendanner Committed by Copybara-Service

Benchmark FNMatch, and use the greedy algorithm with better time and space…

Benchmark FNMatch, and use the greedy algorithm with better time and space complexity and no recursion (from 233 to 53.8 ns).

PiperOrigin-RevId: 557032497
Change-Id: I7a92feb3d79fa3dc1b7aa5b1097e53a9dae17c81
parent 71910654
...@@ -573,9 +573,9 @@ cc_test( ...@@ -573,9 +573,9 @@ cc_test(
], ],
) )
cc_binary( cc_test(
name = "log_benchmark", name = "log_benchmark",
testonly = 1, size = "small",
srcs = ["log_benchmark.cc"], srcs = ["log_benchmark.cc"],
copts = ABSL_TEST_COPTS, copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS, linkopts = ABSL_DEFAULT_LINKOPTS,
......
...@@ -404,3 +404,15 @@ cc_test( ...@@ -404,3 +404,15 @@ cc_test(
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
cc_test(
name = "fnmatch_benchmark",
srcs = ["fnmatch_benchmark.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":fnmatch",
"@com_github_google_benchmark//:benchmark_main",
],
)
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include "absl/log/internal/fnmatch.h" #include "absl/log/internal/fnmatch.h"
#include <cstddef>
#include "absl/base/config.h" #include "absl/base/config.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
...@@ -21,31 +23,49 @@ namespace absl { ...@@ -21,31 +23,49 @@ namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
namespace log_internal { namespace log_internal {
bool FNMatch(absl::string_view pattern, absl::string_view str) { bool FNMatch(absl::string_view pattern, absl::string_view str) {
bool in_wildcard_match = false;
while (true) { while (true) {
if (pattern.empty()) { if (pattern.empty()) {
// `pattern` is exhausted; succeed if all of `str` was consumed matching // `pattern` is exhausted; succeed if all of `str` was consumed matching
// it. // it.
return str.empty(); return in_wildcard_match || str.empty();
} }
if (str.empty()) { if (str.empty()) {
// `str` is exhausted; succeed if `pattern` is empty or all '*'s. // `str` is exhausted; succeed if `pattern` is empty or all '*'s.
return pattern.find_first_not_of('*') == pattern.npos; return pattern.find_first_not_of('*') == pattern.npos;
} }
if (pattern.front() == '*') { switch (pattern.front()) {
pattern.remove_prefix(1); case '*':
if (pattern.empty()) return true; pattern.remove_prefix(1);
do { in_wildcard_match = true;
if (FNMatch(pattern, str)) return true; break;
case '?':
pattern.remove_prefix(1);
str.remove_prefix(1); str.remove_prefix(1);
} while (!str.empty()); break;
return false; default:
} if (in_wildcard_match) {
if (pattern.front() == '?' || pattern.front() == str.front()) { absl::string_view fixed_portion = pattern;
pattern.remove_prefix(1); const size_t end = fixed_portion.find_first_of("*?");
str.remove_prefix(1); if (end != fixed_portion.npos) {
continue; fixed_portion = fixed_portion.substr(0, end);
}
const size_t match = str.find(fixed_portion);
if (match == str.npos) {
return false;
}
pattern.remove_prefix(fixed_portion.size());
str.remove_prefix(match + fixed_portion.size());
in_wildcard_match = false;
} else {
if (pattern.front() != str.front()) {
return false;
}
pattern.remove_prefix(1);
str.remove_prefix(1);
}
break;
} }
return false;
} }
} }
} // namespace log_internal } // namespace log_internal
......
// Copyright 2023 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/log/internal/fnmatch.h"
#include "benchmark/benchmark.h"
namespace {
void BM_FNMatch(benchmark::State& state) {
while (state.KeepRunning()) {
bool ret =
absl::log_internal::FNMatch("*?*asdf*?*we???asdf**asdf*we",
"QWERFASVWERASDFWEDFASDasdfQWERGFWASDERREWF"
"weHOOasdf@#$%TW#ZSERasdfQW#REGTZSERERwe");
benchmark::DoNotOptimize(ret);
}
}
BENCHMARK(BM_FNMatch);
} // namespace
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