blob: eb04c9396a263d1c1b57be1303d9cf8cb9bfb69c [file] [log] [blame]
Elliott Hughes7be369d2012-11-08 15:37:43 -08001/*
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
Anders Lewisa98a5fb2017-08-09 16:52:19 -070017#include <err.h>
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080018#include <stdint.h>
Elliott Hughes7be369d2012-11-08 15:37:43 -080019#include <string.h>
20
Elliott Hughes281e06b2016-02-17 10:23:52 -080021#include <benchmark/benchmark.h>
Anders Lewisa7b0f882017-07-24 20:01:13 -070022#include <util.h>
Elliott Hughes7be369d2012-11-08 15:37:43 -080023
Elliott Hughes281e06b2016-02-17 10:23:52 -080024static void BM_string_memcmp(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010025 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070026 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');
Elliott Hughes7be369d2012-11-08 15:37:43 -080033
34 volatile int c __attribute__((unused)) = 0;
Elliott Hughes281e06b2016-02-17 10:23:52 -080035 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070036 c += memcmp(dst_aligned, src_aligned, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -080037 }
38
Elliott Hughes281e06b2016-02-17 10:23:52 -080039 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -080040}
Anders Lewisa7b0f882017-07-24 20:01:13 -070041BIONIC_BENCHMARK(BM_string_memcmp);
Elliott Hughes7be369d2012-11-08 15:37:43 -080042
Elliott Hughes281e06b2016-02-17 10:23:52 -080043static void BM_string_memcpy(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010044 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070045 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);
Elliott Hughes7be369d2012-11-08 15:37:43 -080052
Elliott Hughes281e06b2016-02-17 10:23:52 -080053 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070054 memcpy(dst_aligned, src_aligned, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -080055 }
56
Elliott Hughes281e06b2016-02-17 10:23:52 -080057 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -080058}
Anders Lewisa7b0f882017-07-24 20:01:13 -070059BIONIC_BENCHMARK(BM_string_memcpy);
Elliott Hughes7be369d2012-11-08 15:37:43 -080060
Anders Lewis271be9b2017-06-07 13:00:38 -070061static void BM_string_memmove_non_overlapping(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010062 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070063 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');
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080070
Elliott Hughes281e06b2016-02-17 10:23:52 -080071 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070072 memmove(dst_aligned, src_aligned, nbytes);
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080073 }
74
Elliott Hughes281e06b2016-02-17 10:23:52 -080075 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080076}
Anders Lewisa7b0f882017-07-24 20:01:13 -070077BIONIC_BENCHMARK(BM_string_memmove_non_overlapping);
Anders Lewis271be9b2017-06-07 13:00:38 -070078
79static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
80 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070081 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');
Anders Lewis271be9b2017-06-07 13:00:38 -070085
86 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070087 memmove(buf_aligned, buf_aligned + 1, nbytes); // Worst-case overlap.
Anders Lewis271be9b2017-06-07 13:00:38 -070088 }
89
90 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
91}
Anders Lewisa7b0f882017-07-24 20:01:13 -070092BIONIC_BENCHMARK(BM_string_memmove_overlap_dst_before_src);
Anders Lewis271be9b2017-06-07 13:00:38 -070093
94static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
95 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070096 const size_t alignment = state.range(1);
97
98 std::vector<char> buf;
99 char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
Anders Lewis271be9b2017-06-07 13:00:38 -0700100
101 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700102 memmove(buf_aligned + 1, buf_aligned, nbytes); // Worst-case overlap.
Anders Lewis271be9b2017-06-07 13:00:38 -0700103 }
104
105 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
106}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700107BIONIC_BENCHMARK(BM_string_memmove_overlap_src_before_dst);
Elliott Hughesfbe44ec2012-11-09 14:59:21 -0800108
Elliott Hughes281e06b2016-02-17 10:23:52 -0800109static void BM_string_memset(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +0100110 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700111 const size_t alignment = state.range(1);
112
113 std::vector<char> buf;
114 char* buf_aligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800115
Elliott Hughes281e06b2016-02-17 10:23:52 -0800116 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700117 memset(buf_aligned, 0, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800118 }
119
Elliott Hughes281e06b2016-02-17 10:23:52 -0800120 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -0800121}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700122BIONIC_BENCHMARK(BM_string_memset);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800123
Elliott Hughes281e06b2016-02-17 10:23:52 -0800124static void BM_string_strlen(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +0100125 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700126 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';
Elliott Hughes7be369d2012-11-08 15:37:43 -0800131
132 volatile int c __attribute__((unused)) = 0;
Elliott Hughes281e06b2016-02-17 10:23:52 -0800133 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700134 c += strlen(buf_aligned);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800135 }
136
Elliott Hughes281e06b2016-02-17 10:23:52 -0800137 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -0800138}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700139BIONIC_BENCHMARK(BM_string_strlen);
Anders Lewisa99d0522017-06-12 11:24:01 -0700140
141static void BM_string_strcat_copy_only(benchmark::State& state) {
142 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700143 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';
Anders Lewisa99d0522017-06-12 11:24:01 -0700154
155 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700156 strcat(dst_aligned, src_aligned);
157 dst_aligned[2] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700158 }
159
160 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
161}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700162BIONIC_BENCHMARK(BM_string_strcat_copy_only);
Anders Lewisa99d0522017-06-12 11:24:01 -0700163
164static void BM_string_strcat_seek_only(benchmark::State& state) {
165 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700166 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';
Anders Lewisa99d0522017-06-12 11:24:01 -0700175
176 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700177 strcat(dst_aligned, src_aligned);
178 dst_aligned[nbytes - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700179 }
180
181 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
182}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700183BIONIC_BENCHMARK(BM_string_strcat_seek_only);
Anders Lewisa99d0522017-06-12 11:24:01 -0700184
185static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
186 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700187 const size_t src_alignment = state.range(1);
188 const size_t dst_alignment = state.range(2);
189
190 std::vector<char> src;
191 std::vector<char> dst;
192 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes / 2, 'x');
193 char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
194 src_aligned[nbytes / 2 - 1] = '\0';
195 dst_aligned[nbytes / 2 - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700196
197 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700198 strcat(dst_aligned, src_aligned);
199 dst_aligned[nbytes / 2 - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700200 }
201
202 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
203}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700204BIONIC_BENCHMARK(BM_string_strcat_half_copy_half_seek);
Anders Lewis1c487e12017-06-12 12:33:06 -0700205
206static void BM_string_strcpy(benchmark::State& state) {
207 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700208 const size_t src_alignment = state.range(1);
209 const size_t dst_alignment = state.range(2);
210
211 std::vector<char> src;
212 std::vector<char> dst;
213 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
214 char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
215 src_aligned[nbytes - 1] = '\0';
Anders Lewis1c487e12017-06-12 12:33:06 -0700216
217 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700218 strcpy(dst_aligned, src_aligned);
Anders Lewis1c487e12017-06-12 12:33:06 -0700219 }
220
221 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
222}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700223BIONIC_BENCHMARK(BM_string_strcpy);
Anders Lewis1c487e12017-06-12 12:33:06 -0700224
225static void BM_string_strcmp(benchmark::State& state) {
226 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700227 const size_t s1_alignment = state.range(1);
228 const size_t s2_alignment = state.range(2);
229
230 std::vector<char> s1;
231 std::vector<char> s2;
232 char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
233 char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
234 s1_aligned[nbytes - 1] = '\0';
235 s2_aligned[nbytes - 1] = '\0';
Anders Lewis1c487e12017-06-12 12:33:06 -0700236
237 volatile int c __attribute__((unused));
238 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700239 c = strcmp(s1_aligned, s2_aligned);
Anders Lewis1c487e12017-06-12 12:33:06 -0700240 }
241
242 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
243}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700244BIONIC_BENCHMARK(BM_string_strcmp);
Anders Lewisac4f4b42017-08-08 18:29:51 -0700245
246static void BM_string_strstr(benchmark::State& state) {
247 const size_t nbytes = state.range(0);
248 const size_t haystack_alignment = state.range(1);
249 const size_t needle_alignment = state.range(2);
250
251 std::vector<char> haystack;
252 std::vector<char> needle;
253 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
254 char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
255 std::min(nbytes, static_cast<size_t>(5)), 'x');
256
257 if (nbytes / 4 > 2) {
258 for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
259 haystack_aligned[4 * i + 3] = 'y';
260 }
261 }
262 haystack_aligned[nbytes - 1] = '\0';
263 needle_aligned[needle.size() - 1] = '\0';
264
265 while (state.KeepRunning()) {
266 if (strstr(haystack_aligned, needle_aligned) == nullptr) {
Anders Lewisa98a5fb2017-08-09 16:52:19 -0700267 errx(1, "ERROR: strstr failed to find valid substring.");
Anders Lewisac4f4b42017-08-08 18:29:51 -0700268 }
269 }
270
271 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
272}
273BIONIC_BENCHMARK(BM_string_strstr);
274
275static void BM_string_strchr(benchmark::State& state) {
276 const size_t nbytes = state.range(0);
277 const size_t haystack_alignment = state.range(1);
278
279 std::vector<char> haystack;
280 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
Anders Lewisa98a5fb2017-08-09 16:52:19 -0700281 haystack_aligned[nbytes-1] = '\0';
Anders Lewisac4f4b42017-08-08 18:29:51 -0700282
283 while (state.KeepRunning()) {
284 if (strchr(haystack_aligned, 'y') != nullptr) {
Anders Lewisa98a5fb2017-08-09 16:52:19 -0700285 errx(1, "ERROR: strchr found a chr where it should have failed.");
Anders Lewisac4f4b42017-08-08 18:29:51 -0700286 }
287 }
288
289 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
290}
291BIONIC_BENCHMARK(BM_string_strchr);