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 27 #if defined(__BIONIC__) 28 29 #else 30 #endif 31 32 static __always_inline void MakeAllocationResident(void* ptr, size_t nbytes, int pagesize) { 33 uint8_t* data = reinterpret_cast<uint8_t*>(ptr); 34 for (size_t i = 0; i < nbytes; i += pagesize) { 35 data[i] = 1; 36 } 37 } 38 39 static void MallocFree(benchmark::State& state) { 40 const size_t nbytes = state.range(0); 41 int pagesize = getpagesize(); 42 43 for (auto _ : state) { 44 void* ptr; 45 benchmark::DoNotOptimize(ptr = malloc(nbytes)); 46 MakeAllocationResident(ptr, nbytes, pagesize); 47 free(ptr); 48 } 49 50 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); 51 } 52 53 static void BM_stdlib_malloc_free_default(benchmark::State& state) { 54 #if defined(__BIONIC__) 55 // The default is expected to be a zero decay time. 56 mallopt(M_DECAY_TIME, 0); 57 #endif 58 59 MallocFree(state); 60 } 61 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_default, "AT_COMMON_SIZES"); 62 63 #if defined(__BIONIC__) 64 static void BM_stdlib_malloc_free_decay1(benchmark::State& state) { 65 mallopt(M_DECAY_TIME, 1); 66 67 MallocFree(state); 68 69 mallopt(M_DECAY_TIME, 0); 70 } 71 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_free_decay1, "AT_COMMON_SIZES"); 72 #endif 73 74 static void MallocMultiple(benchmark::State& state, size_t nbytes, size_t numAllocs) { 75 int pagesize = getpagesize(); 76 void* ptrs[numAllocs]; 77 for (auto _ : state) { 78 for (size_t i = 0; i < numAllocs; i++) { 79 benchmark::DoNotOptimize(ptrs[i] = reinterpret_cast<uint8_t*>(malloc(nbytes))); 80 MakeAllocationResident(ptrs[i], nbytes, pagesize); 81 } 82 state.PauseTiming(); // Stop timers while freeing pointers. 83 for (size_t i = 0; i < numAllocs; i++) { 84 free(ptrs[i]); 85 } 86 state.ResumeTiming(); 87 } 88 89 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes) * numAllocs); 90 } 91 92 void BM_stdlib_malloc_forty_default(benchmark::State& state) { 93 94 #if defined(__BIONIC__) 95 // The default is expected to be a zero decay time. 96 mallopt(M_DECAY_TIME, 0); 97 #endif 98 99 MallocMultiple(state, state.range(0), 40); 100 } 101 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_default, "AT_COMMON_SIZES"); 102 103 #if defined(__BIONIC__) 104 void BM_stdlib_malloc_forty_decay1(benchmark::State& state) { 105 mallopt(M_DECAY_TIME, 1); 106 107 MallocMultiple(state, state.range(0), 40); 108 109 mallopt(M_DECAY_TIME, 0); 110 } 111 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_forty_decay1, "AT_COMMON_SIZES"); 112 #endif 113 114 void BM_stdlib_malloc_multiple_8192_allocs_default(benchmark::State& state) { 115 #if defined(__BIONIC__) 116 // The default is expected to be a zero decay time. 117 mallopt(M_DECAY_TIME, 0); 118 #endif 119 120 MallocMultiple(state, 8192, state.range(0)); 121 } 122 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_default, "AT_SMALL_SIZES"); 123 124 #if defined(__BIONIC__) 125 void BM_stdlib_malloc_multiple_8192_allocs_decay1(benchmark::State& state) { 126 mallopt(M_DECAY_TIME, 1); 127 128 MallocMultiple(state, 8192, state.range(0)); 129 130 mallopt(M_DECAY_TIME, 0); 131 } 132 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_malloc_multiple_8192_allocs_decay1, "AT_SMALL_SIZES"); 133 #endif 134 135 static void BM_stdlib_mbstowcs(benchmark::State& state) { 136 const size_t buf_alignment = state.range(0); 137 const size_t widebuf_alignment = state.range(1); 138 139 std::vector<char> buf; 140 std::vector<wchar_t> widebuf; 141 142 setlocale(LC_CTYPE, "C.UTF-8") 143 || setlocale(LC_CTYPE, "en_US.UTF-8") 144 || setlocale(LC_CTYPE, "en_GB.UTF-8") 145 || setlocale(LC_CTYPE, "en.UTF-8") 146 || setlocale(LC_CTYPE, "de_DE-8") 147 || setlocale(LC_CTYPE, "fr_FR-8"); 148 if (strcmp(nl_langinfo(CODESET), "UTF-8")) { 149 errx(1, "ERROR: unable to set locale in BM_stdlib_mbstowcs"); 150 } 151 152 char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000); 153 wchar_t* widebuf_aligned = GetAlignedPtr(&widebuf, widebuf_alignment, 500000); 154 size_t i, j, k, l; 155 l = 0; 156 for (i=0xc3; i<0xe0; i++) 157 for (j=0x80; j<0xc0; j++) 158 buf[l++] = i, buf[l++] = j; 159 for (i=0xe1; i<0xed; i++) 160 for (j=0x80; j<0xc0; j++) 161 for (k=0x80; k<0xc0; k++) 162 buf[l++] = i, buf[l++] = j, buf[l++] = k; 163 for (i=0xf1; i<0xf4; i++) 164 for (j=0x80; j<0xc0; j++) 165 for (k=0x80; k<0xc0; k++) 166 buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k; 167 buf[l++] = 0; 168 169 volatile size_t c __attribute__((unused)) = 0; 170 for (auto _ : state) { 171 c = mbstowcs(widebuf_aligned, buf_aligned, 500000); 172 } 173 174 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000)); 175 } 176 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbstowcs, "0 0"); 177 178 static void BM_stdlib_mbrtowc(benchmark::State& state) { 179 const size_t buf_alignment = state.range(0); 180 181 std::vector<char> buf; 182 183 setlocale(LC_CTYPE, "C.UTF-8") 184 || setlocale(LC_CTYPE, "en_US.UTF-8") 185 || setlocale(LC_CTYPE, "en_GB.UTF-8") 186 || setlocale(LC_CTYPE, "en.UTF-8") 187 || setlocale(LC_CTYPE, "de_DE-8") 188 || setlocale(LC_CTYPE, "fr_FR-8"); 189 if (strcmp(nl_langinfo(CODESET), "UTF-8")) { 190 errx(1, "ERROR: unable to set locale in BM_stdlib_mbrtowc"); 191 } 192 193 char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000); 194 size_t i, j, k, l; 195 l = 0; 196 for (i=0xc3; i<0xe0; i++) 197 for (j=0x80; j<0xc0; j++) 198 buf[l++] = i, buf[l++] = j; 199 for (i=0xe1; i<0xed; i++) 200 for (j=0x80; j<0xc0; j++) 201 for (k=0x80; k<0xc0; k++) 202 buf[l++] = i, buf[l++] = j, buf[l++] = k; 203 for (i=0xf1; i<0xf4; i++) 204 for (j=0x80; j<0xc0; j++) 205 for (k=0x80; k<0xc0; k++) 206 buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k; 207 buf[l++] = 0; 208 209 wchar_t wc = 0; 210 for (auto _ : state) { 211 for (j = 0; buf_aligned[j]; j+=mbrtowc(&wc, buf_aligned + j, 4, nullptr)) { 212 } 213 } 214 215 state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000)); 216 } 217 BIONIC_BENCHMARK_WITH_ARG(BM_stdlib_mbrtowc, "0"); 218 219 void BM_stdlib_atoi(benchmark::State& state) { 220 for (auto _ : state) { 221 benchmark::DoNotOptimize(atoi(" -123")); 222 } 223 } 224 BIONIC_BENCHMARK(BM_stdlib_atoi); 225 226 void BM_stdlib_atol(benchmark::State& state) { 227 for (auto _ : state) { 228 benchmark::DoNotOptimize(atol(" -123")); 229 } 230 } 231 BIONIC_BENCHMARK(BM_stdlib_atol); 232 233 void BM_stdlib_strtol(benchmark::State& state) { 234 for (auto _ : state) { 235 benchmark::DoNotOptimize(strtol(" -123", nullptr, 0)); 236 } 237 } 238 BIONIC_BENCHMARK(BM_stdlib_strtol); 239 240 void BM_stdlib_strtoll(benchmark::State& state) { 241 for (auto _ : state) { 242 benchmark::DoNotOptimize(strtoll(" -123", nullptr, 0)); 243 } 244 } 245 BIONIC_BENCHMARK(BM_stdlib_strtoll); 246 247 void BM_stdlib_strtoul(benchmark::State& state) { 248 for (auto _ : state) { 249 benchmark::DoNotOptimize(strtoul(" -123", nullptr, 0)); 250 } 251 } 252 BIONIC_BENCHMARK(BM_stdlib_strtoul); 253 254 void BM_stdlib_strtoull(benchmark::State& state) { 255 for (auto _ : state) { 256 benchmark::DoNotOptimize(strtoull(" -123", nullptr, 0)); 257 } 258 } 259 BIONIC_BENCHMARK(BM_stdlib_strtoull); 260 261