blob: 7cd5ca0458e258e9bc9ae2fa099fc7bb9173c346 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* 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 "src/trace_processor/util/glob.h"
#include <benchmark/benchmark.h>
#include <sqlite3.h>
#include "perfetto/ext/base/scoped_file.h"
namespace {
using namespace perfetto;
using benchmark::Counter;
using perfetto::trace_processor::util::GlobMatcher;
static const char kAndroidGlob[] = "*android*";
static const char kLaunchingGlob[] = "launching: *";
static const char kChoreographerGlob[] = "Choreographer#doFrame*";
static const char kQuestionMarkGlob[] = "Choreo?rapher#doFrame*";
static const char kCharClassGlob[] = "Choreo[a-z]rapher#doFrame*";
std::vector<std::string> LoadTraceStrings(benchmark::State& state) {
std::vector<std::string> strs;
// This requires that the user has downloaded the file
// go/perfetto-benchmark-slice-strings into /tmp/trace_strings. The file is
// too big (220 MB after uncompression) and it's not worth adding it to the
// //test/data. Also it contains data from a team member's phone and cannot
// be public.
base::ScopedFstream f(fopen("/tmp/slice_strings", "re"));
if (!f) {
state.SkipWithError(
"Test strings missing. Googlers: download "
"go/perfetto-benchmark-slice-strings and save into /tmp/slice_strings");
return strs;
}
char line[4096];
while (fgets(line, sizeof(line), *f)) {
strs.emplace_back(base::StringView(line).ToStdString());
}
return strs;
}
template <class... Args>
static void BM_Glob(benchmark::State& state, Args&&... args) {
auto args_tuple = std::make_tuple(std::move(args)...);
std::vector<std::string> strs = LoadTraceStrings(state);
GlobMatcher glob = GlobMatcher::FromPattern(std::get<0>(args_tuple));
for (auto _ : state) {
for (const std::string& str : strs)
benchmark::DoNotOptimize(glob.Matches(base::StringView(str)));
benchmark::ClobberMemory();
}
state.counters["str/s"] = Counter(static_cast<double>(strs.size()),
Counter::kIsIterationInvariantRate);
state.counters["s/str"] =
Counter(static_cast<double>(strs.size()),
Counter::kIsIterationInvariantRate | Counter::kInvert);
}
BENCHMARK_CAPTURE(BM_Glob, android, kAndroidGlob);
BENCHMARK_CAPTURE(BM_Glob, launching, kLaunchingGlob);
BENCHMARK_CAPTURE(BM_Glob, choreographer, kChoreographerGlob);
BENCHMARK_CAPTURE(BM_Glob, question_mark, kQuestionMarkGlob);
BENCHMARK_CAPTURE(BM_Glob, char_class, kCharClassGlob);
template <class... Args>
static void BM_SqliteGlob(benchmark::State& state, Args&&... args) {
auto args_tuple = std::make_tuple(std::move(args)...);
const char* glob = std::get<0>(args_tuple);
std::vector<std::string> strs = LoadTraceStrings(state);
for (auto _ : state) {
for (const std::string& str : strs)
benchmark::DoNotOptimize(sqlite3_strglob(glob, str.c_str()));
benchmark::ClobberMemory();
}
state.counters["str/s"] = Counter(static_cast<double>(strs.size()),
Counter::kIsIterationInvariantRate);
state.counters["s/str"] =
Counter(static_cast<double>(strs.size()),
Counter::kIsIterationInvariantRate | Counter::kInvert);
}
BENCHMARK_CAPTURE(BM_SqliteGlob, android, kAndroidGlob);
BENCHMARK_CAPTURE(BM_SqliteGlob, launching, kLaunchingGlob);
BENCHMARK_CAPTURE(BM_SqliteGlob, slice, kChoreographerGlob);
BENCHMARK_CAPTURE(BM_SqliteGlob, question_mark, kQuestionMarkGlob);
BENCHMARK_CAPTURE(BM_SqliteGlob, char_class, kCharClassGlob);
} // namespace