Merge "Improve benchmarking tool, add a few math benchmarks."

This commit is contained in:
Elliott Hughes 2013-02-07 00:04:24 +00:00 committed by Gerrit Code Review
commit c9ab32e4e9
5 changed files with 112 additions and 25 deletions

View file

@ -26,9 +26,11 @@ benchmark_c_flags = \
-O2 \ -O2 \
-Wall -Wextra \ -Wall -Wextra \
-Werror \ -Werror \
-fno-builtin \
benchmark_src_files = \ benchmark_src_files = \
benchmark_main.cpp \ benchmark_main.cpp \
math_benchmark.cpp \
string_benchmark.cpp \ string_benchmark.cpp \
# Build benchmarks for the device (with bionic's .so). Run with: # Build benchmarks for the device (with bionic's .so). Run with:

View file

@ -32,6 +32,8 @@ class Benchmark {
Benchmark* Arg(int x); Benchmark* Arg(int x);
const char* Name();
bool ShouldRun(int argc, char* argv[]); bool ShouldRun(int argc, char* argv[]);
void Run(); void Run();

View file

@ -59,6 +59,10 @@ Benchmark* Benchmark::Arg(int arg) {
return this; return this;
} }
const char* Benchmark::Name() {
return name_;
}
bool Benchmark::ShouldRun(int argc, char* argv[]) { bool Benchmark::ShouldRun(int argc, char* argv[]) {
if (argc == 1) { if (argc == 1) {
return true; // With no arguments, we run all benchmarks. return true; // With no arguments, we run all benchmarks.
@ -94,6 +98,9 @@ void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int
} }
void Benchmark::Run() { void Benchmark::Run() {
if (fn_ != NULL) {
RunWithArg(0);
} else {
if (args_.empty()) { if (args_.empty()) {
fprintf(stderr, "%s: no args!\n", name_); fprintf(stderr, "%s: no args!\n", name_);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -102,6 +109,7 @@ void Benchmark::Run() {
RunWithArg(args_[i]); RunWithArg(args_[i]);
} }
} }
}
void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) { void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
gBytesProcessed = 0; gBytesProcessed = 0;
@ -180,18 +188,31 @@ void StartBenchmarkTiming() {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (gBenchmarks.empty()) { if (gBenchmarks.empty()) {
fprintf(stderr, "no benchmarks!\n"); fprintf(stderr, "No benchmarks registered!\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("%-20s %10s %10s\n", "", "iterations", "ns/op"); bool need_header = true;
fflush(stdout);
for (BenchmarkMapIt it = gBenchmarks.begin(); it != gBenchmarks.end(); ++it) { for (BenchmarkMapIt it = gBenchmarks.begin(); it != gBenchmarks.end(); ++it) {
::testing::Benchmark* b = it->second; ::testing::Benchmark* b = it->second;
if (b->ShouldRun(argc, argv)) { if (b->ShouldRun(argc, argv)) {
if (need_header) {
printf("%-20s %10s %10s\n", "", "iterations", "ns/op");
fflush(stdout);
need_header = false;
}
b->Run(); 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; return 0;
} }

62
tests/math_benchmark.cpp Normal file
View file

@ -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 <math.h>
// 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);

View file

@ -26,7 +26,7 @@
// TODO: test unaligned operation too? (currently everything will be 8-byte aligned by malloc.) // 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(); StopBenchmarkTiming();
char* src = new char[nbytes]; char* dst = new char[nbytes]; char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes); memset(src, 'x', nbytes);
@ -34,7 +34,7 @@ static void BM_memcmp(int iters, int nbytes) {
StartBenchmarkTiming(); StartBenchmarkTiming();
volatile int c __attribute__((unused)) = 0; 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); c += memcmp(dst, src, nbytes);
} }
@ -43,15 +43,15 @@ static void BM_memcmp(int iters, int nbytes) {
delete[] src; delete[] src;
delete[] dst; 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(); StopBenchmarkTiming();
char* src = new char[nbytes]; char* dst = new char[nbytes]; char* src = new char[nbytes]; char* dst = new char[nbytes];
memset(src, 'x', nbytes); memset(src, 'x', nbytes);
StartBenchmarkTiming(); StartBenchmarkTiming();
for (int i = 0; i < iters; i++) { for (int i = 0; i < iters; ++i) {
memcpy(dst, src, nbytes); memcpy(dst, src, nbytes);
} }
@ -60,15 +60,15 @@ static void BM_memcpy(int iters, int nbytes) {
delete[] src; delete[] src;
delete[] dst; 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(); StopBenchmarkTiming();
char* buf = new char[nbytes + 64]; char* buf = new char[nbytes + 64];
memset(buf, 'x', nbytes + 64); memset(buf, 'x', nbytes + 64);
StartBenchmarkTiming(); StartBenchmarkTiming();
for (int i = 0; i < iters; i++) { for (int i = 0; i < iters; ++i) {
memmove(buf, buf + 1, nbytes); // Worst-case overlap. 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)); SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] buf; 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(); StopBenchmarkTiming();
char* dst = new char[nbytes]; char* dst = new char[nbytes];
StartBenchmarkTiming(); StartBenchmarkTiming();
for (int i = 0; i < iters; i++) { for (int i = 0; i < iters; ++i) {
memset(dst, 0, nbytes); memset(dst, 0, nbytes);
} }
@ -91,9 +91,9 @@ static void BM_memset(int iters, int nbytes) {
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes)); SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] dst; 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(); StopBenchmarkTiming();
char* s = new char[nbytes]; char* s = new char[nbytes];
memset(s, 'x', nbytes); memset(s, 'x', nbytes);
@ -101,7 +101,7 @@ static void BM_strlen(int iters, int nbytes) {
StartBenchmarkTiming(); StartBenchmarkTiming();
volatile int c __attribute__((unused)) = 0; volatile int c __attribute__((unused)) = 0;
for (int i = 0; i < iters; i++) { for (int i = 0; i < iters; ++i) {
c += strlen(s); c += strlen(s);
} }
@ -109,4 +109,4 @@ static void BM_strlen(int iters, int nbytes) {
SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes)); SetBenchmarkBytesProcessed(int64_t(iters) * int64_t(nbytes));
delete[] s; delete[] s;
} }
BENCHMARK(BM_strlen)->AT_COMMON_SIZES; BENCHMARK(BM_string_strlen)->AT_COMMON_SIZES;