| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright (C) 2014 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 |  | 
| Anders Lewis | a98a5fb | 2017-08-09 16:52:19 -0700 | [diff] [blame] | 17 | #include <err.h> | 
| Elliott Hughes | 3b644e9 | 2017-12-11 14:43:52 -0800 | [diff] [blame] | 18 | #include <inttypes.h> | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 19 | #include <stdio.h> | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 20 | #include <stdio_ext.h> | 
| Elliott Hughes | c217373 | 2015-05-13 13:18:04 -0700 | [diff] [blame] | 21 | #include <stdlib.h> | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 22 |  | 
| Mark Salyzyn | ba1a723 | 2018-11-14 15:19:53 -0800 | [diff] [blame] | 23 | #include <android-base/file.h> | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 24 | #include <benchmark/benchmark.h> | 
| Anders Lewis | a7b0f88 | 2017-07-24 20:01:13 -0700 | [diff] [blame] | 25 | #include "util.h" | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 26 |  | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 27 | static void FillFile(TemporaryFile& tf) { | 
|  | 28 | char line[256]; | 
|  | 29 | memset(line, 'x', sizeof(line)); | 
|  | 30 | line[sizeof(line) - 1] = '\0'; | 
|  | 31 |  | 
| Elliott Hughes | 5cec377 | 2018-01-19 15:45:23 -0800 | [diff] [blame] | 32 | FILE* fp = fopen(tf.path, "we"); | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 33 | for (size_t i = 0; i < 4096; ++i) fputs(line, fp); | 
|  | 34 | fclose(fp); | 
|  | 35 | } | 
|  | 36 |  | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 37 | template <typename Fn> | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 38 | void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) { | 
| Martijn Coenen | be763d8 | 2016-11-14 14:16:08 +0100 | [diff] [blame] | 39 | size_t chunk_size = state.range(0); | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 40 |  | 
| Elliott Hughes | d706fe5 | 2017-08-22 15:26:07 -0700 | [diff] [blame] | 41 | FILE* fp = fopen("/dev/zero", "r+e"); | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 42 | __fsetlocking(fp, FSETLOCKING_BYCALLER); | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 43 | char* buf = new char[chunk_size]; | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 44 |  | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 45 | if (!buffered) { | 
| Yi Kong | 32bc0fc | 2018-08-02 17:31:13 -0700 | [diff] [blame] | 46 | setvbuf(fp, nullptr, _IONBF, 0); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 47 | } | 
|  | 48 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 49 | while (state.KeepRunning()) { | 
| Elliott Hughes | d706fe5 | 2017-08-22 15:26:07 -0700 | [diff] [blame] | 50 | if (f(buf, chunk_size, 1, fp) != 1) { | 
|  | 51 | errx(1, "ERROR: op of %zu bytes failed.", chunk_size); | 
|  | 52 | } | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 53 | } | 
|  | 54 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 55 | state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(chunk_size)); | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 56 | delete[] buf; | 
|  | 57 | fclose(fp); | 
|  | 58 | } | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 59 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 60 | void BM_stdio_fread(benchmark::State& state) { | 
|  | 61 | ReadWriteTest(state, fread, true); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 62 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 63 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fread, "AT_COMMON_SIZES"); | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 64 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 65 | void BM_stdio_fwrite(benchmark::State& state) { | 
|  | 66 | ReadWriteTest(state, fwrite, true); | 
| Elliott Hughes | b28e490 | 2014-03-11 11:19:06 -0700 | [diff] [blame] | 67 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 68 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fwrite, "AT_COMMON_SIZES"); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 69 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 70 | void BM_stdio_fread_unbuffered(benchmark::State& state) { | 
|  | 71 | ReadWriteTest(state, fread, false); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 72 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 73 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fread_unbuffered, "AT_COMMON_SIZES"); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 74 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 75 | void BM_stdio_fwrite_unbuffered(benchmark::State& state) { | 
|  | 76 | ReadWriteTest(state, fwrite, false); | 
| Elliott Hughes | 47dc7c9 | 2014-12-01 13:12:18 -0800 | [diff] [blame] | 77 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 78 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fwrite_unbuffered, "AT_COMMON_SIZES"); | 
| Elliott Hughes | 1cf32f8 | 2015-01-16 17:08:31 -0800 | [diff] [blame] | 79 |  | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 80 | #if !defined(__GLIBC__) | 
|  | 81 | static void FopenFgetlnFclose(benchmark::State& state, bool no_locking) { | 
|  | 82 | TemporaryFile tf; | 
|  | 83 | FillFile(tf); | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 84 | while (state.KeepRunning()) { | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 85 | FILE* fp = fopen(tf.path, "re"); | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 86 | if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 87 | size_t length; | 
|  | 88 | while (fgetln(fp, &length) != nullptr) { | 
|  | 89 | } | 
|  | 90 | fclose(fp); | 
|  | 91 | } | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | static void BM_stdio_fopen_fgetln_fclose_locking(benchmark::State& state) { | 
|  | 95 | FopenFgetlnFclose(state, false); | 
|  | 96 | } | 
|  | 97 | BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_locking); | 
|  | 98 |  | 
|  | 99 | void BM_stdio_fopen_fgetln_fclose_no_locking(benchmark::State& state) { | 
|  | 100 | FopenFgetlnFclose(state, true); | 
|  | 101 | } | 
|  | 102 | BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_no_locking); | 
|  | 103 | #endif | 
|  | 104 |  | 
|  | 105 | static void FopenFgetsFclose(benchmark::State& state, bool no_locking) { | 
|  | 106 | TemporaryFile tf; | 
|  | 107 | FillFile(tf); | 
|  | 108 | char buf[BUFSIZ]; | 
|  | 109 | while (state.KeepRunning()) { | 
|  | 110 | FILE* fp = fopen(tf.path, "re"); | 
|  | 111 | if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); | 
|  | 112 | while (fgets(buf, sizeof(buf), fp) != nullptr) { | 
| Anders Lewis | a98a5fb | 2017-08-09 16:52:19 -0700 | [diff] [blame] | 113 | } | 
| Elliott Hughes | 1cf32f8 | 2015-01-16 17:08:31 -0800 | [diff] [blame] | 114 | fclose(fp); | 
|  | 115 | } | 
|  | 116 | } | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 117 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 118 | static void BM_stdio_fopen_fgets_fclose_locking(benchmark::State& state) { | 
|  | 119 | FopenFgetsFclose(state, false); | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 120 | } | 
| Anders Lewis | a7b0f88 | 2017-07-24 20:01:13 -0700 | [diff] [blame] | 121 | BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_locking); | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 122 |  | 
| Elliott Hughes | 281e06b | 2016-02-17 10:23:52 -0800 | [diff] [blame] | 123 | void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) { | 
|  | 124 | FopenFgetsFclose(state, true); | 
| Elliott Hughes | 8c4994b | 2015-01-20 18:09:05 -0800 | [diff] [blame] | 125 | } | 
| Anders Lewis | a7b0f88 | 2017-07-24 20:01:13 -0700 | [diff] [blame] | 126 | BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking); | 
| Anders Lewis | ac4f4b4 | 2017-08-08 18:29:51 -0700 | [diff] [blame] | 127 |  | 
| Elliott Hughes | 938bece | 2017-08-23 09:52:50 -0700 | [diff] [blame] | 128 | static void FopenGetlineFclose(benchmark::State& state, bool no_locking) { | 
|  | 129 | TemporaryFile tf; | 
|  | 130 | FillFile(tf); | 
|  | 131 | while (state.KeepRunning()) { | 
|  | 132 | FILE* fp = fopen(tf.path, "re"); | 
|  | 133 | if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); | 
|  | 134 | char* line = nullptr; | 
|  | 135 | size_t n = 0; | 
|  | 136 | while (getline(&line, &n, fp) != -1) { | 
|  | 137 | } | 
|  | 138 | free(line); | 
|  | 139 | fclose(fp); | 
|  | 140 | } | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | static void BM_stdio_fopen_getline_fclose_locking(benchmark::State& state) { | 
|  | 144 | FopenGetlineFclose(state, false); | 
|  | 145 | } | 
|  | 146 | BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_locking); | 
|  | 147 |  | 
|  | 148 | void BM_stdio_fopen_getline_fclose_no_locking(benchmark::State& state) { | 
|  | 149 | FopenGetlineFclose(state, true); | 
|  | 150 | } | 
|  | 151 | BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_no_locking); | 
|  | 152 |  | 
| Anders Lewis | ac4f4b4 | 2017-08-08 18:29:51 -0700 | [diff] [blame] | 153 | static void FopenFgetcFclose(benchmark::State& state, bool no_locking) { | 
|  | 154 | size_t nbytes = state.range(0); | 
|  | 155 | while (state.KeepRunning()) { | 
|  | 156 | FILE* fp = fopen("/dev/zero", "re"); | 
|  | 157 | if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); | 
|  | 158 | volatile int c __attribute__((unused)); | 
|  | 159 | for (size_t i = 0; i < nbytes; ++i) { | 
|  | 160 | c = fgetc(fp); | 
|  | 161 | } | 
|  | 162 | fclose(fp); | 
|  | 163 | } | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | static void BM_stdio_fopen_fgetc_fclose_locking(benchmark::State& state) { | 
|  | 167 | FopenFgetcFclose(state, false); | 
|  | 168 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 169 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fopen_fgetc_fclose_locking, "1024"); | 
| Anders Lewis | ac4f4b4 | 2017-08-08 18:29:51 -0700 | [diff] [blame] | 170 |  | 
|  | 171 | void BM_stdio_fopen_fgetc_fclose_no_locking(benchmark::State& state) { | 
|  | 172 | FopenFgetcFclose(state, true); | 
|  | 173 | } | 
| Christopher Ferris | 858e336 | 2017-11-30 08:53:15 -0800 | [diff] [blame] | 174 | BIONIC_BENCHMARK_WITH_ARG(BM_stdio_fopen_fgetc_fclose_no_locking, "1024"); | 
| Elliott Hughes | 9280599 | 2017-10-26 15:41:49 -0700 | [diff] [blame] | 175 |  | 
|  | 176 | static void BM_stdio_printf_literal(benchmark::State& state) { | 
|  | 177 | while (state.KeepRunning()) { | 
|  | 178 | char buf[BUFSIZ]; | 
|  | 179 | snprintf(buf, sizeof(buf), "this is just a literal string with no format specifiers"); | 
|  | 180 | } | 
|  | 181 | } | 
|  | 182 | BIONIC_BENCHMARK(BM_stdio_printf_literal); | 
|  | 183 |  | 
|  | 184 | static void BM_stdio_printf_s(benchmark::State& state) { | 
|  | 185 | while (state.KeepRunning()) { | 
|  | 186 | char buf[BUFSIZ]; | 
|  | 187 | snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %s", | 
|  | 188 | "No such file or directory"); | 
|  | 189 | } | 
|  | 190 | } | 
|  | 191 | BIONIC_BENCHMARK(BM_stdio_printf_s); | 
|  | 192 |  | 
|  | 193 | static void BM_stdio_printf_d(benchmark::State& state) { | 
|  | 194 | while (state.KeepRunning()) { | 
|  | 195 | char buf[BUFSIZ]; | 
|  | 196 | snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %d", 123456); | 
|  | 197 | } | 
|  | 198 | } | 
|  | 199 | BIONIC_BENCHMARK(BM_stdio_printf_d); | 
| Elliott Hughes | 5305a4d | 2017-11-03 14:00:37 -0700 | [diff] [blame] | 200 |  | 
|  | 201 | static void BM_stdio_printf_1$s(benchmark::State& state) { | 
|  | 202 | while (state.KeepRunning()) { | 
|  | 203 | char buf[BUFSIZ]; | 
|  | 204 | snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %1$s", | 
|  | 205 | "No such file or directory"); | 
|  | 206 | } | 
|  | 207 | } | 
|  | 208 | BIONIC_BENCHMARK(BM_stdio_printf_1$s); | 
| Elliott Hughes | 3b644e9 | 2017-12-11 14:43:52 -0800 | [diff] [blame] | 209 |  | 
|  | 210 | static void BM_stdio_scanf_s(benchmark::State& state) { | 
|  | 211 | while (state.KeepRunning()) { | 
|  | 212 | char s[BUFSIZ]; | 
|  | 213 | if (sscanf("file /etc/passwd", "file %s", s) != 1) abort(); | 
|  | 214 | } | 
|  | 215 | } | 
|  | 216 | BIONIC_BENCHMARK(BM_stdio_scanf_s); | 
|  | 217 |  | 
|  | 218 | static void BM_stdio_scanf_d(benchmark::State& state) { | 
|  | 219 | while (state.KeepRunning()) { | 
|  | 220 | int i; | 
|  | 221 | if (sscanf("size 12345", "size %d", &i) != 1) abort(); | 
|  | 222 | } | 
|  | 223 | } | 
|  | 224 | BIONIC_BENCHMARK(BM_stdio_scanf_d); | 
|  | 225 |  | 
| Elliott Hughes | 7063a83 | 2017-12-19 08:55:40 -0800 | [diff] [blame] | 226 | // Parsing maps is a common use of sscanf with a relatively complex format string. | 
| Elliott Hughes | 3b644e9 | 2017-12-11 14:43:52 -0800 | [diff] [blame] | 227 | static void BM_stdio_scanf_maps(benchmark::State& state) { | 
|  | 228 | while (state.KeepRunning()) { | 
|  | 229 | uintptr_t start; | 
|  | 230 | uintptr_t end; | 
|  | 231 | uintptr_t offset; | 
|  | 232 | char permissions[5]; | 
|  | 233 | int name_pos; | 
|  | 234 | if (sscanf("6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so", | 
|  | 235 | "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d %n", | 
|  | 236 | &start, &end, permissions, &offset, &name_pos) != 4) abort(); | 
|  | 237 | } | 
|  | 238 | } | 
|  | 239 | BIONIC_BENCHMARK(BM_stdio_scanf_maps); | 
| Elliott Hughes | 7063a83 | 2017-12-19 08:55:40 -0800 | [diff] [blame] | 240 |  | 
|  | 241 | // Hard-coded equivalent of the maps sscanf from libunwindstack/Maps.cpp for a baseline. | 
|  | 242 | static int ParseMap(const char* line, const char* /*fmt*/, uintptr_t* start, uintptr_t* end, | 
|  | 243 | char* permissions, uintptr_t* offset, int* name_pos) __attribute__((noinline)) { | 
|  | 244 | char* str; | 
|  | 245 | const char* old_str = line; | 
|  | 246 |  | 
|  | 247 | // "%" PRIxPTR "-" | 
|  | 248 | *start = strtoul(old_str, &str, 16); | 
|  | 249 | if (old_str == str || *str++ != '-') return 0; | 
|  | 250 |  | 
|  | 251 | // "%" PRIxPTR " " | 
|  | 252 | old_str = str; | 
|  | 253 | *end = strtoul(old_str, &str, 16); | 
|  | 254 | if (old_str == str || !std::isspace(*str++)) return 0; | 
|  | 255 | while (std::isspace(*str)) str++; | 
|  | 256 |  | 
|  | 257 | // "%4s " | 
|  | 258 | if (*str == '\0') return 0; | 
|  | 259 | permissions[0] = *str; | 
|  | 260 | str++; | 
|  | 261 | permissions[1] = *str; | 
|  | 262 | str++; | 
|  | 263 | permissions[2] = *str; | 
|  | 264 | str++; | 
|  | 265 | permissions[3] = *str; | 
|  | 266 | str++; | 
|  | 267 | permissions[4] = 0; | 
|  | 268 | if (!std::isspace(*str++)) return 0; | 
|  | 269 |  | 
|  | 270 | // "%" PRIxPTR " " | 
|  | 271 | old_str = str; | 
|  | 272 | *offset = strtoul(old_str, &str, 16); | 
|  | 273 | if (old_str == str || !std::isspace(*str)) return 0; | 
|  | 274 |  | 
|  | 275 | // "%*x:%*x " | 
|  | 276 | old_str = str; | 
|  | 277 | (void)strtoul(old_str, &str, 16); | 
|  | 278 | if (old_str == str || *str++ != ':') return 0; | 
|  | 279 | if (std::isspace(*str)) return 0; | 
|  | 280 | old_str = str; | 
|  | 281 | (void)strtoul(str, &str, 16); | 
|  | 282 | if (old_str == str || !std::isspace(*str++)) return 0; | 
|  | 283 |  | 
|  | 284 | // "%*d " | 
|  | 285 | old_str = str; | 
|  | 286 | (void)strtoul(old_str, &str, 10); | 
|  | 287 | if (old_str == str || (!std::isspace(*str) && *str != '\0')) return 0; | 
|  | 288 | while (std::isspace(*str)) str++; | 
|  | 289 |  | 
|  | 290 | // "%n" | 
|  | 291 | *name_pos = (str - line); | 
|  | 292 | return 4; | 
|  | 293 | } | 
|  | 294 |  | 
|  | 295 | static void BM_stdio_scanf_maps_baseline(benchmark::State& state) { | 
|  | 296 | while (state.KeepRunning()) { | 
|  | 297 | uintptr_t start; | 
|  | 298 | uintptr_t end; | 
|  | 299 | uintptr_t offset; | 
|  | 300 | char permissions[5]; | 
|  | 301 | int name_pos; | 
|  | 302 | if (ParseMap("6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so", | 
|  | 303 | "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d %n", | 
|  | 304 | &start, &end, permissions, &offset, &name_pos) != 4) abort(); | 
|  | 305 | } | 
|  | 306 | } | 
|  | 307 | BIONIC_BENCHMARK(BM_stdio_scanf_maps_baseline); |