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 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 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 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 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 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 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 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 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 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 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 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 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 251 static void BM_string_strstr(benchmark::State& state) { 252 const size_t nbytes = state.range(0); 253 const size_t haystack_alignment = state.range(1); 254 const size_t needle_alignment = state.range(2); 255 256 std::vector<char> haystack; 257 std::vector<char> needle; 258 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x'); 259 char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment, 260 std::min(nbytes, static_cast<size_t>(5)), 'x'); 261 262 if (nbytes / 4 > 2) { 263 for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) { 264 haystack_aligned[4 * i + 3] = 'y'; 265 } 266 } 267 haystack_aligned[nbytes - 1] = '\0'; 268 needle_aligned[needle.size() - 1] = '\0'; 269 270 while (state.KeepRunning()) { 271 if (strstr(haystack_aligned, needle_aligned) == nullptr) { 272 errx(1, "ERROR: strstr failed to find valid substring."); 273 } 274 } 275 276 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); 277 } 278 BIONIC_BENCHMARK_WITH_ARG(BM_string_strstr, "AT_ALIGNED_TWOBUF"); 279 280 static void BM_string_strchr(benchmark::State& state) { 281 const size_t nbytes = state.range(0); 282 const size_t haystack_alignment = state.range(1); 283 284 std::vector<char> haystack; 285 char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x'); 286 haystack_aligned[nbytes-1] = '\0'; 287 288 while (state.KeepRunning()) { 289 if (strchr(haystack_aligned, 'y') != nullptr) { 290 errx(1, "ERROR: strchr found a chr where it should have failed."); 291 } 292 } 293 294 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); 295 } 296 BIONIC_BENCHMARK_WITH_ARG(BM_string_strchr, "AT_ALIGNED_ONEBUF"); 297