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