• 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 <stdint.h>
18 #include <string.h>
19 
20 #include <benchmark/benchmark.h>
21 #include "util.h"
22 
23 constexpr auto KB = 1024;
24 
25 // NOTE: these constants are temporary replacements for AT_COMMON_SIZES until
26 // the new interface for Bionic benchmarks is implemented.
27 
28 // Set all four to 0 to test normal alignment.
29 #define AT_SRC_ALIGN 0
30 #define AT_DST_ALIGN 0
31 
32 #define AT_ALIGNED_TWOBUF \
33     Args({(8), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
34     Args({(512), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(1*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
35     Args({(8*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(16*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
36     Args({(32*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64*KB), AT_SRC_ALIGN, AT_DST_ALIGN})
37 
38 #define AT_ALIGNED_ONEBUF \
39     Args({(8), AT_SRC_ALIGN})->Args({(64), AT_SRC_ALIGN})->Args({(512), AT_SRC_ALIGN})-> \
40     Args({(1*KB), AT_SRC_ALIGN})->Args({(8*KB), AT_SRC_ALIGN})->Args({(16*KB), AT_SRC_ALIGN})-> \
41     Args({(32*KB), AT_SRC_ALIGN})->Args({(64*KB), AT_SRC_ALIGN})
42 
BM_string_memcmp(benchmark::State & state)43 static void BM_string_memcmp(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 = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'x');
52 
53   volatile int c __attribute__((unused)) = 0;
54   while (state.KeepRunning()) {
55     c += memcmp(dst_aligned, src_aligned, nbytes);
56   }
57 
58   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
59 }
60 BENCHMARK(BM_string_memcmp)->AT_ALIGNED_TWOBUF;
61 
BM_string_memcpy(benchmark::State & state)62 static void BM_string_memcpy(benchmark::State& state) {
63   const size_t nbytes = state.range(0);
64   const size_t src_alignment = state.range(1);
65   const size_t dst_alignment = state.range(2);
66 
67   std::vector<char> src;
68   std::vector<char> dst;
69   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
70   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
71 
72   while (state.KeepRunning()) {
73     memcpy(dst_aligned, src_aligned, nbytes);
74   }
75 
76   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
77 }
78 BENCHMARK(BM_string_memcpy)->AT_ALIGNED_TWOBUF;
79 
BM_string_memmove_non_overlapping(benchmark::State & state)80 static void BM_string_memmove_non_overlapping(benchmark::State& state) {
81   const size_t nbytes = state.range(0);
82   const size_t src_alignment = state.range(1);
83   const size_t dst_alignment = state.range(2);
84 
85   std::vector<char> src;
86   std::vector<char> dst;
87   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
88   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
89 
90   while (state.KeepRunning()) {
91     memmove(dst_aligned, src_aligned, nbytes);
92   }
93 
94   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
95 }
96 BENCHMARK(BM_string_memmove_non_overlapping)->AT_ALIGNED_TWOBUF;
97 
BM_string_memmove_overlap_dst_before_src(benchmark::State & state)98 static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
99   const size_t nbytes = state.range(0);
100   const size_t alignment = state.range(1);
101 
102   std::vector<char> buf(3 * alignment + nbytes + 1, 'x');
103   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
104 
105   while (state.KeepRunning()) {
106     memmove(buf_aligned, buf_aligned + 1, nbytes);  // Worst-case overlap.
107   }
108 
109   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
110 }
111 BENCHMARK(BM_string_memmove_overlap_dst_before_src)->AT_ALIGNED_ONEBUF;
112 
BM_string_memmove_overlap_src_before_dst(benchmark::State & state)113 static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
114   const size_t nbytes = state.range(0);
115   const size_t alignment = state.range(1);
116 
117   std::vector<char> buf;
118   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
119 
120   while (state.KeepRunning()) {
121     memmove(buf_aligned + 1, buf_aligned, nbytes);  // Worst-case overlap.
122   }
123 
124   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
125 }
126 BENCHMARK(BM_string_memmove_overlap_src_before_dst)->AT_ALIGNED_ONEBUF;
127 
BM_string_memset(benchmark::State & state)128 static void BM_string_memset(benchmark::State& state) {
129   const size_t nbytes = state.range(0);
130   const size_t alignment = state.range(1);
131 
132   std::vector<char> buf;
133   char* buf_aligned = GetAlignedPtr(&buf, alignment, nbytes + 1);
134 
135   while (state.KeepRunning()) {
136     memset(buf_aligned, 0, nbytes);
137   }
138 
139   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
140 }
141 BENCHMARK(BM_string_memset)->AT_ALIGNED_ONEBUF;
142 
BM_string_strlen(benchmark::State & state)143 static void BM_string_strlen(benchmark::State& state) {
144   const size_t nbytes = state.range(0);
145   const size_t alignment = state.range(1);
146 
147   std::vector<char> buf;
148   char* buf_aligned = GetAlignedPtrFilled(&buf, alignment, nbytes + 1, 'x');
149   buf_aligned[nbytes - 1] = '\0';
150 
151   volatile int c __attribute__((unused)) = 0;
152   while (state.KeepRunning()) {
153     c += strlen(buf_aligned);
154   }
155 
156   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
157 }
158 BENCHMARK(BM_string_strlen)->AT_ALIGNED_ONEBUF;
159 
BM_string_strcat_copy_only(benchmark::State & state)160 static void BM_string_strcat_copy_only(benchmark::State& state) {
161   const size_t nbytes = state.range(0);
162   const size_t src_alignment = state.range(1);
163   const size_t dst_alignment = state.range(2);
164 
165   std::vector<char> src;
166   std::vector<char> dst;
167   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
168   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes + 2);
169   src_aligned[nbytes - 1] = '\0';
170   dst_aligned[0] = 'y';
171   dst_aligned[1] = 'y';
172   dst_aligned[2] = '\0';
173 
174   while (state.KeepRunning()) {
175     strcat(dst_aligned, src_aligned);
176     dst_aligned[2] = '\0';
177   }
178 
179   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
180 }
181 BENCHMARK(BM_string_strcat_copy_only)->AT_ALIGNED_TWOBUF;
182 
BM_string_strcat_seek_only(benchmark::State & state)183 static void BM_string_strcat_seek_only(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   std::vector<char> src;
189   std::vector<char> dst;
190   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, 3, 'x');
191   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes + 2, 'y');
192   src_aligned[2] = '\0';
193   dst_aligned[nbytes - 1] = '\0';
194 
195   while (state.KeepRunning()) {
196     strcat(dst_aligned, src_aligned);
197     dst_aligned[nbytes - 1] = '\0';
198   }
199 
200   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
201 }
202 BENCHMARK(BM_string_strcat_seek_only)->AT_ALIGNED_TWOBUF;
203 
BM_string_strcat_half_copy_half_seek(benchmark::State & state)204 static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
205   const size_t nbytes = state.range(0);
206   const size_t src_alignment = state.range(1);
207   const size_t dst_alignment = state.range(2);
208 
209   std::vector<char> src;
210   std::vector<char> dst;
211   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes / 2, 'x');
212   char* dst_aligned = GetAlignedPtrFilled(&dst, dst_alignment, nbytes, 'y');
213   src_aligned[nbytes / 2 - 1] = '\0';
214   dst_aligned[nbytes / 2 - 1] = '\0';
215 
216   while (state.KeepRunning()) {
217     strcat(dst_aligned, src_aligned);
218     dst_aligned[nbytes / 2 - 1] = '\0';
219   }
220 
221   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
222 }
223 BENCHMARK(BM_string_strcat_half_copy_half_seek)->AT_ALIGNED_TWOBUF;
224 
BM_string_strcpy(benchmark::State & state)225 static void BM_string_strcpy(benchmark::State& state) {
226   const size_t nbytes = state.range(0);
227   const size_t src_alignment = state.range(1);
228   const size_t dst_alignment = state.range(2);
229 
230   std::vector<char> src;
231   std::vector<char> dst;
232   char* src_aligned = GetAlignedPtrFilled(&src, src_alignment, nbytes, 'x');
233   char* dst_aligned = GetAlignedPtr(&dst, dst_alignment, nbytes);
234   src_aligned[nbytes - 1] = '\0';
235 
236   while (state.KeepRunning()) {
237     strcpy(dst_aligned, src_aligned);
238   }
239 
240   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
241 }
242 BENCHMARK(BM_string_strcpy)->AT_ALIGNED_TWOBUF;
243 
BM_string_strcmp(benchmark::State & state)244 static void BM_string_strcmp(benchmark::State& state) {
245   const size_t nbytes = state.range(0);
246   const size_t s1_alignment = state.range(1);
247   const size_t s2_alignment = state.range(2);
248 
249   std::vector<char> s1;
250   std::vector<char> s2;
251   char* s1_aligned = GetAlignedPtrFilled(&s1, s1_alignment, nbytes, 'x');
252   char* s2_aligned = GetAlignedPtrFilled(&s2, s2_alignment, nbytes, 'x');
253   s1_aligned[nbytes - 1] = '\0';
254   s2_aligned[nbytes - 1] = '\0';
255 
256   volatile int c __attribute__((unused));
257   while (state.KeepRunning()) {
258     c = strcmp(s1_aligned, s2_aligned);
259   }
260 
261   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
262 }
263 BENCHMARK(BM_string_strcmp)->AT_ALIGNED_TWOBUF;
264