1 /*
2 * Copyright (C) 2023 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 #include <benchmark/benchmark.h>
17
18 #include <cstdlib>
19 #include <ctime>
20 #include <map>
21 #include <unordered_map>
22 #include <vector>
23
24 #include "utils.h"
25
26 namespace android {
27 namespace os {
28 namespace statsd {
29
30 namespace {
31
32 template <typename ContainerType>
benchmarkFunctionForVector(std::vector<ContainerType> & vec,int capacity)33 void benchmarkFunctionForVector(std::vector<ContainerType>& vec, int capacity) {
34 ContainerType result = false;
35 for (int i = 0; i < capacity; i++) {
36 vec[i] = !result;
37 result = !result;
38 }
39
40 int resultInt = 0;
41 for (int i = 0; i < capacity; i++) {
42 resultInt += vec[i];
43 }
44
45 // Make sure the variable is not optimized away by compiler
46 benchmark::DoNotOptimize(vec);
47 benchmark::DoNotOptimize(resultInt);
48 }
49
50 template <typename ContainerType>
benchmarkStdFillForVector(std::vector<ContainerType> & vec,int capacity)51 void benchmarkStdFillForVector(std::vector<ContainerType>& vec, int capacity) {
52 std::fill(vec.begin(), vec.end(), true);
53 int resultInt = 0;
54 for (int i = 0; i < capacity; i++) {
55 resultInt += vec[i];
56 }
57
58 // Make sure the variable is not optimized away by compiler
59 benchmark::DoNotOptimize(vec);
60 benchmark::DoNotOptimize(resultInt);
61 }
62
63 template <typename ContainerType>
benchmarkUpdateKeyValueContainer(benchmark::State & state)64 void benchmarkUpdateKeyValueContainer(benchmark::State& state) {
65 const int kHashesCount = state.range(0);
66
67 ContainerType matcherStats;
68
69 auto hashIds = generateRandomHashIds(kHashesCount);
70 for (auto& v : hashIds) {
71 matcherStats[v] = 1;
72 }
73
74 int64_t result = 0;
75 while (state.KeepRunning()) {
76 for (auto& v : hashIds) {
77 matcherStats[v]++;
78 }
79 for (auto& v : hashIds) {
80 result += matcherStats[v];
81 }
82 benchmark::DoNotOptimize(result);
83 benchmark::ClobberMemory();
84 }
85 }
86
87 } // namespace
88
BM_BasicVectorBoolUsage(benchmark::State & state)89 static void BM_BasicVectorBoolUsage(benchmark::State& state) {
90 const int capacity = state.range(0);
91 std::vector<bool> vec(capacity);
92
93 while (state.KeepRunning()) {
94 benchmarkFunctionForVector<bool>(vec, capacity);
95 }
96 }
97 BENCHMARK(BM_BasicVectorBoolUsage)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100});
98
BM_VectorBoolStdFill(benchmark::State & state)99 static void BM_VectorBoolStdFill(benchmark::State& state) {
100 const int capacity = state.range(0);
101 std::vector<bool> vec(capacity);
102
103 while (state.KeepRunning()) {
104 benchmarkStdFillForVector<bool>(vec, capacity);
105 }
106 }
107 BENCHMARK(BM_VectorBoolStdFill)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100});
108
BM_BasicVectorInt8Usage(benchmark::State & state)109 static void BM_BasicVectorInt8Usage(benchmark::State& state) {
110 const int capacity = state.range(0);
111 std::vector<int8_t> vec(capacity);
112
113 while (state.KeepRunning()) {
114 benchmarkFunctionForVector<int8_t>(vec, capacity);
115 }
116 }
117 BENCHMARK(BM_BasicVectorInt8Usage)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100});
118
BM_VectorInt8StdFill(benchmark::State & state)119 static void BM_VectorInt8StdFill(benchmark::State& state) {
120 const int capacity = state.range(0);
121 std::vector<int8_t> vec(capacity);
122
123 while (state.KeepRunning()) {
124 benchmarkStdFillForVector<int8_t>(vec, capacity);
125 }
126 }
127 BENCHMARK(BM_VectorInt8StdFill)->Args({5})->Args({10})->Args({20})->Args({50})->Args({100});
128
BM_DictUpdateWithMap(benchmark::State & state)129 static void BM_DictUpdateWithMap(benchmark::State& state) {
130 benchmarkUpdateKeyValueContainer<std::map<int64_t, int>>(state);
131 }
132 BENCHMARK(BM_DictUpdateWithMap)->Args({500})->Args({1000})->Args({2000});
133
BM_DictUpdateWithUnorderedMap(benchmark::State & state)134 static void BM_DictUpdateWithUnorderedMap(benchmark::State& state) {
135 benchmarkUpdateKeyValueContainer<std::unordered_map<int64_t, int>>(state);
136 }
137 BENCHMARK(BM_DictUpdateWithUnorderedMap)->Args({500})->Args({1000})->Args({2000});
138
139 } // namespace statsd
140 } // namespace os
141 } // namespace android
142