• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 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 <err.h>
18 #include <stdint.h>
19 #include <string.h>
20 
21 #include <benchmark/benchmark.h>
22 #include <util.h>
23 
BM_string_memcmp(benchmark::State & state)24 static void BM_string_memcmp(benchmark::State& state) {
25   const size_t nbytes = state.range(0);
26   const size_t src_alignment = state.range(1);
27   const size_t dst_alignment = state.range(2);
28 
29   std::vector<char> src;
30   std::vector<char> dst;
31   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
32   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'x');
33 
34   volatile int c __attribute__((unused)) = 0;
35   while (state.KeepRunning()) {
36     c += memcmp(dst_aligned, src_aligned, nbytes);
37   }
38 
39   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
40 }
41 BIONIC_BENCHMARK_WITH_ARG(BM_string_memcmp, "AT_ALIGNED_TWOBUF");
42 
BM_string_memcpy(benchmark::State & state)43 static void BM_string_memcpy(benchmark::State& state) {
44   const size_t nbytes = state.range(0);
45   const size_t src_alignment = state.range(1);
46   const size_t dst_alignment = state.range(2);
47 
48   std::vector<char> src;
49   std::vector<char> dst;
50   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
51   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
52 
53   while (state.KeepRunning()) {
54     memcpy(dst_aligned, src_aligned, nbytes);
55   }
56 
57   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
58 }
59 BIONIC_BENCHMARK_WITH_ARG(BM_string_memcpy, "AT_ALIGNED_TWOBUF");
60 
BM_string_memmove_non_overlapping(benchmark::State & state)61 static void BM_string_memmove_non_overlapping(benchmark::State& state) {
62   const size_t nbytes = state.range(0);
63   const size_t src_alignment = state.range(1);
64   const size_t dst_alignment = state.range(2);
65 
66   std::vector<char> src;
67   std::vector<char> dst;
68   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
69   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
70 
71   while (state.KeepRunning()) {
72     memmove(dst_aligned, src_aligned, nbytes);
73   }
74 
75   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
76 }
77 BIONIC_BENCHMARK_WITH_ARG(BM_string_memmove_non_overlapping, "AT_ALIGNED_TWOBUF");
78 
BM_string_memmove_overlap_dst_before_src(benchmark::State & state)79 static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
80   const size_t nbytes = state.range(0);
81   const size_t alignment = state.range(1);
82 
83   std::vector<char> buf(3 * alignment + nbytes + 1, 'x');
84   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
85 
86   while (state.KeepRunning()) {
87     memmove(buf_aligned, buf_aligned + 1, nbytes);  // Worst-case overlap.
88   }
89 
90   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
91 }
92 BIONIC_BENCHMARK_WITH_ARG(BM_string_memmove_overlap_dst_before_src, "AT_ALIGNED_ONEBUF");
93 
BM_string_memmove_overlap_src_before_dst(benchmark::State & state)94 static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
95   const size_t nbytes = state.range(0);
96   const size_t alignment = state.range(1);
97 
98   std::vector<char> buf;
99   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
100 
101   while (state.KeepRunning()) {
102     memmove(buf_aligned + 1, buf_aligned, nbytes);  // Worst-case overlap.
103   }
104 
105   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
106 }
107 BIONIC_BENCHMARK_WITH_ARG(BM_string_memmove_overlap_src_before_dst, "AT_ALIGNED_ONEBUF");
108 
BM_string_memset(benchmark::State & state)109 static void BM_string_memset(benchmark::State& state) {
110   const size_t nbytes = state.range(0);
111   const size_t alignment = state.range(1);
112 
113   std::vector<char> buf;
114   char* buf_aligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
115 
116   while (state.KeepRunning()) {
117     memset(buf_aligned, 0, nbytes);
118   }
119 
120   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
121 }
122 BIONIC_BENCHMARK_WITH_ARG(BM_string_memset, "AT_ALIGNED_ONEBUF");
123 
BM_string_strlen(benchmark::State & state)124 static void BM_string_strlen(benchmark::State& state) {
125   const size_t nbytes = state.range(0);
126   const size_t alignment = state.range(1);
127 
128   std::vector<char> buf;
129   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
130   buf_aligned[nbytes - 1] = '\0';
131 
132   volatile int c __attribute__((unused)) = 0;
133   while (state.KeepRunning()) {
134     c += strlen(buf_aligned);
135   }
136 
137   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
138 }
139 BIONIC_BENCHMARK_WITH_ARG(BM_string_strlen, "AT_ALIGNED_ONEBUF");
140 
BM_string_strcat_copy_only(benchmark::State & state)141 static void BM_string_strcat_copy_only(benchmark::State& state) {
142   const size_t nbytes = state.range(0);
143   const size_t src_alignment = state.range(1);
144   const size_t dst_alignment = state.range(2);
145 
146   std::vector<char> src;
147   std::vector<char> dst;
148   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
149   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes + 2);
150   src_aligned[nbytes - 1] = '\0';
151   dst_aligned[0] = 'y';
152   dst_aligned[1] = 'y';
153   dst_aligned[2] = '\0';
154 
155   while (state.KeepRunning()) {
156     strcat(dst_aligned, src_aligned);
157     dst_aligned[2] = '\0';
158   }
159 
160   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
161 }
162 BIONIC_BENCHMARK_WITH_ARG(BM_string_strcat_copy_only, "AT_ALIGNED_TWOBUF");
163 
BM_string_strcat_seek_only(benchmark::State & state)164 static void BM_string_strcat_seek_only(benchmark::State& state) {
165   const size_t nbytes = state.range(0);
166   const size_t src_alignment = state.range(1);
167   const size_t dst_alignment = state.range(2);
168 
169   std::vector<char> src;
170   std::vector<char> dst;
171   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, 3, 'x');
172   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes + 2, 'y');
173   src_aligned[2] = '\0';
174   dst_aligned[nbytes - 1] = '\0';
175 
176   while (state.KeepRunning()) {
177     strcat(dst_aligned, src_aligned);
178     dst_aligned[nbytes - 1] = '\0';
179   }
180 
181   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
182 }
183 BIONIC_BENCHMARK_WITH_ARG(BM_string_strcat_seek_only, "AT_ALIGNED_TWOBUF");
184 
BM_string_strcat_half_copy_half_seek(benchmark::State & state)185 static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
186   const size_t nbytes = state.range(0);
187   const size_t src_alignment = state.range(1);
188   const size_t dst_alignment = state.range(2);
189 
190   // Skip sizes that don't make sense.
191   if ((nbytes / 2) == 0) {
192     return;
193   }
194 
195   std::vector<char> src;
196   std::vector<char> dst;
197   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes / 2, 'x');
198   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
199   src_aligned[nbytes / 2 - 1] = '\0';
200   dst_aligned[nbytes / 2 - 1] = '\0';
201 
202   while (state.KeepRunning()) {
203     strcat(dst_aligned, src_aligned);
204     dst_aligned[nbytes / 2 - 1] = '\0';
205   }
206 
207   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
208 }
209 BIONIC_BENCHMARK_WITH_ARG(BM_string_strcat_half_copy_half_seek, "AT_ALIGNED_TWOBUF");
210 
BM_string_strcpy(benchmark::State & state)211 static void BM_string_strcpy(benchmark::State& state) {
212   const size_t nbytes = state.range(0);
213   const size_t src_alignment = state.range(1);
214   const size_t dst_alignment = state.range(2);
215 
216   std::vector<char> src;
217   std::vector<char> dst;
218   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
219   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
220   src_aligned[nbytes - 1] = '\0';
221 
222   while (state.KeepRunning()) {
223     strcpy(dst_aligned, src_aligned);
224   }
225 
226   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
227 }
228 BIONIC_BENCHMARK_WITH_ARG(BM_string_strcpy, "AT_ALIGNED_TWOBUF");
229 
BM_string_strcmp(benchmark::State & state)230 static void BM_string_strcmp(benchmark::State& state) {
231   const size_t nbytes = state.range(0);
232   const size_t s1_alignment = state.range(1);
233   const size_t s2_alignment = state.range(2);
234 
235   std::vector<char> s1;
236   std::vector<char> s2;
237   char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
238   char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
239   s1_aligned[nbytes - 1] = '\0';
240   s2_aligned[nbytes - 1] = '\0';
241 
242   volatile int c __attribute__((unused));
243   while (state.KeepRunning()) {
244     c = strcmp(s1_aligned, s2_aligned);
245   }
246 
247   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
248 }
249 BIONIC_BENCHMARK_WITH_ARG(BM_string_strcmp, "AT_ALIGNED_TWOBUF");
250 
BM_string_strncmp(benchmark::State & state)251 static void BM_string_strncmp(benchmark::State& state) {
252   const size_t nbytes = state.range(0);
253   const size_t s1_alignment = state.range(1);
254   const size_t s2_alignment = state.range(2);
255 
256   std::vector<char> s1;
257   std::vector<char> s2;
258   char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
259   char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
260 
261   volatile int c __attribute__((unused));
262   for (auto _ : state) {
263     c = strncmp(s1_aligned, s2_aligned, nbytes);
264   }
265 
266   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
267 }
268 BIONIC_BENCHMARK_WITH_ARG(BM_string_strncmp, "AT_ALIGNED_TWOBUF");
269 
BM_string_strstr(benchmark::State & state)270 static void BM_string_strstr(benchmark::State& state) {
271   const size_t nbytes = state.range(0);
272   const size_t haystack_alignment = state.range(1);
273   const size_t needle_alignment = state.range(2);
274 
275   std::vector<char> haystack;
276   std::vector<char> needle;
277   char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
278   char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
279                                              std::min(nbytes, static_cast<size_t>(5)), 'x');
280 
281   if (nbytes / 4 > 2) {
282     for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
283       haystack_aligned[4 * i + 3] = 'y';
284     }
285   }
286   haystack_aligned[nbytes - 1] = '\0';
287   needle_aligned[needle.size() - 1] = '\0';
288 
289   while (state.KeepRunning()) {
290     if (strstr(haystack_aligned, needle_aligned) == nullptr) {
291       errx(1, "ERROR: strstr failed to find valid substring.");
292     }
293   }
294 
295   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
296 }
297 BIONIC_BENCHMARK_WITH_ARG(BM_string_strstr, "AT_ALIGNED_TWOBUF");
298 
BM_string_strchr(benchmark::State & state)299 static void BM_string_strchr(benchmark::State& state) {
300   const size_t nbytes = state.range(0);
301   const size_t haystack_alignment = state.range(1);
302 
303   std::vector<char> haystack;
304   char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
305   haystack_aligned[nbytes-1] = '\0';
306 
307   while (state.KeepRunning()) {
308     if (strchr(haystack_aligned, 'y') != nullptr) {
309       errx(1, "ERROR: strchr found a chr where it should have failed.");
310     }
311   }
312 
313   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
314 }
315 BIONIC_BENCHMARK_WITH_ARG(BM_string_strchr, "AT_ALIGNED_ONEBUF");
316