blob: 94e7583f654e5a46c81ed24cc4081848e25c3257 [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
Christopher Ferrisdf4942c2015-02-17 19:58:53 -080017#include <stdint.h>
Elliott Hughes7be369d2012-11-08 15:37:43 -080018#include <string.h>
19
Elliott Hughes281e06b2016-02-17 10:23:52 -080020#include <benchmark/benchmark.h>
Anders Lewisa7b0f882017-07-24 20:01:13 -070021#include <util.h>
Elliott Hughes7be369d2012-11-08 15:37:43 -080022
Elliott Hughes281e06b2016-02-17 10:23:52 -080023static void BM_string_memcmp(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010024 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070025 const size_t src_alignment = state.range(1);
26 const size_t dst_alignment = state.range(2);
27
28 std::vector<char> src;
29 std::vector<char> dst;
30 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
31 char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'x');
Elliott Hughes7be369d2012-11-08 15:37:43 -080032
33 volatile int c __attribute__((unused)) = 0;
Elliott Hughes281e06b2016-02-17 10:23:52 -080034 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070035 c += memcmp(dst_aligned, src_aligned, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -080036 }
37
Elliott Hughes281e06b2016-02-17 10:23:52 -080038 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -080039}
Anders Lewisa7b0f882017-07-24 20:01:13 -070040BIONIC_BENCHMARK(BM_string_memcmp);
Elliott Hughes7be369d2012-11-08 15:37:43 -080041
Elliott Hughes281e06b2016-02-17 10:23:52 -080042static void BM_string_memcpy(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010043 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070044 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);
Elliott Hughes7be369d2012-11-08 15:37:43 -080051
Elliott Hughes281e06b2016-02-17 10:23:52 -080052 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070053 memcpy(dst_aligned, src_aligned, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -080054 }
55
Elliott Hughes281e06b2016-02-17 10:23:52 -080056 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -080057}
Anders Lewisa7b0f882017-07-24 20:01:13 -070058BIONIC_BENCHMARK(BM_string_memcpy);
Elliott Hughes7be369d2012-11-08 15:37:43 -080059
Anders Lewis271be9b2017-06-07 13:00:38 -070060static void BM_string_memmove_non_overlapping(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010061 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070062 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');
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080069
Elliott Hughes281e06b2016-02-17 10:23:52 -080070 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070071 memmove(dst_aligned, src_aligned, nbytes);
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080072 }
73
Elliott Hughes281e06b2016-02-17 10:23:52 -080074 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughesfbe44ec2012-11-09 14:59:21 -080075}
Anders Lewisa7b0f882017-07-24 20:01:13 -070076BIONIC_BENCHMARK(BM_string_memmove_non_overlapping);
Anders Lewis271be9b2017-06-07 13:00:38 -070077
78static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
79 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070080 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');
Anders Lewis271be9b2017-06-07 13:00:38 -070084
85 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -070086 memmove(buf_aligned, buf_aligned + 1, nbytes); // Worst-case overlap.
Anders Lewis271be9b2017-06-07 13:00:38 -070087 }
88
89 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
90}
Anders Lewisa7b0f882017-07-24 20:01:13 -070091BIONIC_BENCHMARK(BM_string_memmove_overlap_dst_before_src);
Anders Lewis271be9b2017-06-07 13:00:38 -070092
93static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
94 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -070095 const size_t alignment = state.range(1);
96
97 std::vector<char> buf;
98 char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
Anders Lewis271be9b2017-06-07 13:00:38 -070099
100 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700101 memmove(buf_aligned + 1, buf_aligned, nbytes); // Worst-case overlap.
Anders Lewis271be9b2017-06-07 13:00:38 -0700102 }
103
104 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
105}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700106BIONIC_BENCHMARK(BM_string_memmove_overlap_src_before_dst);
Elliott Hughesfbe44ec2012-11-09 14:59:21 -0800107
Elliott Hughes281e06b2016-02-17 10:23:52 -0800108static void BM_string_memset(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +0100109 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700110 const size_t alignment = state.range(1);
111
112 std::vector<char> buf;
113 char* buf_aligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800114
Elliott Hughes281e06b2016-02-17 10:23:52 -0800115 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700116 memset(buf_aligned, 0, nbytes);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800117 }
118
Elliott Hughes281e06b2016-02-17 10:23:52 -0800119 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -0800120}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700121BIONIC_BENCHMARK(BM_string_memset);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800122
Elliott Hughes281e06b2016-02-17 10:23:52 -0800123static void BM_string_strlen(benchmark::State& state) {
Martijn Coenenbe763d82016-11-14 14:16:08 +0100124 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700125 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';
Elliott Hughes7be369d2012-11-08 15:37:43 -0800130
131 volatile int c __attribute__((unused)) = 0;
Elliott Hughes281e06b2016-02-17 10:23:52 -0800132 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700133 c += strlen(buf_aligned);
Elliott Hughes7be369d2012-11-08 15:37:43 -0800134 }
135
Elliott Hughes281e06b2016-02-17 10:23:52 -0800136 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
Elliott Hughes7be369d2012-11-08 15:37:43 -0800137}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700138BIONIC_BENCHMARK(BM_string_strlen);
Anders Lewisa99d0522017-06-12 11:24:01 -0700139
140static void BM_string_strcat_copy_only(benchmark::State& state) {
141 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700142 const size_t src_alignment = state.range(1);
143 const size_t dst_alignment = state.range(2);
144
145 std::vector<char> src;
146 std::vector<char> dst;
147 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
148 char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes + 2);
149 src_aligned[nbytes - 1] = '\0';
150 dst_aligned[0] = 'y';
151 dst_aligned[1] = 'y';
152 dst_aligned[2] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700153
154 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700155 strcat(dst_aligned, src_aligned);
156 dst_aligned[2] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700157 }
158
159 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
160}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700161BIONIC_BENCHMARK(BM_string_strcat_copy_only);
Anders Lewisa99d0522017-06-12 11:24:01 -0700162
163static void BM_string_strcat_seek_only(benchmark::State& state) {
164 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700165 const size_t src_alignment = state.range(1);
166 const size_t dst_alignment = state.range(2);
167
168 std::vector<char> src;
169 std::vector<char> dst;
170 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, 3, 'x');
171 char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes + 2, 'y');
172 src_aligned[2] = '\0';
173 dst_aligned[nbytes - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700174
175 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700176 strcat(dst_aligned, src_aligned);
177 dst_aligned[nbytes - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700178 }
179
180 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
181}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700182BIONIC_BENCHMARK(BM_string_strcat_seek_only);
Anders Lewisa99d0522017-06-12 11:24:01 -0700183
184static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
185 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700186 const size_t src_alignment = state.range(1);
187 const size_t dst_alignment = state.range(2);
188
189 std::vector<char> src;
190 std::vector<char> dst;
191 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes / 2, 'x');
192 char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
193 src_aligned[nbytes / 2 - 1] = '\0';
194 dst_aligned[nbytes / 2 - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700195
196 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700197 strcat(dst_aligned, src_aligned);
198 dst_aligned[nbytes / 2 - 1] = '\0';
Anders Lewisa99d0522017-06-12 11:24:01 -0700199 }
200
201 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
202}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700203BIONIC_BENCHMARK(BM_string_strcat_half_copy_half_seek);
Anders Lewis1c487e12017-06-12 12:33:06 -0700204
205static void BM_string_strcpy(benchmark::State& state) {
206 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700207 const size_t src_alignment = state.range(1);
208 const size_t dst_alignment = state.range(2);
209
210 std::vector<char> src;
211 std::vector<char> dst;
212 char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
213 char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
214 src_aligned[nbytes - 1] = '\0';
Anders Lewis1c487e12017-06-12 12:33:06 -0700215
216 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700217 strcpy(dst_aligned, src_aligned);
Anders Lewis1c487e12017-06-12 12:33:06 -0700218 }
219
220 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
221}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700222BIONIC_BENCHMARK(BM_string_strcpy);
Anders Lewis1c487e12017-06-12 12:33:06 -0700223
224static void BM_string_strcmp(benchmark::State& state) {
225 const size_t nbytes = state.range(0);
Anders Lewisf4447b92017-06-23 15:53:59 -0700226 const size_t s1_alignment = state.range(1);
227 const size_t s2_alignment = state.range(2);
228
229 std::vector<char> s1;
230 std::vector<char> s2;
231 char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
232 char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
233 s1_aligned[nbytes - 1] = '\0';
234 s2_aligned[nbytes - 1] = '\0';
Anders Lewis1c487e12017-06-12 12:33:06 -0700235
236 volatile int c __attribute__((unused));
237 while (state.KeepRunning()) {
Anders Lewisf4447b92017-06-23 15:53:59 -0700238 c = strcmp(s1_aligned, s2_aligned);
Anders Lewis1c487e12017-06-12 12:33:06 -0700239 }
240
241 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
242}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700243BIONIC_BENCHMARK(BM_string_strcmp);
Anders Lewisac4f4b42017-08-08 18:29:51 -0700244
245static void BM_string_strstr(benchmark::State& state) {
246 const size_t nbytes = state.range(0);
247 const size_t haystack_alignment = state.range(1);
248 const size_t needle_alignment = state.range(2);
249
250 std::vector<char> haystack;
251 std::vector<char> needle;
252 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
253 char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment,
254 std::min(nbytes, static_cast<size_t>(5)), 'x');
255
256 if (nbytes / 4 > 2) {
257 for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) {
258 haystack_aligned[4 * i + 3] = 'y';
259 }
260 }
261 haystack_aligned[nbytes - 1] = '\0';
262 needle_aligned[needle.size() - 1] = '\0';
263
264 while (state.KeepRunning()) {
265 if (strstr(haystack_aligned, needle_aligned) == nullptr) {
266 abort();
267 }
268 }
269
270 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
271}
272BIONIC_BENCHMARK(BM_string_strstr);
273
274static void BM_string_strchr(benchmark::State& state) {
275 const size_t nbytes = state.range(0);
276 const size_t haystack_alignment = state.range(1);
277
278 std::vector<char> haystack;
279 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x');
280
281 while (state.KeepRunning()) {
282 if (strchr(haystack_aligned, 'y') != nullptr) {
283 abort();
284 }
285 }
286
287 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
288}
289BIONIC_BENCHMARK(BM_string_strchr);