• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 <langinfo.h>
19 #include <locale.h>
20 #include <malloc.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include <benchmark/benchmark.h>
25 #include "util.h"
26 
MallocFree(benchmark::State & state)27 static void MallocFree(benchmark::State& state) {
28   const size_t nbytes = state.range(0);
29   int pagesize = getpagesize();
30 
31   for (auto _ : state) {
32     void* ptr;
33     benchmark::DoNotOptimize(ptr = malloc(nbytes));
34     MakeAllocationResident(ptr, nbytes, pagesize);
35     free(ptr);
36   }
37 
38   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
39 }
40 
BM_stdlib_malloc_free_default(benchmark::State & state)41 static void BM_stdlib_malloc_free_default(benchmark::State& state) {
42 #if defined(__BIONIC__)
43   // The default is expected to be a zero decay time.
44   mallopt(M_DECAY_TIME, 0);
45 #endif
46 
47   MallocFree(state);
48 }
49 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_default, "AT_COMMON_SIZES");
50 
51 #if defined(__BIONIC__)
BM_stdlib_malloc_free_decay1(benchmark::State & state)52 static void BM_stdlib_malloc_free_decay1(benchmark::State& state) {
53   mallopt(M_DECAY_TIME, 1);
54 
55   MallocFree(state);
56 
57   mallopt(M_DECAY_TIME, 0);
58 }
59 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_decay1, "AT_COMMON_SIZES");
60 #endif
61 
CallocFree(benchmark::State & state)62 static void CallocFree(benchmark::State& state) {
63   const size_t nbytes = state.range(0);
64   int pagesize = getpagesize();
65 
66   for (auto _ : state) {
67     void* ptr;
68     benchmark::DoNotOptimize(ptr = calloc(1, nbytes));
69     MakeAllocationResident(ptr, nbytes, pagesize);
70     free(ptr);
71   }
72 
73   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
74 }
75 
BM_stdlib_calloc_free_default(benchmark::State & state)76 static void BM_stdlib_calloc_free_default(benchmark::State& state) {
77 #if defined(__BIONIC__)
78   // The default is expected to be a zero decay time.
79   mallopt(M_DECAY_TIME, 0);
80 #endif
81 
82   CallocFree(state);
83 }
84 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_default, "AT_COMMON_SIZES");
85 
86 #if defined(__BIONIC__)
BM_stdlib_calloc_free_decay1(benchmark::State & state)87 static void BM_stdlib_calloc_free_decay1(benchmark::State& state) {
88   mallopt(M_DECAY_TIME, 1);
89 
90   CallocFree(state);
91 
92   mallopt(M_DECAY_TIME, 0);
93 }
94 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_calloc_free_decay1, "AT_COMMON_SIZES");
95 #endif
96 
MallocMultiple(benchmark::State & state,size_t nbytes,size_t numAllocs)97 static void MallocMultiple(benchmark::State& state, size_t nbytes, size_t numAllocs) {
98   int pagesize = getpagesize();
99   void* ptrs[numAllocs];
100   for (auto _ : state) {
101     for (size_t i = 0; i < numAllocs; i++) {
102       benchmark::DoNotOptimize(ptrs[i] = reinterpret_cast<uint8_t*>(malloc(nbytes)));
103       MakeAllocationResident(ptrs[i], nbytes, pagesize);
104     }
105     state.PauseTiming(); // Stop timers while freeing pointers.
106     for (size_t i = 0; i < numAllocs; i++) {
107       free(ptrs[i]);
108     }
109     state.ResumeTiming();
110   }
111 
112   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes) * numAllocs);
113 }
114 
BM_stdlib_malloc_forty_default(benchmark::State & state)115 void BM_stdlib_malloc_forty_default(benchmark::State& state) {
116 
117 #if defined(__BIONIC__)
118   // The default is expected to be a zero decay time.
119   mallopt(M_DECAY_TIME, 0);
120 #endif
121 
122   MallocMultiple(state, state.range(0), 40);
123 }
124 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_default, "AT_COMMON_SIZES");
125 
126 #if defined(__BIONIC__)
BM_stdlib_malloc_forty_decay1(benchmark::State & state)127 void BM_stdlib_malloc_forty_decay1(benchmark::State& state) {
128   mallopt(M_DECAY_TIME, 1);
129 
130   MallocMultiple(state, state.range(0), 40);
131 
132   mallopt(M_DECAY_TIME, 0);
133 }
134 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_decay1, "AT_COMMON_SIZES");
135 #endif
136 
BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State & state)137 void BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State& state) {
138 #if defined(__BIONIC__)
139   // The default is expected to be a zero decay time.
140   mallopt(M_DECAY_TIME, 0);
141 #endif
142 
143   MallocMultiple(state, 8192, state.range(0));
144 }
145 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_default, "AT_SMALL_SIZES");
146 
147 #if defined(__BIONIC__)
BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State & state)148 void BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State& state) {
149   mallopt(M_DECAY_TIME, 1);
150 
151   MallocMultiple(state, 8192, state.range(0));
152 
153   mallopt(M_DECAY_TIME, 0);
154 }
155 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_decay1, "AT_SMALL_SIZES");
156 #endif
157 
BM_stdlib_mbstowcs_ascii(benchmark::State & state)158 static void BM_stdlib_mbstowcs_ascii(benchmark::State& state) {
159   // It doesn't really matter what ASCII character we pick.
160   // The flow through the fast path is the same regardless.
161   const size_t count = 500000;
162   std::vector<char> mbs(count, 'e');
163   std::vector<wchar_t> wcs(count);
164 
165   for (auto _ : state) {
166     benchmark::DoNotOptimize(mbstowcs(&wcs[0], &mbs[0], wcs.size()));
167   }
168 
169   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(wcs.size()));
170 }
171 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbstowcs_ascii, "");
172 
BM_stdlib_mbstowcs_wide(benchmark::State & state)173 static void BM_stdlib_mbstowcs_wide(benchmark::State& state) {
174   // It doesn't matter much what wide character we pick.
175   // A three-byte character seems pretty representative, and all three byte
176   // characters are the same from the code's perspective.
177   const size_t count = 500000;
178   std::string mbs;
179   for (size_t i = 0; i < count; i++) {
180     mbs += "\xe5\xb1\xb1";
181   }
182   std::vector<wchar_t> wcs(count);
183 
184   for (auto _ : state) {
185     benchmark::DoNotOptimize(mbstowcs(&wcs[0], &mbs[0], wcs.size()));
186   }
187 
188   state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(wcs.size()));
189 }
190 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbstowcs_wide, "");
191 
BM_stdlib_mbrtowc_1(benchmark::State & state)192 static void BM_stdlib_mbrtowc_1(benchmark::State& state) {
193   wchar_t wc;
194   for (auto _ : state) {
195     benchmark::DoNotOptimize(mbrtowc(&wc, "e", 1, nullptr));
196   }
197 }
198 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_1, "");
199 
BM_stdlib_mbrtowc_2(benchmark::State & state)200 static void BM_stdlib_mbrtowc_2(benchmark::State& state) {
201   wchar_t wc;
202   for (auto _ : state) {
203     benchmark::DoNotOptimize(mbrtowc(&wc, "\xc3\x9f", 3, nullptr));
204   }
205 }
206 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_2, "");
207 
BM_stdlib_mbrtowc_3(benchmark::State & state)208 static void BM_stdlib_mbrtowc_3(benchmark::State& state) {
209   wchar_t wc;
210   for (auto _ : state) {
211     benchmark::DoNotOptimize(mbrtowc(&wc, "\xe5\xb1\xb1", 3, nullptr));
212   }
213 }
214 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_3, "");
215 
BM_stdlib_mbrtowc_4(benchmark::State & state)216 static void BM_stdlib_mbrtowc_4(benchmark::State& state) {
217   wchar_t wc;
218   for (auto _ : state) {
219     benchmark::DoNotOptimize(mbrtowc(&wc, "\xf0\xa4\xad\xa2", 4, nullptr));
220   }
221 }
222 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc_4, "");
223 
224 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_atoi, atoi(" -123"));
225 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_atol, atol(" -123"));
226 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtol, strtol(" -123", nullptr, 0));
227 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoll, strtoll(" -123", nullptr, 0));
228 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoul, strtoul(" -123", nullptr, 0));
229 BIONIC_TRIVIAL_BENCHMARK(BM_stdlib_strtoull, strtoull(" -123", nullptr, 0));
230