1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <memory>
18 #include <regex>
19 #include <string>
20 
21 #include "benchmark/benchmark.h"
22 // #include "re2/re2.h"
23 #include "utils/Regex.h"
24 
25 using android::os::statsd::Regex;
26 using namespace std;
27 
removeTrailingCharacters(string & str,const string & characters)28 static void removeTrailingCharacters(string& str, const string& characters) {
29     str.erase(str.find_last_not_of(characters) + 1, string::npos);
30 }
31 
removeLeadingCharacters(string & str,const char charToRemove)32 static void removeLeadingCharacters(string& str, const char charToRemove) {
33     str.erase(0, min(str.find_first_not_of(charToRemove), str.size() - 1));
34 }
35 
removeTrailingNumbers(string & str)36 static void removeTrailingNumbers(string& str) {
37     int i = str.length() - 1;
38     while (i >= 0 && isdigit(str[i])) {
39         str.erase(i, 1);
40         i--;
41     }
42 }
43 
BM_RemoveTrailingCharacters(benchmark::State & state)44 static void BM_RemoveTrailingCharacters(benchmark::State& state) {
45     const string prefix(state.range(0), 'a' + rand() % 26);
46     const string suffix(state.range(1), '0' + rand() % 10);
47     const string input = prefix + suffix;
48     const string characters("0123456789");
49     for (auto _ : state) {
50         string str = input;
51         removeTrailingCharacters(str, characters);
52         benchmark::DoNotOptimize(str);
53     }
54 }
55 BENCHMARK(BM_RemoveTrailingCharacters)->RangeMultiplier(2)->RangePair(0, 20, 0, 20);
56 
BM_RemoveTrailingNumbers(benchmark::State & state)57 static void BM_RemoveTrailingNumbers(benchmark::State& state) {
58     const string prefix(state.range(0), 'a' + rand() % 26);
59     const string suffix(state.range(1), '0' + rand() % 10);
60     const string input = prefix + suffix;
61     for (auto _ : state) {
62         string str = input;
63         removeTrailingNumbers(str);
64         benchmark::DoNotOptimize(str);
65     }
66 }
67 BENCHMARK(BM_RemoveTrailingNumbers)->RangeMultiplier(2)->RangePair(0, 20, 0, 20);
68 
BM_RemoveTrailingNumbersCppRegex(benchmark::State & state)69 static void BM_RemoveTrailingNumbersCppRegex(benchmark::State& state) {
70     static const regex re(R"([\d]+$)");
71     const string prefix(state.range(0), 'a' + rand() % 26);
72     const string suffix(state.range(1), '0' + rand() % 10);
73     const string input = prefix + suffix;
74     for (auto _ : state) {
75         string str = input;
76         benchmark::DoNotOptimize(regex_replace(str, re, ""));
77     }
78 }
79 BENCHMARK(BM_RemoveTrailingNumbersCppRegex)->RangeMultiplier(2)->RangePair(0, 20, 0, 20);
80 
BM_RemoveTrailingNumbersCRegex(benchmark::State & state)81 static void BM_RemoveTrailingNumbersCRegex(benchmark::State& state) {
82     unique_ptr<Regex> re = Regex::create(R"([0-9]+$)");
83     const string prefix(state.range(0), 'a' + rand() % 26);
84     const string suffix(state.range(1), '0' + rand() % 10);
85     const string input = prefix + suffix;
86     for (auto _ : state) {
87         string str = input;
88         benchmark::DoNotOptimize(re->replace(str, ""));
89     }
90 }
91 BENCHMARK(BM_RemoveTrailingNumbersCRegex)->RangeMultiplier(2)->RangePair(0, 20, 0, 20);
92 
93 // To run RE2 benchmark locally, libregex_re2 under external/regex_re2 needs to be made visible to
94 // statsd_benchmark.
95 // static void BM_RemoveTrailingNumbersRe2(benchmark::State& state) {
96 //     using namespace re2;
97 //     static const RE2 re2{R"([\d]+$)"};
98 //     const string prefix(state.range(0), 'a' + rand() % 26);
99 //     const string suffix(state.range(1), '0' + rand() % 10);
100 //     const string input = prefix + suffix;
101 //     for (auto _ : state) {
102 //         string str = input;
103 //         RE2::Replace(&str, re2, "");
104 //         benchmark::DoNotOptimize(str);
105 //     }
106 // }
107 // BENCHMARK(BM_RemoveTrailingNumbersRe2)->RangeMultiplier(2)->RangePair(0, 20, 0, 20);
108