Home | History | Annotate | Download | only in benchmarks
      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