blob: 76e9ddb13e8b5ecb48b0777822734c4ab722d2f1 [file] [log] [blame]
Elliott Hughesb28e4902014-03-11 11:19:06 -07001/*
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 Lewisa98a5fb2017-08-09 16:52:19 -070017#include <err.h>
Elliott Hughesb28e4902014-03-11 11:19:06 -070018#include <stdio.h>
Elliott Hughes8c4994b2015-01-20 18:09:05 -080019#include <stdio_ext.h>
Elliott Hughesc2173732015-05-13 13:18:04 -070020#include <stdlib.h>
Elliott Hughesb28e4902014-03-11 11:19:06 -070021
Elliott Hughes938bece2017-08-23 09:52:50 -070022#include <android-base/test_utils.h>
Elliott Hughes281e06b2016-02-17 10:23:52 -080023#include <benchmark/benchmark.h>
Anders Lewisa7b0f882017-07-24 20:01:13 -070024#include "util.h"
Elliott Hughesb28e4902014-03-11 11:19:06 -070025
Elliott Hughes938bece2017-08-23 09:52:50 -070026static void FillFile(TemporaryFile& tf) {
27 char line[256];
28 memset(line, 'x', sizeof(line));
29 line[sizeof(line) - 1] = '\0';
30
31 FILE* fp = fopen(tf.path, "w");
32 for (size_t i = 0; i < 4096; ++i) fputs(line, fp);
33 fclose(fp);
34}
35
Elliott Hughes47dc7c92014-12-01 13:12:18 -080036template <typename Fn>
Elliott Hughes281e06b2016-02-17 10:23:52 -080037void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) {
Martijn Coenenbe763d82016-11-14 14:16:08 +010038 size_t chunk_size = state.range(0);
Elliott Hughes281e06b2016-02-17 10:23:52 -080039
Elliott Hughesd706fe52017-08-22 15:26:07 -070040 FILE* fp = fopen("/dev/zero", "r+e");
Elliott Hughes8c4994b2015-01-20 18:09:05 -080041 __fsetlocking(fp, FSETLOCKING_BYCALLER);
Elliott Hughesb28e4902014-03-11 11:19:06 -070042 char* buf = new char[chunk_size];
Elliott Hughesb28e4902014-03-11 11:19:06 -070043
Elliott Hughes47dc7c92014-12-01 13:12:18 -080044 if (!buffered) {
45 setvbuf(fp, 0, _IONBF, 0);
46 }
47
Elliott Hughes281e06b2016-02-17 10:23:52 -080048 while (state.KeepRunning()) {
Elliott Hughesd706fe52017-08-22 15:26:07 -070049 if (f(buf, chunk_size, 1, fp) != 1) {
50 errx(1, "ERROR: op of %zu bytes failed.", chunk_size);
51 }
Elliott Hughesb28e4902014-03-11 11:19:06 -070052 }
53
Elliott Hughes281e06b2016-02-17 10:23:52 -080054 state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(chunk_size));
Elliott Hughesb28e4902014-03-11 11:19:06 -070055 delete[] buf;
56 fclose(fp);
57}
Elliott Hughes47dc7c92014-12-01 13:12:18 -080058
Elliott Hughes281e06b2016-02-17 10:23:52 -080059void BM_stdio_fread(benchmark::State& state) {
60 ReadWriteTest(state, fread, true);
Elliott Hughes47dc7c92014-12-01 13:12:18 -080061}
Anders Lewisa7b0f882017-07-24 20:01:13 -070062BIONIC_BENCHMARK(BM_stdio_fread);
Elliott Hughesb28e4902014-03-11 11:19:06 -070063
Elliott Hughes281e06b2016-02-17 10:23:52 -080064void BM_stdio_fwrite(benchmark::State& state) {
65 ReadWriteTest(state, fwrite, true);
Elliott Hughesb28e4902014-03-11 11:19:06 -070066}
Anders Lewisa7b0f882017-07-24 20:01:13 -070067BIONIC_BENCHMARK(BM_stdio_fwrite);
Elliott Hughes47dc7c92014-12-01 13:12:18 -080068
Elliott Hughes281e06b2016-02-17 10:23:52 -080069void BM_stdio_fread_unbuffered(benchmark::State& state) {
70 ReadWriteTest(state, fread, false);
Elliott Hughes47dc7c92014-12-01 13:12:18 -080071}
Anders Lewisa7b0f882017-07-24 20:01:13 -070072BIONIC_BENCHMARK(BM_stdio_fread_unbuffered);
Elliott Hughes47dc7c92014-12-01 13:12:18 -080073
Elliott Hughes281e06b2016-02-17 10:23:52 -080074void BM_stdio_fwrite_unbuffered(benchmark::State& state) {
75 ReadWriteTest(state, fwrite, false);
Elliott Hughes47dc7c92014-12-01 13:12:18 -080076}
Anders Lewisa7b0f882017-07-24 20:01:13 -070077BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered);
Elliott Hughes1cf32f82015-01-16 17:08:31 -080078
Elliott Hughes938bece2017-08-23 09:52:50 -070079#if !defined(__GLIBC__)
80static void FopenFgetlnFclose(benchmark::State& state, bool no_locking) {
81 TemporaryFile tf;
82 FillFile(tf);
Elliott Hughes281e06b2016-02-17 10:23:52 -080083 while (state.KeepRunning()) {
Elliott Hughes938bece2017-08-23 09:52:50 -070084 FILE* fp = fopen(tf.path, "re");
Elliott Hughes8c4994b2015-01-20 18:09:05 -080085 if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
Elliott Hughes938bece2017-08-23 09:52:50 -070086 size_t length;
87 while (fgetln(fp, &length) != nullptr) {
88 }
89 fclose(fp);
90 }
91}
92
93static void BM_stdio_fopen_fgetln_fclose_locking(benchmark::State& state) {
94 FopenFgetlnFclose(state, false);
95}
96BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_locking);
97
98void BM_stdio_fopen_fgetln_fclose_no_locking(benchmark::State& state) {
99 FopenFgetlnFclose(state, true);
100}
101BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_no_locking);
102#endif
103
104static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
105 TemporaryFile tf;
106 FillFile(tf);
107 char buf[BUFSIZ];
108 while (state.KeepRunning()) {
109 FILE* fp = fopen(tf.path, "re");
110 if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
111 while (fgets(buf, sizeof(buf), fp) != nullptr) {
Anders Lewisa98a5fb2017-08-09 16:52:19 -0700112 }
Elliott Hughes1cf32f82015-01-16 17:08:31 -0800113 fclose(fp);
114 }
115}
Elliott Hughes8c4994b2015-01-20 18:09:05 -0800116
Elliott Hughes281e06b2016-02-17 10:23:52 -0800117static void BM_stdio_fopen_fgets_fclose_locking(benchmark::State& state) {
118 FopenFgetsFclose(state, false);
Elliott Hughes8c4994b2015-01-20 18:09:05 -0800119}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700120BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
Elliott Hughes8c4994b2015-01-20 18:09:05 -0800121
Elliott Hughes281e06b2016-02-17 10:23:52 -0800122void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) {
123 FopenFgetsFclose(state, true);
Elliott Hughes8c4994b2015-01-20 18:09:05 -0800124}
Anders Lewisa7b0f882017-07-24 20:01:13 -0700125BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
Anders Lewisac4f4b42017-08-08 18:29:51 -0700126
Elliott Hughes938bece2017-08-23 09:52:50 -0700127static void FopenGetlineFclose(benchmark::State& state, bool no_locking) {
128 TemporaryFile tf;
129 FillFile(tf);
130 while (state.KeepRunning()) {
131 FILE* fp = fopen(tf.path, "re");
132 if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
133 char* line = nullptr;
134 size_t n = 0;
135 while (getline(&line, &n, fp) != -1) {
136 }
137 free(line);
138 fclose(fp);
139 }
140}
141
142static void BM_stdio_fopen_getline_fclose_locking(benchmark::State& state) {
143 FopenGetlineFclose(state, false);
144}
145BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_locking);
146
147void BM_stdio_fopen_getline_fclose_no_locking(benchmark::State& state) {
148 FopenGetlineFclose(state, true);
149}
150BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_no_locking);
151
Anders Lewisac4f4b42017-08-08 18:29:51 -0700152static void FopenFgetcFclose(benchmark::State& state, bool no_locking) {
153 size_t nbytes = state.range(0);
154 while (state.KeepRunning()) {
155 FILE* fp = fopen("/dev/zero", "re");
156 if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
157 volatile int c __attribute__((unused));
158 for (size_t i = 0; i < nbytes; ++i) {
159 c = fgetc(fp);
160 }
161 fclose(fp);
162 }
163}
164
165static void BM_stdio_fopen_fgetc_fclose_locking(benchmark::State& state) {
166 FopenFgetcFclose(state, false);
167}
168BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_locking);
169
170void BM_stdio_fopen_fgetc_fclose_no_locking(benchmark::State& state) {
171 FopenFgetcFclose(state, true);
172}
173BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_no_locking);
Elliott Hughes92805992017-10-26 15:41:49 -0700174
175static void BM_stdio_printf_literal(benchmark::State& state) {
176 while (state.KeepRunning()) {
177 char buf[BUFSIZ];
178 snprintf(buf, sizeof(buf), "this is just a literal string with no format specifiers");
179 }
180}
181BIONIC_BENCHMARK(BM_stdio_printf_literal);
182
183static void BM_stdio_printf_s(benchmark::State& state) {
184 while (state.KeepRunning()) {
185 char buf[BUFSIZ];
186 snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %s",
187 "No such file or directory");
188 }
189}
190BIONIC_BENCHMARK(BM_stdio_printf_s);
191
192static void BM_stdio_printf_d(benchmark::State& state) {
193 while (state.KeepRunning()) {
194 char buf[BUFSIZ];
195 snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %d", 123456);
196 }
197}
198BIONIC_BENCHMARK(BM_stdio_printf_d);
Elliott Hughes5305a4d2017-11-03 14:00:37 -0700199
200static void BM_stdio_printf_1$s(benchmark::State& state) {
201 while (state.KeepRunning()) {
202 char buf[BUFSIZ];
203 snprintf(buf, sizeof(buf), "this is a more typical error message with detail: %1$s",
204 "No such file or directory");
205 }
206}
207BIONIC_BENCHMARK(BM_stdio_printf_1$s);