diff --git a/tests/Android.mk b/tests/Android.mk index ed1df6e6b..3217a4d71 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -26,9 +26,11 @@ benchmark_c_flags = \ -O2 \ -Wall -Wextra \ -Werror \ + -fno-builtin \ benchmark_src_files = \ benchmark_main.cpp \ + math_benchmark.cpp \ string_benchmark.cpp \ # Build benchmarks for the device (with bionic's .so). Run with: diff --git a/tests/benchmark.h b/tests/benchmark.h index 70d4c63db..d7af50f31 100644 --- a/tests/benchmark.h +++ b/tests/benchmark.h @@ -32,6 +32,8 @@ class Benchmark { Benchmark* Arg(int x); + const char* Name(); + bool ShouldRun(int argc, char* argv[]); void Run(); diff --git a/tests/benchmark_main.cpp b/tests/benchmark_main.cpp index 4fbeb0742..e15a68831 100644 --- a/tests/benchmark_main.cpp +++ b/tests/benchmark_main.cpp @@ -59,6 +59,10 @@ Benchmark* Benchmark::Arg(int arg) { return this; } +const char* Benchmark::Name() { + return name_; +} + bool Benchmark::ShouldRun(int argc, char* argv[]) { if (argc == 1) { return true; // With no arguments, we run all benchmarks. @@ -94,12 +98,16 @@ void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int } void Benchmark::Run() { - if (args_.empty()) { - fprintf(stderr, "%s: no args!\n", name_); - exit(EXIT_FAILURE); - } - for (size_t i = 0; i < args_.size(); ++i) { - RunWithArg(args_[i]); + if (fn_ != NULL) { + RunWithArg(0); + } else { + if (args_.empty()) { + fprintf(stderr, "%s: no args!\n", name_); + exit(EXIT_FAILURE); + } + for (size_t i = 0; i < args_.size(); ++i) { + RunWithArg(args_[i]); + } } } @@ -180,18 +188,31 @@ void StartBenchmarkTiming() { int main(int argc, char* argv[]) { if (gBenchmarks.empty()) { - fprintf(stderr, "no benchmarks!\n"); + fprintf(stderr, "No benchmarks registered!\n"); exit(EXIT_FAILURE); } - printf("%-20s %10s %10s\n", "", "iterations", "ns/op"); - fflush(stdout); - + bool need_header = true; for (BenchmarkMapIt it = gBenchmarks.begin(); it != gBenchmarks.end(); ++it) { ::testing::Benchmark* b = it->second; if (b->ShouldRun(argc, argv)) { + if (need_header) { + printf("%-20s %10s %10s\n", "", "iterations", "ns/op"); + fflush(stdout); + need_header = false; + } b->Run(); } } + + if (need_header) { + fprintf(stderr, "No matching benchmarks!\n"); + fprintf(stderr, "Available benchmarks:\n"); + for (BenchmarkMapIt it = gBenchmarks.begin(); it != gBenchmarks.end(); ++it) { + fprintf(stderr, " %s\n", it->second->Name()); + } + exit(EXIT_FAILURE); + } + return 0; } diff --git a/tests/math_benchmark.cpp b/tests/math_benchmark.cpp new file mode 100644 index 000000000..a8c1cfae7 --- /dev/null +++ b/tests/math_benchmark.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 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 "benchmark.h" + +#include + +// Avoid optimization. +double d; +double v; + +static void BM_math_sqrt(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 2.0; + for (int i = 0; i < iters; ++i) { + d += sqrt(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_sqrt); + +static void BM_math_log10(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 1234.0; + for (int i = 0; i < iters; ++i) { + d += log10(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_log10); + +static void BM_math_logb(int iters) { + StartBenchmarkTiming(); + + d = 0.0; + v = 1234.0; + for (int i = 0; i < iters; ++i) { + d += logb(v); + } + + StopBenchmarkTiming(); +} +BENCHMARK(BM_math_logb); diff --git a/tests/string_benchmark.cpp b/tests/string_benchmark.cpp index 7ac8e98c9..536e253fd 100644 --- a/tests/string_benchmark.cpp +++ b/tests/string_benchmark.cpp @@ -26,7 +26,7 @@ // TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.) -static void BM_memcmp(int iters, int nbytes) { +static void BM_string_memcmp(int iters, int nbytes) { StopBenchmarkTiming(); char* src = new char[nbytes]; char* dst = new char[nbytes]; memset(src, 'x', nbytes); @@ -34,7 +34,7 @@ static void BM_memcmp(int iters, int nbytes) { StartBenchmarkTiming(); volatile int c __attribute__((unused)) = 0; - for (int i = 0; i < iters; i++) { + for (int i = 0; i < iters; ++i) { c += memcmp(dst, src, nbytes); } @@ -43,15 +43,15 @@ static void BM_memcmp(int iters, int nbytes) { delete[] src; delete[] dst; } -BENCHMARK(BM_memcmp)->AT_COMMON_SIZES; +BENCHMARK(BM_string_memcmp)->AT_COMMON_SIZES; -static void BM_memcpy(int iters, int nbytes) { +static void BM_string_memcpy(int iters, int nbytes) { StopBenchmarkTiming(); char* src = new char[nbytes]; char* dst = new char[nbytes]; memset(src, 'x', nbytes); StartBenchmarkTiming(); - for (int i = 0; i < iters; i++) { + for (int i = 0; i < iters; ++i) { memcpy(dst, src, nbytes); } @@ -60,15 +60,15 @@ static void BM_memcpy(int iters, int nbytes) { delete[] src; delete[] dst; } -BENCHMARK(BM_memcpy)->AT_COMMON_SIZES; +BENCHMARK(BM_string_memcpy)->AT_COMMON_SIZES; -static void BM_memmove(int iters, int nbytes) { +static void BM_string_memmove(int iters, int nbytes) { StopBenchmarkTiming(); char* buf = new char[nbytes + 64]; memset(buf, 'x', nbytes + 64); StartBenchmarkTiming(); - for (int i = 0; i < iters; i++) { + for (int i = 0; i < iters; ++i) { memmove(buf, buf + 1, nbytes); // Worst-case overlap. } @@ -76,14 +76,14 @@ static void BM_memmove(int iters, int nbytes) { SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes)); delete[] buf; } -BENCHMARK(BM_memmove)->AT_COMMON_SIZES; +BENCHMARK(BM_string_memmove)->AT_COMMON_SIZES; -static void BM_memset(int iters, int nbytes) { +static void BM_string_memset(int iters, int nbytes) { StopBenchmarkTiming(); char* dst = new char[nbytes]; StartBenchmarkTiming(); - for (int i = 0; i < iters; i++) { + for (int i = 0; i < iters; ++i) { memset(dst, 0, nbytes); } @@ -91,9 +91,9 @@ static void BM_memset(int iters, int nbytes) { SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes)); delete[] dst; } -BENCHMARK(BM_memset)->AT_COMMON_SIZES; +BENCHMARK(BM_string_memset)->AT_COMMON_SIZES; -static void BM_strlen(int iters, int nbytes) { +static void BM_string_strlen(int iters, int nbytes) { StopBenchmarkTiming(); char* s = new char[nbytes]; memset(s, 'x', nbytes); @@ -101,7 +101,7 @@ static void BM_strlen(int iters, int nbytes) { StartBenchmarkTiming(); volatile int c __attribute__((unused)) = 0; - for (int i = 0; i < iters; i++) { + for (int i = 0; i < iters; ++i) { c += strlen(s); } @@ -109,4 +109,4 @@ static void BM_strlen(int iters, int nbytes) { SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes)); delete[] s; } -BENCHMARK(BM_strlen)->AT_COMMON_SIZES; +BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;