diff options
author | Elliott Hughes <enh@google.com> | 2017-08-23 09:52:50 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2017-08-23 14:03:43 -0700 |
commit | 938bece9e0c5d7d67d137dbfbba1e2d244c95b35 (patch) | |
tree | cb655541a4b96f3af5c854a80793af05833235b5 /benchmarks/stdio_benchmark.cpp | |
parent | 57e07a150e536f79d78f8203b0c807087b5c854b (diff) |
Benchmark fgetln(3) and getline(3) as well as fgets(3).
On Pixel 2016, there's about 1us overhead for getline versus
fgets. fgetln(3) is worse still because of the intermediate buffering
(though it might actually be better if you were only reading one line
whose length was less than BUFSIZ).
Also use somewhat realistic input for these benchmarks: /dev/zero makes
no sense at all.
Bug: N/A
Test: ran benchmarks
Change-Id: I4a319825a37ac3849014c4c6b31523c1e200c641
Diffstat (limited to 'benchmarks/stdio_benchmark.cpp')
-rw-r--r-- | benchmarks/stdio_benchmark.cpp | 71 |
1 files changed, 66 insertions, 5 deletions
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp index 3f5e0f138..0e7f668f3 100644 --- a/benchmarks/stdio_benchmark.cpp +++ b/benchmarks/stdio_benchmark.cpp @@ -19,9 +19,20 @@ #include <stdio_ext.h> #include <stdlib.h> +#include <android-base/test_utils.h> #include <benchmark/benchmark.h> #include "util.h" +static void FillFile(TemporaryFile& tf) { + char line[256]; + memset(line, 'x', sizeof(line)); + line[sizeof(line) - 1] = '\0'; + + FILE* fp = fopen(tf.path, "w"); + for (size_t i = 0; i < 4096; ++i) fputs(line, fp); + fclose(fp); +} + template <typename Fn> void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) { size_t chunk_size = state.range(0); @@ -65,14 +76,39 @@ void BM_stdio_fwrite_unbuffered(benchmark::State& state) { } BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered); +#if !defined(__GLIBC__) +static void FopenFgetlnFclose(benchmark::State& state, bool no_locking) { + TemporaryFile tf; + FillFile(tf); + while (state.KeepRunning()) { + FILE* fp = fopen(tf.path, "re"); + if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); + size_t length; + while (fgetln(fp, &length) != nullptr) { + } + fclose(fp); + } +} + +static void BM_stdio_fopen_fgetln_fclose_locking(benchmark::State& state) { + FopenFgetlnFclose(state, false); +} +BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_locking); + +void BM_stdio_fopen_fgetln_fclose_no_locking(benchmark::State& state) { + FopenFgetlnFclose(state, true); +} +BIONIC_BENCHMARK(BM_stdio_fopen_fgetln_fclose_no_locking); +#endif + static void FopenFgetsFclose(benchmark::State& state, bool no_locking) { - size_t nbytes = state.range(0); - char buf[nbytes]; + TemporaryFile tf; + FillFile(tf); + char buf[BUFSIZ]; while (state.KeepRunning()) { - FILE* fp = fopen("/dev/zero", "re"); + FILE* fp = fopen(tf.path, "re"); if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); - if (fgets(buf, sizeof(buf), fp) == nullptr) { - errx(1, "ERROR: fgets of %zu bytes failed.", nbytes); + while (fgets(buf, sizeof(buf), fp) != nullptr) { } fclose(fp); } @@ -88,6 +124,31 @@ void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) { } BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking); +static void FopenGetlineFclose(benchmark::State& state, bool no_locking) { + TemporaryFile tf; + FillFile(tf); + while (state.KeepRunning()) { + FILE* fp = fopen(tf.path, "re"); + if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); + char* line = nullptr; + size_t n = 0; + while (getline(&line, &n, fp) != -1) { + } + free(line); + fclose(fp); + } +} + +static void BM_stdio_fopen_getline_fclose_locking(benchmark::State& state) { + FopenGetlineFclose(state, false); +} +BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_locking); + +void BM_stdio_fopen_getline_fclose_no_locking(benchmark::State& state) { + FopenGetlineFclose(state, true); +} +BIONIC_BENCHMARK(BM_stdio_fopen_getline_fclose_no_locking); + static void FopenFgetcFclose(benchmark::State& state, bool no_locking) { size_t nbytes = state.range(0); while (state.KeepRunning()) { |