diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp index fae6f20af..93f62cfe2 100644 --- a/benchmarks/Android.bp +++ b/benchmarks/Android.bp @@ -35,6 +35,7 @@ cc_defaults { "string_benchmark.cpp", "time_benchmark.cpp", "unistd_benchmark.cpp", + "stdlib_benchmark.cpp", ], shared_libs: ["libtinyxml2"], static_libs: [ diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp index f1ae4ff7e..1f362e331 100644 --- a/benchmarks/bionic_benchmarks.cpp +++ b/benchmarks/bionic_benchmarks.cpp @@ -306,21 +306,21 @@ int RegisterXmlBenchmarks(bench_opts_t cmdline_opts, std::map GetShorthand() { std::map args_shorthand { {"AT_ALIGNED_TWOBUF", args_vector_t{ {8, 0, 0}, - {64, 0, 0}, - {512, 0, 0}, - {1 * KB, 0, 0}, - {8 * KB, 0, 0}, - {16 * KB, 0, 0}, - {32 * KB, 0, 0}, - {64 * KB, 0, 0} }}, + {64, 0, 0}, + {512, 0, 0}, + {1 * KB, 0, 0}, + {8 * KB, 0, 0}, + {16 * KB, 0, 0}, + {32 * KB, 0, 0}, + {64 * KB, 0, 0} }}, {"AT_ALIGNED_ONEBUF", args_vector_t{ {(8), 0}, - {(64), 0}, - {(512), 0}, - {(1*KB), 0}, - {(8*KB), 0}, - {(16*KB), 0}, - {(32*KB), 0}, - {(64*KB), 0}}}, + {(64), 0}, + {(512), 0}, + {(1*KB), 0}, + {(8*KB), 0}, + {(16*KB), 0}, + {(32*KB), 0}, + {(64*KB), 0}}}, {"AT_COMMON_SIZES", args_vector_t{ {8}, {64}, {512}, {1*KB}, {8*KB}, {16*KB}, {32*KB}, {64*KB}}}, diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp index 756a698bb..a1ca60e8a 100644 --- a/benchmarks/stdio_benchmark.cpp +++ b/benchmarks/stdio_benchmark.cpp @@ -63,9 +63,10 @@ void BM_stdio_fwrite_unbuffered(benchmark::State& state) { BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered); static void FopenFgetsFclose(benchmark::State& state, bool no_locking) { - char buf[1024]; + size_t nbytes = state.range(0); + char buf[nbytes]; while (state.KeepRunning()) { - FILE* fp = fopen("/proc/version", "re"); + FILE* fp = fopen("/dev/zero", "re"); if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); if (fgets(buf, sizeof(buf), fp) == nullptr) abort(); fclose(fp); @@ -81,3 +82,27 @@ void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) { FopenFgetsFclose(state, true); } BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking); + +static void FopenFgetcFclose(benchmark::State& state, bool no_locking) { + size_t nbytes = state.range(0); + while (state.KeepRunning()) { + FILE* fp = fopen("/dev/zero", "re"); + if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER); + volatile int c __attribute__((unused)); + for (size_t i = 0; i < nbytes; ++i) { + c = fgetc(fp); + } + fclose(fp); + } +} + +static void BM_stdio_fopen_fgetc_fclose_locking(benchmark::State& state) { + FopenFgetcFclose(state, false); +} +BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_locking); + +void BM_stdio_fopen_fgetc_fclose_no_locking(benchmark::State& state) { + FopenFgetcFclose(state, true); +} +BIONIC_BENCHMARK(BM_stdio_fopen_fgetc_fclose_no_locking); + diff --git a/benchmarks/stdlib_benchmark.cpp b/benchmarks/stdlib_benchmark.cpp new file mode 100644 index 000000000..7a12eb6eb --- /dev/null +++ b/benchmarks/stdlib_benchmark.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include +#include "util.h" + +static void BM_stdlib_malloc_free(benchmark::State& state) { + const size_t nbytes = state.range(0); + + void* c; + while (state.KeepRunning()) { + c = malloc(nbytes); + free(c); + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); +} +BIONIC_BENCHMARK(BM_stdlib_malloc_free); + +static void BM_stdlib_mbstowcs(benchmark::State& state) { + const size_t buf_alignment = state.range(0); + const size_t widebuf_alignment = state.range(1); + + std::vector buf; + std::vector widebuf; + + setlocale(LC_CTYPE, "C.UTF-8") + || setlocale(LC_CTYPE, "en_US.UTF-8") + || setlocale(LC_CTYPE, "en_GB.UTF-8") + || setlocale(LC_CTYPE, "en.UTF-8") + || setlocale(LC_CTYPE, "de_DE-8") + || setlocale(LC_CTYPE, "fr_FR-8"); + if (strcmp(nl_langinfo(CODESET), "UTF-8")) abort(); + + char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000); + wchar_t* widebuf_aligned = GetAlignedPtr(&widebuf, widebuf_alignment, 500000); + size_t i, j, k, l; + l = 0; + for (i=0xc3; i<0xe0; i++) + for (j=0x80; j<0xc0; j++) + buf[l++] = i, buf[l++] = j; + for (i=0xe1; i<0xed; i++) + for (j=0x80; j<0xc0; j++) + for (k=0x80; k<0xc0; k++) + buf[l++] = i, buf[l++] = j, buf[l++] = k; + for (i=0xf1; i<0xf4; i++) + for (j=0x80; j<0xc0; j++) + for (k=0x80; k<0xc0; k++) + buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k; + buf[l++] = 0; + + volatile size_t c __attribute__((unused)) = 0; + while (state.KeepRunning()) { + c = mbstowcs(widebuf_aligned, buf_aligned, 500000); + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000)); +} +BIONIC_BENCHMARK(BM_stdlib_mbstowcs); + +static void BM_stdlib_mbrtowc(benchmark::State& state) { + const size_t buf_alignment = state.range(0); + + std::vector buf; + + setlocale(LC_CTYPE, "C.UTF-8") + || setlocale(LC_CTYPE, "en_US.UTF-8") + || setlocale(LC_CTYPE, "en_GB.UTF-8") + || setlocale(LC_CTYPE, "en.UTF-8") + || setlocale(LC_CTYPE, "de_DE-8") + || setlocale(LC_CTYPE, "fr_FR-8"); + if (strcmp(nl_langinfo(CODESET), "UTF-8")) abort(); + + char* buf_aligned = GetAlignedPtr(&buf, buf_alignment, 500000); + size_t i, j, k, l; + l = 0; + for (i=0xc3; i<0xe0; i++) + for (j=0x80; j<0xc0; j++) + buf[l++] = i, buf[l++] = j; + for (i=0xe1; i<0xed; i++) + for (j=0x80; j<0xc0; j++) + for (k=0x80; k<0xc0; k++) + buf[l++] = i, buf[l++] = j, buf[l++] = k; + for (i=0xf1; i<0xf4; i++) + for (j=0x80; j<0xc0; j++) + for (k=0x80; k<0xc0; k++) + buf[l++] = i, buf[l++] = j, buf[l++] = 0x80, buf[l++] = k; + buf[l++] = 0; + + wchar_t wc = 0; + while (state.KeepRunning()) { + for (j = 0; buf_aligned[j]; j+=mbrtowc(&wc, buf_aligned + j, 4, NULL)) { + } + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(500000)); +} +BIONIC_BENCHMARK(BM_stdlib_mbrtowc); diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp index 729b20dbd..94e7583f6 100644 --- a/benchmarks/string_benchmark.cpp +++ b/benchmarks/string_benchmark.cpp @@ -241,3 +241,49 @@ static void BM_string_strcmp(benchmark::State& state) { state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); } BIONIC_BENCHMARK(BM_string_strcmp); + +static void BM_string_strstr(benchmark::State& state) { + const size_t nbytes = state.range(0); + const size_t haystack_alignment = state.range(1); + const size_t needle_alignment = state.range(2); + + std::vector haystack; + std::vector needle; + char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x'); + char* needle_aligned = GetAlignedPtrFilled(&needle, needle_alignment, + std::min(nbytes, static_cast(5)), 'x'); + + if (nbytes / 4 > 2) { + for (size_t i = 0; nbytes / 4 >= 2 && i < nbytes / 4 - 2; i++) { + haystack_aligned[4 * i + 3] = 'y'; + } + } + haystack_aligned[nbytes - 1] = '\0'; + needle_aligned[needle.size() - 1] = '\0'; + + while (state.KeepRunning()) { + if (strstr(haystack_aligned, needle_aligned) == nullptr) { + abort(); + } + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); +} +BIONIC_BENCHMARK(BM_string_strstr); + +static void BM_string_strchr(benchmark::State& state) { + const size_t nbytes = state.range(0); + const size_t haystack_alignment = state.range(1); + + std::vector haystack; + char* haystack_aligned = GetAlignedPtrFilled(&haystack, haystack_alignment, nbytes, 'x'); + + while (state.KeepRunning()) { + if (strchr(haystack_aligned, 'y') != nullptr) { + abort(); + } + } + + state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes)); +} +BIONIC_BENCHMARK(BM_string_strchr); diff --git a/benchmarks/suites/full.xml b/benchmarks/suites/full.xml index 707a3d626..8c9aef6e8 100644 --- a/benchmarks/suites/full.xml +++ b/benchmarks/suites/full.xml @@ -180,9 +180,19 @@ BM_stdio_fopen_fgets_fclose_locking + 1024 BM_stdio_fopen_fgets_fclose_no_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_no_locking + 1024 BM_string_memcmp @@ -232,6 +242,14 @@ BM_string_strcmp AT_ALIGNED_TWOBUF + + BM_string_strstr + AT_ALIGNED_TWOBUF + + + BM_string_strchr + AT_ALIGNED_ONEBUF + BM_time_clock_gettime @@ -265,3 +283,15 @@ BM_unistd_gettid_syscall + + BM_stdlib_malloc_free + AT_ALIGNED_ONEBUF + + + BM_stdlib_mbstowcs + 0 0 + + + BM_stdlib_mbrtowc + 0 + diff --git a/benchmarks/suites/host.xml b/benchmarks/suites/host.xml index c4d0d3a3e..05769e910 100644 --- a/benchmarks/suites/host.xml +++ b/benchmarks/suites/host.xml @@ -160,9 +160,19 @@ BM_stdio_fopen_fgets_fclose_locking + 1024 BM_stdio_fopen_fgets_fclose_no_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_no_locking + 1024 BM_string_memcmp @@ -212,6 +222,14 @@ BM_string_strcmp AT_ALIGNED_TWOBUF + + BM_string_strstr + AT_ALIGNED_TWOBUF + + + BM_string_strchr + AT_ALIGNED_ONEBUF + BM_time_clock_gettime @@ -242,3 +260,15 @@ BM_unistd_gettid_syscall + + BM_stdlib_malloc_free + AT_ALIGNED_ONEBUF + + + BM_stdlib_mbstowcs + 0 0 + + + BM_stdlib_mbrtowc + 0 + diff --git a/benchmarks/suites/test_full.xml b/benchmarks/suites/test_full.xml index f9d97ee4f..adc3f28a3 100644 --- a/benchmarks/suites/test_full.xml +++ b/benchmarks/suites/test_full.xml @@ -180,9 +180,19 @@ BM_stdio_fopen_fgets_fclose_locking + 1024 BM_stdio_fopen_fgets_fclose_no_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_locking + 1024 + + + BM_stdio_fopen_fgetc_fclose_no_locking + 1024 BM_string_memcmp @@ -232,6 +242,14 @@ BM_string_strcmp AT_ALIGNED_TWOBUF + + BM_string_strstr + AT_ALIGNED_TWOBUF + + + BM_string_strchr + AT_ALIGNED_ONEBUF + BM_time_clock_gettime @@ -259,3 +277,15 @@ BM_unistd_gettid_syscall + + BM_stdlib_malloc_free + AT_ALIGNED_ONEBUF + + + BM_stdlib_mbstowcs + 0 0 + + + BM_stdlib_mbrtowc + 0 + diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp index a9e303106..9283e6baf 100644 --- a/benchmarks/tests/interface_test.cpp +++ b/benchmarks/tests/interface_test.cpp @@ -242,8 +242,10 @@ TEST_F(SystemTests, full_suite) { "BM_stdio_fwrite_unbuffered/16384/iterations:1\n" "BM_stdio_fwrite_unbuffered/32768/iterations:1\n" "BM_stdio_fwrite_unbuffered/65536/iterations:1\n" - "BM_stdio_fopen_fgets_fclose_locking/iterations:1\n" - "BM_stdio_fopen_fgets_fclose_no_locking/iterations:1\n" + "BM_stdio_fopen_fgets_fclose_locking/1024/iterations:1\n" + "BM_stdio_fopen_fgets_fclose_no_locking/1024/iterations:1\n" + "BM_stdio_fopen_fgetc_fclose_locking/1024/iterations:1\n" + "BM_stdio_fopen_fgetc_fclose_no_locking/1024/iterations:1\n" "BM_string_memcmp/8/0/0/iterations:1\n" "BM_string_memcmp/64/0/0/iterations:1\n" "BM_string_memcmp/512/0/0/iterations:1\n" @@ -340,6 +342,22 @@ TEST_F(SystemTests, full_suite) { "BM_string_strcmp/16384/0/0/iterations:1\n" "BM_string_strcmp/32768/0/0/iterations:1\n" "BM_string_strcmp/65536/0/0/iterations:1\n" + "BM_string_strstr/8/0/0/iterations:1\n" + "BM_string_strstr/64/0/0/iterations:1\n" + "BM_string_strstr/512/0/0/iterations:1\n" + "BM_string_strstr/1024/0/0/iterations:1\n" + "BM_string_strstr/8192/0/0/iterations:1\n" + "BM_string_strstr/16384/0/0/iterations:1\n" + "BM_string_strstr/32768/0/0/iterations:1\n" + "BM_string_strstr/65536/0/0/iterations:1\n" + "BM_string_strchr/8/0/iterations:1\n" + "BM_string_strchr/64/0/iterations:1\n" + "BM_string_strchr/512/0/iterations:1\n" + "BM_string_strchr/1024/0/iterations:1\n" + "BM_string_strchr/8192/0/iterations:1\n" + "BM_string_strchr/16384/0/iterations:1\n" + "BM_string_strchr/32768/0/iterations:1\n" + "BM_string_strchr/65536/0/iterations:1\n" "BM_time_clock_gettime/iterations:1\n" "BM_time_clock_gettime_syscall/iterations:1\n" "BM_time_gettimeofday/iterations:1\n" @@ -348,7 +366,17 @@ TEST_F(SystemTests, full_suite) { "BM_unistd_getpid/iterations:1\n" "BM_unistd_getpid_syscall/iterations:1\n" "BM_unistd_gettid/iterations:1\n" - "BM_unistd_gettid_syscall/iterations:1\n"; + "BM_unistd_gettid_syscall/iterations:1\n" + "BM_stdlib_malloc_free/8/0/iterations:1\n" + "BM_stdlib_malloc_free/64/0/iterations:1\n" + "BM_stdlib_malloc_free/512/0/iterations:1\n" + "BM_stdlib_malloc_free/1024/0/iterations:1\n" + "BM_stdlib_malloc_free/8192/0/iterations:1\n" + "BM_stdlib_malloc_free/16384/0/iterations:1\n" + "BM_stdlib_malloc_free/32768/0/iterations:1\n" + "BM_stdlib_malloc_free/65536/0/iterations:1\n" + "BM_stdlib_mbstowcs/0/0/iterations:1\n" + "BM_stdlib_mbrtowc/0/iterations:1\n"; Verify(expected, 0, std::vector{"--bionic_xml=suites/test_full.xml", "--bionic_iterations=1"}); } diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp index 9afca6f7e..0c7254c14 100644 --- a/benchmarks/util.cpp +++ b/benchmarks/util.cpp @@ -16,9 +16,11 @@ #include "util.h" +#include #include #include #include +#include #include @@ -49,6 +51,12 @@ char* GetAlignedPtr(std::vector* buf, size_t alignment, size_t nbytes) { return GetAlignedMemory(buf->data(), alignment, 0); } +wchar_t* GetAlignedPtr(std::vector* buf, size_t alignment, size_t nchars) { + buf->resize(nchars + ceil((3 * alignment) / sizeof(wchar_t))); + return reinterpret_cast(GetAlignedMemory(reinterpret_cast(buf->data()), + alignment, 0)); +} + char* GetAlignedPtrFilled(std::vector* buf, size_t alignment, size_t nbytes, char fill_byte) { char* buf_aligned = GetAlignedPtr(buf, alignment, nbytes); memset(buf_aligned, fill_byte, nbytes); diff --git a/benchmarks/util.h b/benchmarks/util.h index c8c39e315..cf6f50eb8 100644 --- a/benchmarks/util.h +++ b/benchmarks/util.h @@ -52,6 +52,8 @@ char* GetAlignedMemory(char* orig_ptr, size_t alignment, size_t or_mask); char* GetAlignedPtr(std::vector* buf, size_t alignment, size_t nbytes); +wchar_t* GetAlignedPtr(std::vector* buf, size_t alignment, size_t nbytes); + char* GetAlignedPtrFilled(std::vector* buf, size_t alignment, size_t nbytes, char fill_byte); bool LockToCPU(long cpu_to_lock);