xref: /aosp_15_r20/bionic/benchmarks/stdlib_benchmark.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2017 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  *
4*8d67ca89SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*8d67ca89SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*8d67ca89SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*8d67ca89SAndroid Build Coastguard Worker  *
8*8d67ca89SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*8d67ca89SAndroid Build Coastguard Worker  *
10*8d67ca89SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*8d67ca89SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*8d67ca89SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8d67ca89SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*8d67ca89SAndroid Build Coastguard Worker  * limitations under the License.
15*8d67ca89SAndroid Build Coastguard Worker  */
16*8d67ca89SAndroid Build Coastguard Worker 
17*8d67ca89SAndroid Build Coastguard Worker #include <err.h>
18*8d67ca89SAndroid Build Coastguard Worker #include <langinfo.h>
19*8d67ca89SAndroid Build Coastguard Worker #include <locale.h>
20*8d67ca89SAndroid Build Coastguard Worker #include <malloc.h>
21*8d67ca89SAndroid Build Coastguard Worker #include <stdlib.h>
22*8d67ca89SAndroid Build Coastguard Worker #include <unistd.h>
23*8d67ca89SAndroid Build Coastguard Worker 
24*8d67ca89SAndroid Build Coastguard Worker #include <benchmark/benchmark.h>
25*8d67ca89SAndroid Build Coastguard Worker #include "ScopedDecayTimeRestorer.h"
26*8d67ca89SAndroid Build Coastguard Worker #include "util.h"
27*8d67ca89SAndroid Build Coastguard Worker 
MallocFree(benchmark::State & state)28*8d67ca89SAndroid Build Coastguard Worker static void MallocFree(benchmark::State& state) {
29*8d67ca89SAndroid Build Coastguard Worker   const size_t nbytes = state.range(0);
30*8d67ca89SAndroid Build Coastguard Worker   int pagesize = getpagesize();
31*8d67ca89SAndroid Build Coastguard Worker 
32*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
33*8d67ca89SAndroid Build Coastguard Worker     void* ptr;
34*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(ptr = malloc(nbytes));
35*8d67ca89SAndroid Build Coastguard Worker     MakeAllocationResident(ptr, nbytes, pagesize);
36*8d67ca89SAndroid Build Coastguard Worker     free(ptr);
37*8d67ca89SAndroid Build Coastguard Worker   }
38*8d67ca89SAndroid Build Coastguard Worker 
39*8d67ca89SAndroid Build Coastguard Worker   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
40*8d67ca89SAndroid Build Coastguard Worker }
41*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_malloc_free_default(benchmark::State & state)42*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_malloc_free_default(benchmark::State& state) {
43*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
44*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
45*8d67ca89SAndroid Build Coastguard Worker 
46*8d67ca89SAndroid Build Coastguard Worker   // The default is expected to be a zero decay time.
47*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 0);
48*8d67ca89SAndroid Build Coastguard Worker #endif
49*8d67ca89SAndroid Build Coastguard Worker 
50*8d67ca89SAndroid Build Coastguard Worker   MallocFree(state);
51*8d67ca89SAndroid Build Coastguard Worker }
52*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_default, "AT_COMMON_SIZES");
53*8d67ca89SAndroid Build Coastguard Worker 
54*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
BM_stdlib_malloc_free_decay1(benchmark::State & state)55*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_malloc_free_decay1(benchmark::State& state) {
56*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
57*8d67ca89SAndroid Build Coastguard Worker 
58*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 1);
59*8d67ca89SAndroid Build Coastguard Worker 
60*8d67ca89SAndroid Build Coastguard Worker   MallocFree(state);
61*8d67ca89SAndroid Build Coastguard Worker }
62*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_decay1, "AT_COMMON_SIZES");
63*8d67ca89SAndroid Build Coastguard Worker #endif
64*8d67ca89SAndroid Build Coastguard Worker 
CallocFree(benchmark::State & state)65*8d67ca89SAndroid Build Coastguard Worker static void CallocFree(benchmark::State& state) {
66*8d67ca89SAndroid Build Coastguard Worker   const size_t nbytes = state.range(0);
67*8d67ca89SAndroid Build Coastguard Worker   int pagesize = getpagesize();
68*8d67ca89SAndroid Build Coastguard Worker 
69*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
70*8d67ca89SAndroid Build Coastguard Worker     void* ptr;
71*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(ptr = calloc(1, nbytes));
72*8d67ca89SAndroid Build Coastguard Worker     MakeAllocationResident(ptr, nbytes, pagesize);
73*8d67ca89SAndroid Build Coastguard Worker     free(ptr);
74*8d67ca89SAndroid Build Coastguard Worker   }
75*8d67ca89SAndroid Build Coastguard Worker 
76*8d67ca89SAndroid Build Coastguard Worker   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
77*8d67ca89SAndroid Build Coastguard Worker }
78*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_calloc_free_default(benchmark::State & state)79*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_calloc_free_default(benchmark::State& state) {
80*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
81*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
82*8d67ca89SAndroid Build Coastguard Worker 
83*8d67ca89SAndroid Build Coastguard Worker   // The default is expected to be a zero decay time.
84*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 0);
85*8d67ca89SAndroid Build Coastguard Worker #endif
86*8d67ca89SAndroid Build Coastguard Worker 
87*8d67ca89SAndroid Build Coastguard Worker   CallocFree(state);
88*8d67ca89SAndroid Build Coastguard Worker }
89*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_default, "AT_COMMON_SIZES");
90*8d67ca89SAndroid Build Coastguard Worker 
91*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
BM_stdlib_calloc_free_decay1(benchmark::State & state)92*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_calloc_free_decay1(benchmark::State& state) {
93*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 1);
94*8d67ca89SAndroid Build Coastguard Worker 
95*8d67ca89SAndroid Build Coastguard Worker   CallocFree(state);
96*8d67ca89SAndroid Build Coastguard Worker 
97*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 0);
98*8d67ca89SAndroid Build Coastguard Worker }
99*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_decay1, "AT_COMMON_SIZES");
100*8d67ca89SAndroid Build Coastguard Worker #endif
101*8d67ca89SAndroid Build Coastguard Worker 
MallocMultiple(benchmark::State & state,size_t nbytes,size_t numAllocs)102*8d67ca89SAndroid Build Coastguard Worker static void MallocMultiple(benchmark::State& state, size_t nbytes, size_t numAllocs) {
103*8d67ca89SAndroid Build Coastguard Worker   int pagesize = getpagesize();
104*8d67ca89SAndroid Build Coastguard Worker   void* ptrs[numAllocs];
105*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
106*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < numAllocs; i++) {
107*8d67ca89SAndroid Build Coastguard Worker       benchmark::DoNotOptimize(ptrs[i] = reinterpret_cast<uint8_t*>(malloc(nbytes)));
108*8d67ca89SAndroid Build Coastguard Worker       MakeAllocationResident(ptrs[i], nbytes, pagesize);
109*8d67ca89SAndroid Build Coastguard Worker     }
110*8d67ca89SAndroid Build Coastguard Worker     state.PauseTiming(); // Stop timers while freeing pointers.
111*8d67ca89SAndroid Build Coastguard Worker     for (size_t i = 0; i < numAllocs; i++) {
112*8d67ca89SAndroid Build Coastguard Worker       free(ptrs[i]);
113*8d67ca89SAndroid Build Coastguard Worker     }
114*8d67ca89SAndroid Build Coastguard Worker     state.ResumeTiming();
115*8d67ca89SAndroid Build Coastguard Worker   }
116*8d67ca89SAndroid Build Coastguard Worker 
117*8d67ca89SAndroid Build Coastguard Worker   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes) * numAllocs);
118*8d67ca89SAndroid Build Coastguard Worker }
119*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_malloc_forty_default(benchmark::State & state)120*8d67ca89SAndroid Build Coastguard Worker void BM_stdlib_malloc_forty_default(benchmark::State& state) {
121*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
122*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
123*8d67ca89SAndroid Build Coastguard Worker 
124*8d67ca89SAndroid Build Coastguard Worker   // The default is expected to be a zero decay time.
125*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 0);
126*8d67ca89SAndroid Build Coastguard Worker #endif
127*8d67ca89SAndroid Build Coastguard Worker 
128*8d67ca89SAndroid Build Coastguard Worker   MallocMultiple(state, state.range(0), 40);
129*8d67ca89SAndroid Build Coastguard Worker }
130*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_default, "AT_COMMON_SIZES");
131*8d67ca89SAndroid Build Coastguard Worker 
132*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
BM_stdlib_malloc_forty_decay1(benchmark::State & state)133*8d67ca89SAndroid Build Coastguard Worker void BM_stdlib_malloc_forty_decay1(benchmark::State& state) {
134*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
135*8d67ca89SAndroid Build Coastguard Worker 
136*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 1);
137*8d67ca89SAndroid Build Coastguard Worker 
138*8d67ca89SAndroid Build Coastguard Worker   MallocMultiple(state, state.range(0), 40);
139*8d67ca89SAndroid Build Coastguard Worker }
140*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_decay1, "AT_COMMON_SIZES");
141*8d67ca89SAndroid Build Coastguard Worker #endif
142*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State & state)143*8d67ca89SAndroid Build Coastguard Worker void BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State& state) {
144*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
145*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
146*8d67ca89SAndroid Build Coastguard Worker 
147*8d67ca89SAndroid Build Coastguard Worker   // The default is expected to be a zero decay time.
148*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 0);
149*8d67ca89SAndroid Build Coastguard Worker #endif
150*8d67ca89SAndroid Build Coastguard Worker 
151*8d67ca89SAndroid Build Coastguard Worker   MallocMultiple(state, 8192, state.range(0));
152*8d67ca89SAndroid Build Coastguard Worker }
153*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_default, "AT_SMALL_SIZES");
154*8d67ca89SAndroid Build Coastguard Worker 
155*8d67ca89SAndroid Build Coastguard Worker #if defined(__BIONIC__)
BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State & state)156*8d67ca89SAndroid Build Coastguard Worker void BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State& state) {
157*8d67ca89SAndroid Build Coastguard Worker   ScopedDecayTimeRestorer restorer;
158*8d67ca89SAndroid Build Coastguard Worker 
159*8d67ca89SAndroid Build Coastguard Worker   mallopt(M_DECAY_TIME, 1);
160*8d67ca89SAndroid Build Coastguard Worker 
161*8d67ca89SAndroid Build Coastguard Worker   MallocMultiple(state, 8192, state.range(0));
162*8d67ca89SAndroid Build Coastguard Worker }
163*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_decay1, "AT_SMALL_SIZES");
164*8d67ca89SAndroid Build Coastguard Worker #endif
165*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbstowcs_ascii(benchmark::State & state)166*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbstowcs_ascii(benchmark::State& state) {
167*8d67ca89SAndroid Build Coastguard Worker   // It doesn't really matter what ASCII character we pick.
168*8d67ca89SAndroid Build Coastguard Worker   // The flow through the fast path is the same regardless.
169*8d67ca89SAndroid Build Coastguard Worker   const size_t count = 500000;
170*8d67ca89SAndroid Build Coastguard Worker   std::vector<char> mbs(count, 'e');
171*8d67ca89SAndroid Build Coastguard Worker   std::vector<wchar_t> wcs(count);
172*8d67ca89SAndroid Build Coastguard Worker 
173*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
174*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbstowcs(&wcs[0], &mbs[0], wcs.size()));
175*8d67ca89SAndroid Build Coastguard Worker   }
176*8d67ca89SAndroid Build Coastguard Worker 
177*8d67ca89SAndroid Build Coastguard Worker   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(wcs.size()));
178*8d67ca89SAndroid Build Coastguard Worker }
179*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbstowcs_ascii, "");
180*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbstowcs_wide(benchmark::State & state)181*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbstowcs_wide(benchmark::State& state) {
182*8d67ca89SAndroid Build Coastguard Worker   // It doesn't matter much what wide character we pick.
183*8d67ca89SAndroid Build Coastguard Worker   // A three-byte character seems pretty representative, and all three byte
184*8d67ca89SAndroid Build Coastguard Worker   // characters are the same from the code's perspective.
185*8d67ca89SAndroid Build Coastguard Worker   const size_t count = 500000;
186*8d67ca89SAndroid Build Coastguard Worker   std::string mbs;
187*8d67ca89SAndroid Build Coastguard Worker   for (size_t i = 0; i < count; i++) {
188*8d67ca89SAndroid Build Coastguard Worker     mbs += "\xe5\xb1\xb1";
189*8d67ca89SAndroid Build Coastguard Worker   }
190*8d67ca89SAndroid Build Coastguard Worker   std::vector<wchar_t> wcs(count);
191*8d67ca89SAndroid Build Coastguard Worker 
192*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
193*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbstowcs(&wcs[0], &mbs[0], wcs.size()));
194*8d67ca89SAndroid Build Coastguard Worker   }
195*8d67ca89SAndroid Build Coastguard Worker 
196*8d67ca89SAndroid Build Coastguard Worker   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(wcs.size()));
197*8d67ca89SAndroid Build Coastguard Worker }
198*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbstowcs_wide, "");
199*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbrtowc_1(benchmark::State & state)200*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbrtowc_1(benchmark::State& state) {
201*8d67ca89SAndroid Build Coastguard Worker   wchar_t wc;
202*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
203*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbrtowc(&wc, "e", 1, nullptr));
204*8d67ca89SAndroid Build Coastguard Worker   }
205*8d67ca89SAndroid Build Coastguard Worker }
206*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_1, "");
207*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbrtowc_2(benchmark::State & state)208*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbrtowc_2(benchmark::State& state) {
209*8d67ca89SAndroid Build Coastguard Worker   wchar_t wc;
210*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
211*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbrtowc(&wc, "\xc3\x9f", 3, nullptr));
212*8d67ca89SAndroid Build Coastguard Worker   }
213*8d67ca89SAndroid Build Coastguard Worker }
214*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_2, "");
215*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbrtowc_3(benchmark::State & state)216*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbrtowc_3(benchmark::State& state) {
217*8d67ca89SAndroid Build Coastguard Worker   wchar_t wc;
218*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
219*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbrtowc(&wc, "\xe5\xb1\xb1", 3, nullptr));
220*8d67ca89SAndroid Build Coastguard Worker   }
221*8d67ca89SAndroid Build Coastguard Worker }
222*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_3, "");
223*8d67ca89SAndroid Build Coastguard Worker 
BM_stdlib_mbrtowc_4(benchmark::State & state)224*8d67ca89SAndroid Build Coastguard Worker static void BM_stdlib_mbrtowc_4(benchmark::State& state) {
225*8d67ca89SAndroid Build Coastguard Worker   wchar_t wc;
226*8d67ca89SAndroid Build Coastguard Worker   for (auto _ : state) {
227*8d67ca89SAndroid Build Coastguard Worker     benchmark::DoNotOptimize(mbrtowc(&wc, "\xf0\xa4\xad\xa2", 4, nullptr));
228*8d67ca89SAndroid Build Coastguard Worker   }
229*8d67ca89SAndroid Build Coastguard Worker }
230*8d67ca89SAndroid Build Coastguard Worker BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_4, "");
231*8d67ca89SAndroid Build Coastguard Worker 
232*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_atoi, atoi(" -123"));
233*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_atol, atol(" -123"));
234*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtol, strtol(" -123", nullptr, 0));
235*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoll, strtoll(" -123", nullptr, 0));
236*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoul, strtoul(" -123", nullptr, 0));
237*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoull, strtoull(" -123", nullptr, 0));
238*8d67ca89SAndroid Build Coastguard Worker 
239*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtol_hex, strtol("0xdeadbeef", nullptr, 0));
240*8d67ca89SAndroid Build Coastguard Worker BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoul_hex, strtoul("0xdeadbeef", nullptr, 0));
241