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