aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Ferris <cferris@google.com>2017-08-08 01:20:46 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-08-08 01:20:46 +0000
commitebbbe292bd2657b98007f3b6d0405686c1c646b8 (patch)
tree7725096a817a36ded544e815c507be40c88a9d23
parent8aa387fbee2e741e00d34290945b67ab42bb10ec (diff)
parenta7b0f8899790198cd9e72950f481679fe31e1a92 (diff)
downloadbionic-ebbbe292bd2657b98007f3b6d0405686c1c646b8.tar.gz
Merge "Implement interface for bionic benchmarks."
-rw-r--r--benchmarks/Android.bp10
-rw-r--r--benchmarks/atomic_benchmark.cpp24
-rw-r--r--benchmarks/bionic_benchmarks.cpp385
-rw-r--r--benchmarks/math_benchmark.cpp40
-rw-r--r--benchmarks/property_benchmark.cpp14
-rw-r--r--benchmarks/pthread_benchmark.cpp29
-rw-r--r--benchmarks/semaphore_benchmark.cpp11
-rw-r--r--benchmarks/stdio_benchmark.cpp19
-rw-r--r--benchmarks/string_benchmark.cpp46
-rw-r--r--benchmarks/suites/full.xml267
-rw-r--r--benchmarks/suites/host.xml244
-rw-r--r--benchmarks/suites/test_alignment.xml50
-rw-r--r--benchmarks/suites/test_from_each.xml30
-rw-r--r--benchmarks/suites/test_full.xml261
-rw-r--r--benchmarks/suites/test_medium.xml16
-rw-r--r--benchmarks/suites/test_small.xml11
-rw-r--r--benchmarks/tests/interface_test.cpp526
-rw-r--r--benchmarks/time_benchmark.cpp15
-rw-r--r--benchmarks/unistd_benchmark.cpp11
-rw-r--r--benchmarks/util.cpp12
-rw-r--r--benchmarks/util.h36
21 files changed, 1930 insertions, 127 deletions
diff --git a/benchmarks/Android.bp b/benchmarks/Android.bp
index 0edba659a..fae6f20af 100644
--- a/benchmarks/Android.bp
+++ b/benchmarks/Android.bp
@@ -25,6 +25,7 @@ cc_defaults {
"-Wunused",
],
srcs: [
+ "bionic_benchmarks.cpp",
"atomic_benchmark.cpp",
"math_benchmark.cpp",
"property_benchmark.cpp",
@@ -35,7 +36,11 @@ cc_defaults {
"time_benchmark.cpp",
"unistd_benchmark.cpp",
],
- static_libs: ["libBionicBenchmarksUtils"],
+ shared_libs: ["libtinyxml2"],
+ static_libs: [
+ "libbase",
+ "libBionicBenchmarksUtils",
+ ],
}
cc_defaults {
@@ -54,6 +59,7 @@ cc_defaults {
cc_benchmark {
name: "bionic-benchmarks",
defaults: ["bionic-benchmarks-defaults"],
+ data: ["suites/*"],
}
// We don't build a static benchmark executable because it's not usually
@@ -87,6 +93,8 @@ cc_test {
defaults: ["bionic-benchmarks-extras-defaults"],
srcs: [
"tests/benchmark_test.cpp",
+ "tests/interface_test.cpp",
],
static_libs: ["libBionicBenchmarksUtils"],
+ data: ["suites/test_*.xml"],
}
diff --git a/benchmarks/atomic_benchmark.cpp b/benchmarks/atomic_benchmark.cpp
index 66a0120a1..a584dce2d 100644
--- a/benchmarks/atomic_benchmark.cpp
+++ b/benchmarks/atomic_benchmark.cpp
@@ -20,10 +20,12 @@
// Expected mappings from C++ atomics to hardware primitives can be found at
// http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html .
-#include <benchmark/benchmark.h>
#include <atomic>
#include <mutex>
+#include <benchmark/benchmark.h>
+#include "util.h"
+
// We time atomic operations separated by a volatile (not atomic!) increment. This ensures
// that the compiler emits memory instructions (e.g. load or store) prior to any fence or the
// like. That in turn ensures that the CPU has outstanding memory operations when the fence
@@ -48,7 +50,7 @@ void BM_empty(benchmark::State& state) {
++counter;
}
}
-BENCHMARK(BM_empty);
+BIONIC_BENCHMARK(BM_empty);
static void BM_load_relaxed(benchmark::State& state) {
unsigned result = 0;
@@ -58,7 +60,7 @@ static void BM_load_relaxed(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_load_relaxed);
+BIONIC_BENCHMARK(BM_load_relaxed);
static void BM_load_acquire(benchmark::State& state) {
unsigned result = 0;
@@ -68,7 +70,7 @@ static void BM_load_acquire(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_load_acquire);
+BIONIC_BENCHMARK(BM_load_acquire);
static void BM_store_release(benchmark::State& state) {
int i = counter;
@@ -77,7 +79,7 @@ static void BM_store_release(benchmark::State& state) {
++counter;
}
}
-BENCHMARK(BM_store_release);
+BIONIC_BENCHMARK(BM_store_release);
static void BM_store_seq_cst(benchmark::State& state) {
int i = counter;
@@ -86,7 +88,7 @@ static void BM_store_seq_cst(benchmark::State& state) {
++counter;
}
}
-BENCHMARK(BM_store_seq_cst);
+BIONIC_BENCHMARK(BM_store_seq_cst);
static void BM_fetch_add_relaxed(benchmark::State& state) {
unsigned result = 0;
@@ -96,7 +98,7 @@ static void BM_fetch_add_relaxed(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_fetch_add_relaxed);
+BIONIC_BENCHMARK(BM_fetch_add_relaxed);
static void BM_fetch_add_seq_cst(benchmark::State& state) {
unsigned result = 0;
@@ -106,7 +108,7 @@ static void BM_fetch_add_seq_cst(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_fetch_add_seq_cst);
+BIONIC_BENCHMARK(BM_fetch_add_seq_cst);
// The fence benchmarks include a relaxed load to make it much harder to optimize away
// the fence.
@@ -120,7 +122,7 @@ static void BM_acquire_fence(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_acquire_fence);
+BIONIC_BENCHMARK(BM_acquire_fence);
static void BM_seq_cst_fence(benchmark::State& state) {
unsigned result = 0;
@@ -131,7 +133,7 @@ static void BM_seq_cst_fence(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_seq_cst_fence);
+BIONIC_BENCHMARK(BM_seq_cst_fence);
// For comparison, also throw in a critical section version:
@@ -145,4 +147,4 @@ static void BM_fetch_add_cs(benchmark::State& state) {
}
sink = result;
}
-BENCHMARK(BM_fetch_add_cs);
+BIONIC_BENCHMARK(BM_fetch_add_cs);
diff --git a/benchmarks/bionic_benchmarks.cpp b/benchmarks/bionic_benchmarks.cpp
new file mode 100644
index 000000000..7f91b7444
--- /dev/null
+++ b/benchmarks/bionic_benchmarks.cpp
@@ -0,0 +1,385 @@
+/*
+ * 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 <getopt.h>
+#include <math.h>
+#include <sys/resource.h>
+
+#include <map>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "android-base/strings.h"
+#include <benchmark/benchmark.h>
+#include <tinyxml2.h>
+#include "util.h"
+
+std::map<std::string, benchmark_func_t> g_str_to_func;
+
+std::mutex g_map_lock;
+
+static struct option g_long_options[] =
+{
+ {"bionic_cpu", required_argument, 0, 'c'},
+ {"bionic_xml", required_argument, 0, 'x'},
+ {"bionic_iterations", required_argument, 0, 'i'},
+ {"bionic_extra", required_argument, 0, 'a'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0},
+};
+
+typedef std::vector<std::vector<int>> args_vector_t;
+
+void Usage() {
+ printf("Usage:\n");
+ printf("bionic_benchmarks [--bionic_cpu=<cpu_to_isolate>] [--bionic_xml=<path_to_xml>]\n");
+ printf(" [--bionic_iterations=<num_iter>]\n");
+ printf(" [--bionic_extra=\"<fn_name> <arg1> <arg 2> ... \n]");
+ printf(" [<Google benchmark flags>]\n");
+ printf("Google benchmark flags:\n");
+
+ int fake_argc = 2;
+ char argv0[] = "bionic_benchmarks";
+ char argv1[] = "--help";
+ char* fake_argv[3] {argv0, argv1, NULL};
+ benchmark::Initialize(&fake_argc, fake_argv);
+ abort();
+}
+
+// This function removes any bionic benchmarks command line arguments by checking them
+// against g_long_options. It fills new_argv with the filtered args.
+void SanitizeOpts(int argc, char** argv, std::vector<char*>* new_argv) {
+ // TO THOSE ADDING OPTIONS: This currently doesn't support optional arguments.
+ (*new_argv)[0] = argv[0];
+ for (int i = 1; i < argc; ++i) {
+ char* optarg = argv[i];
+ size_t opt_idx = 0;
+
+ // Iterate through g_long_options until either we hit the end or we have a match.
+ for (opt_idx = 0; g_long_options[opt_idx].name &&
+ strncmp(g_long_options[opt_idx].name, optarg + 2,
+ strlen(g_long_options[opt_idx].name)); ++opt_idx) {
+ }
+
+ if (!g_long_options[opt_idx].name) {
+ new_argv->push_back(optarg);
+ } else {
+ if (g_long_options[opt_idx].has_arg == required_argument) {
+ // If the arg was passed in with an =, it spans one char *.
+ // Otherwise, we skip a spot for the argument.
+ if (!strchr(optarg, '=')) {
+ i++;
+ }
+ }
+ }
+ }
+ new_argv->push_back(0);
+}
+
+bench_opts_t ParseOpts(int argc, char** argv) {
+ bench_opts_t opts;
+ int opt;
+ int option_index = 0;
+
+ opts.cpu_to_lock = LONG_MAX;
+ opts.num_iterations = 0;
+
+ // To make this parser handle the benchmark options silently:
+ extern int opterr;
+ opterr = 0;
+
+ while ((opt = getopt_long(argc, argv, "c:x:i:a:h", g_long_options, &option_index)) != -1) {
+ if (opt == -1) {
+ break;
+ }
+ switch (opt) {
+ case 'c':
+ if (*optarg) {
+ char* check_null;
+ opts.cpu_to_lock = strtol(optarg, &check_null, 10);
+ if (*check_null) {
+ printf("ERROR: Args %s is not a valid integer.\n", optarg);
+ abort();
+ }
+ } else {
+ printf("ERROR: no argument specified for bionic_cpu\n");
+ Usage();
+ }
+ break;
+ case 'x':
+ if (*optarg) {
+ opts.xmlpath = optarg;
+ } else {
+ printf("ERROR: no argument specified for bionic_xml\n");
+ Usage();
+ }
+ break;
+ case 'a':
+ if (*optarg) {
+ opts.extra_benchmarks.push_back(optarg);
+ } else {
+ printf("ERROR: no argument specified for bionic_extra\n");
+ Usage();
+ }
+ break;
+ case 'i':
+ if (*optarg){
+ char* check_null;
+ opts.num_iterations = strtol(optarg, &check_null, 10);
+ if (*check_null != '\0') {
+ printf("ERROR: Args %s is not a valid integer.\n", optarg);
+ abort();
+ }
+ } else {
+ printf("ERROR: no argument specified for bionic_iterations\n");
+ Usage();
+ }
+ break;
+ case 'h':
+ Usage();
+ break;
+ case '?':
+ break;
+ default:
+ abort();
+ }
+ }
+ return opts;
+}
+
+// This is a wrapper for every function call for per-benchmark cpu pinning.
+void LockAndRun(benchmark::State& state, benchmark_func_t func_to_bench, long cpu_to_lock) {
+ if (cpu_to_lock != LONG_MAX) LockToCPU(cpu_to_lock);
+ // To avoid having to link against Google benchmarks in libutil,
+ // benchmarks are kept without parameter information, necessitating this cast.
+ reinterpret_cast<void(*) (benchmark::State&)>(func_to_bench)(state);
+}
+
+args_vector_t* ResolveArgs(args_vector_t* to_populate, std::string args,
+ std::map<std::string, args_vector_t>& args_shorthand) {
+ // args is either a space-separated list of ints or a macro name.
+ // To ease formatting in XML files, args is left and right trimmed.
+ if (args_shorthand.count(args)) {
+ return &args_shorthand[args];
+ }
+ to_populate->push_back(std::vector<int>());
+ std::stringstream sstream(args);
+ std::string argstr;
+ while (sstream >> argstr) {
+ char* check_null;
+ int converted = static_cast<int>(strtol(argstr.c_str(), &check_null, 10));
+ if (*check_null) {
+ printf("ERROR: Args str %s contains an invalid macro or int.\n", args.c_str());
+ abort();
+ }
+ (*to_populate)[0].push_back(converted);
+ }
+ return to_populate;
+}
+
+void RegisterGoogleBenchmarks(bench_opts_t primary_opts, bench_opts_t secondary_opts,
+ std::string fn_name, args_vector_t* run_args) {
+ if (g_str_to_func.find(fn_name) == g_str_to_func.end()) {
+ printf("ERROR:No benchmark for function %s\n", fn_name.c_str());
+ abort();
+ }
+ long iterations_to_use = primary_opts.num_iterations ? primary_opts.num_iterations :
+ secondary_opts.num_iterations;
+ int cpu_to_use = INT_MAX;
+ if (primary_opts.cpu_to_lock != INT_MAX) {
+ cpu_to_use = primary_opts.cpu_to_lock;
+
+ } else if (secondary_opts.cpu_to_lock != INT_MAX) {
+ cpu_to_use = secondary_opts.cpu_to_lock;
+ }
+
+ for (std::vector<int> args : (*run_args)) {
+ auto registration = benchmark::RegisterBenchmark(fn_name.c_str(), LockAndRun,
+ g_str_to_func.at(fn_name),
+ cpu_to_use)->Args(args);
+ if (iterations_to_use > 0) {
+ registration->Iterations(iterations_to_use);
+ }
+ }
+}
+
+void RegisterCliBenchmarks(bench_opts_t cmdline_opts,
+ std::map<std::string, args_vector_t>& args_shorthand) {
+ // Register any of the extra benchmarks that were specified in the options.
+ args_vector_t arg_vector;
+ args_vector_t* run_args = &arg_vector;
+ for (std::string extra_fn : cmdline_opts.extra_benchmarks) {
+ android::base::Trim(extra_fn);
+ size_t first_space_pos = extra_fn.find(" ");
+ std::string fn_name = extra_fn.substr(0, first_space_pos);
+ std::string cmd_args;
+ if (first_space_pos != std::string::npos) {
+ cmd_args = extra_fn.substr(extra_fn.find(" ") + 1);
+ } else {
+ cmd_args = "";
+ }
+ run_args = ResolveArgs(run_args, cmd_args, args_shorthand);
+ RegisterGoogleBenchmarks(bench_opts_t(), cmdline_opts, fn_name, run_args);
+
+ run_args = &arg_vector;
+ arg_vector.clear();
+ }
+}
+
+int RegisterXmlBenchmarks(bench_opts_t cmdline_opts,
+ std::map<std::string, args_vector_t>& args_shorthand) {
+ // Structure of the XML file:
+ // - Element "fn" Function to benchmark.
+ // - - Element "iterations" Number of iterations to run. Leaving this blank uses
+ // Google benchmarks' convergence heuristics.
+ // - - Element "cpu" CPU to isolate to, if any.
+ // - - Element "args" Whitespace-separated list of per-function integer arguments, or
+ // one of the macros defined in util.h.
+ tinyxml2::XMLDocument doc;
+ if (doc.LoadFile(cmdline_opts.xmlpath.c_str()) != tinyxml2::XML_NO_ERROR) {
+ doc.PrintError();
+ return doc.ErrorID();
+ }
+
+ // Read and register the functions.
+ tinyxml2::XMLNode* fn = doc.FirstChildElement("fn");
+ args_vector_t arg_vector;
+ args_vector_t* run_args = &arg_vector;
+ while (fn) {
+ auto fn_elem = fn->FirstChildElement("name");
+ if (!fn_elem) {
+ printf("Error: Malformed XML entry: missing name element.\n");
+ abort();
+ }
+ std::string fn_name = fn_elem->GetText();
+ if (fn_name.empty()) {
+ printf("Error: Malformed XML entry: error parsing name text.");
+ abort();
+ }
+ auto* xml_args = fn->FirstChildElement("args");
+ run_args = ResolveArgs(run_args, xml_args ? android::base::Trim(xml_args->GetText()) : "",
+ args_shorthand);
+
+ // XML values for CPU and iterations take precedence over those passed in via CLI.
+ bench_opts_t xml_opts{};
+ auto* num_iterations_elem = fn->FirstChildElement("iterations");
+ if (num_iterations_elem) {
+ int temp;
+ num_iterations_elem->QueryIntText(&temp);
+ xml_opts.num_iterations = temp;
+ } else {
+ xml_opts.num_iterations = 0;
+ }
+ auto* cpu_to_lock_elem = fn->FirstChildElement("cpu");
+ if (cpu_to_lock_elem) {
+ int temp;
+ cpu_to_lock_elem->QueryIntText(&temp);
+ xml_opts.cpu_to_lock = temp;
+ } else {
+ xml_opts.cpu_to_lock = INT_MAX;
+ }
+
+ RegisterGoogleBenchmarks(xml_opts, cmdline_opts, fn_name, run_args);
+
+ fn = fn->NextSibling();
+ run_args = &arg_vector;
+ arg_vector.clear();
+ }
+ return 0;
+}
+
+std::map<std::string, args_vector_t> GetShorthand() {
+ std::map<std::string, args_vector_t> 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} }},
+ {"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}}},
+
+ {"AT_COMMON_SIZES", args_vector_t{ {8}, {64}, {512}, {1*KB}, {8*KB}, {16*KB},
+ {32*KB}, {64*KB}}},
+
+ // Do not exceed 512. that is about the largest number of properties
+ // that can be created with the current property area size.
+ {"NUM_PROPS", args_vector_t{ {1}, {4}, {16}, {64}, {128}, {256}, {512} }},
+
+ {"MATH_COMMON", args_vector_t{ {0}, {1}, {2}, {3} }}
+ };
+ for (int i = 1; i < 15; i++) {
+ int align = pow(2, i);
+ std::stringstream sstream;
+ sstream << "AT_" << align << "_ALIGN_TWOBUF";
+ args_shorthand.emplace(sstream.str(),
+ args_vector_t{ {8, align, align},
+ {64, align, align},
+ {512, align, align},
+ {1 * KB, align, align},
+ {8 * KB, align, align},
+ {16 * KB, align, align},
+ {32 * KB, align, align},
+ {64 * KB, align, align} });
+ sstream.str("");
+ sstream << "AT_" << align << "_ALIGN_ONEBUF";
+ args_shorthand.emplace(sstream.str(),
+ args_vector_t{ {(8), align},
+ {(64), align},
+ {(512), align},
+ {(1*KB), align},
+ {(8*KB), align},
+ {(16*KB), align},
+ {(32*KB), align},
+ {(64*KB), align} });
+ sstream.str("");
+ }
+ return args_shorthand;
+}
+
+
+int main(int argc, char** argv) {
+ std::map<std::string, args_vector_t> args_shorthand = GetShorthand();
+ bench_opts_t opts = ParseOpts(argc, argv);
+ std::vector<char*> new_argv(argc);
+ SanitizeOpts(argc, argv, &new_argv);
+
+ if (!opts.xmlpath.empty()) {
+ if (int err = RegisterXmlBenchmarks(opts, args_shorthand)) {
+ return err;
+ }
+ }
+ RegisterCliBenchmarks(opts, args_shorthand);
+
+ // Set the thread priority to the maximum.
+ if (setpriority(PRIO_PROCESS, 0, -20)) {
+ perror("Failed to raise priority of process. Are you root?\n");
+ }
+
+ int new_argc = new_argv.size();
+ benchmark::Initialize(&new_argc, new_argv.data());
+ benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/benchmarks/math_benchmark.cpp b/benchmarks/math_benchmark.cpp
index a411c9ca1..7b9a28321 100644
--- a/benchmarks/math_benchmark.cpp
+++ b/benchmarks/math_benchmark.cpp
@@ -18,11 +18,11 @@
#include <math.h>
#include <benchmark/benchmark.h>
+#include "util.h"
static const double values[] = { 1234.0, nan(""), HUGE_VAL, 0.0 };
static const char* names[] = { "1234.0", "nan", "HUGE_VAL", "0.0" };
-#define BENCHMARK_COMMON_VALS(name) BENCHMARK(name)->Arg(0)->Arg(1)->Arg(2)->Arg(3)
static void SetLabel(benchmark::State& state) {
state.SetLabel(names[state.range(0)]);
@@ -39,7 +39,7 @@ static void BM_math_sqrt(benchmark::State& state) {
d += sqrt(v);
}
}
-BENCHMARK(BM_math_sqrt);
+BIONIC_BENCHMARK(BM_math_sqrt);
static void BM_math_log10(benchmark::State& state) {
d = 0.0;
@@ -48,7 +48,7 @@ static void BM_math_log10(benchmark::State& state) {
d += log10(v);
}
}
-BENCHMARK(BM_math_log10);
+BIONIC_BENCHMARK(BM_math_log10);
static void BM_math_logb(benchmark::State& state) {
d = 0.0;
@@ -57,7 +57,7 @@ static void BM_math_logb(benchmark::State& state) {
d += logb(v);
}
}
-BENCHMARK(BM_math_logb);
+BIONIC_BENCHMARK(BM_math_logb);
static void BM_math_isfinite_macro(benchmark::State& state) {
d = 0.0;
@@ -67,7 +67,7 @@ static void BM_math_isfinite_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isfinite_macro);
+BIONIC_BENCHMARK(BM_math_isfinite_macro);
#if defined(__BIONIC__)
#define test_isfinite __isfinite
@@ -82,7 +82,7 @@ static void BM_math_isfinite(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isfinite);
+BIONIC_BENCHMARK(BM_math_isfinite);
static void BM_math_isinf_macro(benchmark::State& state) {
d = 0.0;
@@ -92,7 +92,7 @@ static void BM_math_isinf_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isinf_macro);
+BIONIC_BENCHMARK(BM_math_isinf_macro);
static void BM_math_isinf(benchmark::State& state) {
d = 0.0;
@@ -102,7 +102,7 @@ static void BM_math_isinf(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isinf);
+BIONIC_BENCHMARK(BM_math_isinf);
static void BM_math_isnan_macro(benchmark::State& state) {
d = 0.0;
@@ -112,7 +112,7 @@ static void BM_math_isnan_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isnan_macro);
+BIONIC_BENCHMARK(BM_math_isnan_macro);
static void BM_math_isnan(benchmark::State& state) {
d = 0.0;
@@ -122,7 +122,7 @@ static void BM_math_isnan(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isnan);
+BIONIC_BENCHMARK(BM_math_isnan);
static void BM_math_isnormal_macro(benchmark::State& state) {
d = 0.0;
@@ -132,7 +132,7 @@ static void BM_math_isnormal_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isnormal_macro);
+BIONIC_BENCHMARK(BM_math_isnormal_macro);
#if defined(__BIONIC__)
static void BM_math_isnormal(benchmark::State& state) {
@@ -143,7 +143,7 @@ static void BM_math_isnormal(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_isnormal);
+BIONIC_BENCHMARK(BM_math_isnormal);
#endif
static void BM_math_sin_fast(benchmark::State& state) {
@@ -152,7 +152,7 @@ static void BM_math_sin_fast(benchmark::State& state) {
d += sin(d);
}
}
-BENCHMARK(BM_math_sin_fast);
+BIONIC_BENCHMARK(BM_math_sin_fast);
static void BM_math_sin_feupdateenv(benchmark::State& state) {
d = 1.0;
@@ -164,7 +164,7 @@ static void BM_math_sin_feupdateenv(benchmark::State& state) {
feupdateenv(&__libc_save_rm);
}
}
-BENCHMARK(BM_math_sin_feupdateenv);
+BIONIC_BENCHMARK(BM_math_sin_feupdateenv);
static void BM_math_sin_fesetenv(benchmark::State& state) {
d = 1.0;
@@ -176,7 +176,7 @@ static void BM_math_sin_fesetenv(benchmark::State& state) {
fesetenv(&__libc_save_rm);
}
}
-BENCHMARK(BM_math_sin_fesetenv);
+BIONIC_BENCHMARK(BM_math_sin_fesetenv);
static void BM_math_fpclassify(benchmark::State& state) {
d = 0.0;
@@ -186,7 +186,7 @@ static void BM_math_fpclassify(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_fpclassify);
+BIONIC_BENCHMARK(BM_math_fpclassify);
static void BM_math_signbit_macro(benchmark::State& state) {
d = 0.0;
@@ -196,7 +196,7 @@ static void BM_math_signbit_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_signbit_macro);
+BIONIC_BENCHMARK(BM_math_signbit_macro);
static void BM_math_signbit(benchmark::State& state) {
d = 0.0;
@@ -206,7 +206,7 @@ static void BM_math_signbit(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_signbit);
+BIONIC_BENCHMARK(BM_math_signbit);
static void BM_math_fabs_macro(benchmark::State& state) {
d = 0.0;
@@ -216,7 +216,7 @@ static void BM_math_fabs_macro(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_fabs_macro);
+BIONIC_BENCHMARK(BM_math_fabs_macro);
static void BM_math_fabs(benchmark::State& state) {
d = 0.0;
@@ -226,4 +226,4 @@ static void BM_math_fabs(benchmark::State& state) {
}
SetLabel(state);
}
-BENCHMARK_COMMON_VALS(BM_math_fabs);
+BIONIC_BENCHMARK(BM_math_fabs);
diff --git a/benchmarks/property_benchmark.cpp b/benchmarks/property_benchmark.cpp
index 97eb832c6..a099494b6 100644
--- a/benchmarks/property_benchmark.cpp
+++ b/benchmarks/property_benchmark.cpp
@@ -27,11 +27,7 @@
#include <sys/_system_properties.h>
#include <benchmark/benchmark.h>
-
-// Do not exceed 512, that is about the largest number of properties
-// that can be created with the current property area size.
-#define TEST_NUM_PROPS \
- Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
+#include "util.h"
struct LocalPropertyTestState {
explicit LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
@@ -145,7 +141,7 @@ static void BM_property_get(benchmark::State& state) {
__system_property_get(pa.names[random() % nprops], value);
}
}
-BENCHMARK(BM_property_get)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_get);
static void BM_property_find(benchmark::State& state) {
const size_t nprops = state.range(0);
@@ -157,7 +153,7 @@ static void BM_property_find(benchmark::State& state) {
__system_property_find(pa.names[random() % nprops]);
}
}
-BENCHMARK(BM_property_find)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_find);
static void BM_property_read(benchmark::State& state) {
const size_t nprops = state.range(0);
@@ -180,7 +176,7 @@ static void BM_property_read(benchmark::State& state) {
delete[] pinfo;
}
-BENCHMARK(BM_property_read)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_read);
static void BM_property_serial(benchmark::State& state) {
const size_t nprops = state.range(0);
@@ -201,6 +197,6 @@ static void BM_property_serial(benchmark::State& state) {
delete[] pinfo;
}
-BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;
+BIONIC_BENCHMARK(BM_property_serial);
#endif // __BIONIC__
diff --git a/benchmarks/pthread_benchmark.cpp b/benchmarks/pthread_benchmark.cpp
index d3c2de865..7a967ef73 100644
--- a/benchmarks/pthread_benchmark.cpp
+++ b/benchmarks/pthread_benchmark.cpp
@@ -17,6 +17,7 @@
#include <pthread.h>
#include <benchmark/benchmark.h>
+#include "util.h"
// Stop GCC optimizing out our pure function.
/* Must not be static! */ pthread_t (*pthread_self_fp)() = pthread_self;
@@ -26,7 +27,7 @@ static void BM_pthread_self(benchmark::State& state) {
pthread_self_fp();
}
}
-BENCHMARK(BM_pthread_self);
+BIONIC_BENCHMARK(BM_pthread_self);
static void BM_pthread_getspecific(benchmark::State& state) {
pthread_key_t key;
@@ -38,7 +39,7 @@ static void BM_pthread_getspecific(benchmark::State& state) {
pthread_key_delete(key);
}
-BENCHMARK(BM_pthread_getspecific);
+BIONIC_BENCHMARK(BM_pthread_getspecific);
static void BM_pthread_setspecific(benchmark::State& state) {
pthread_key_t key;
@@ -50,7 +51,7 @@ static void BM_pthread_setspecific(benchmark::State& state) {
pthread_key_delete(key);
}
-BENCHMARK(BM_pthread_setspecific);
+BIONIC_BENCHMARK(BM_pthread_setspecific);
static void DummyPthreadOnceInitFunction() {
}
@@ -63,7 +64,7 @@ static void BM_pthread_once(benchmark::State& state) {
pthread_once(&once, DummyPthreadOnceInitFunction);
}
}
-BENCHMARK(BM_pthread_once);
+BIONIC_BENCHMARK(BM_pthread_once);
static void BM_pthread_mutex_lock(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -73,7 +74,7 @@ static void BM_pthread_mutex_lock(benchmark::State& state) {
pthread_mutex_unlock(&mutex);
}
}
-BENCHMARK(BM_pthread_mutex_lock);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock);
static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
@@ -83,7 +84,7 @@ static void BM_pthread_mutex_lock_ERRORCHECK(benchmark::State& state) {
pthread_mutex_unlock(&mutex);
}
}
-BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock_ERRORCHECK);
static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
@@ -93,7 +94,7 @@ static void BM_pthread_mutex_lock_RECURSIVE(benchmark::State& state) {
pthread_mutex_unlock(&mutex);
}
}
-BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
+BIONIC_BENCHMARK(BM_pthread_mutex_lock_RECURSIVE);
static void BM_pthread_rwlock_read(benchmark::State& state) {
pthread_rwlock_t lock;
@@ -106,7 +107,7 @@ static void BM_pthread_rwlock_read(benchmark::State& state) {
pthread_rwlock_destroy(&lock);
}
-BENCHMARK(BM_pthread_rwlock_read);
+BIONIC_BENCHMARK(BM_pthread_rwlock_read);
static void BM_pthread_rwlock_write(benchmark::State& state) {
pthread_rwlock_t lock;
@@ -119,7 +120,7 @@ static void BM_pthread_rwlock_write(benchmark::State& state) {
pthread_rwlock_destroy(&lock);
}
-BENCHMARK(BM_pthread_rwlock_write);
+BIONIC_BENCHMARK(BM_pthread_rwlock_write);
static void* IdleThread(void*) {
return NULL;
@@ -134,7 +135,7 @@ static void BM_pthread_create(benchmark::State& state) {
state.ResumeTiming();
}
}
-BENCHMARK(BM_pthread_create);
+BIONIC_BENCHMARK(BM_pthread_create);
static void* RunThread(void* arg) {
benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
@@ -150,7 +151,7 @@ static void BM_pthread_create_and_run(benchmark::State& state) {
state.ResumeTiming();
}
}
-BENCHMARK(BM_pthread_create_and_run);
+BIONIC_BENCHMARK(BM_pthread_create_and_run);
static void* ExitThread(void* arg) {
benchmark::State& state = *reinterpret_cast<benchmark::State*>(arg);
@@ -166,7 +167,7 @@ static void BM_pthread_exit_and_join(benchmark::State& state) {
pthread_join(thread, NULL);
}
}
-BENCHMARK(BM_pthread_exit_and_join);
+BIONIC_BENCHMARK(BM_pthread_exit_and_join);
static void BM_pthread_key_create(benchmark::State& state) {
while (state.KeepRunning()) {
@@ -178,7 +179,7 @@ static void BM_pthread_key_create(benchmark::State& state) {
state.ResumeTiming();
}
}
-BENCHMARK(BM_pthread_key_create);
+BIONIC_BENCHMARK(BM_pthread_key_create);
static void BM_pthread_key_delete(benchmark::State& state) {
while (state.KeepRunning()) {
@@ -190,4 +191,4 @@ static void BM_pthread_key_delete(benchmark::State& state) {
pthread_key_delete(key);
}
}
-BENCHMARK(BM_pthread_key_delete);
+BIONIC_BENCHMARK(BM_pthread_key_delete);
diff --git a/benchmarks/semaphore_benchmark.cpp b/benchmarks/semaphore_benchmark.cpp
index b932a2b32..a4aa7bb8f 100644
--- a/benchmarks/semaphore_benchmark.cpp
+++ b/benchmarks/semaphore_benchmark.cpp
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <benchmark/benchmark.h>
+#include "util.h"
static void BM_semaphore_sem_getvalue(benchmark::State& state) {
sem_t semaphore;
@@ -31,7 +32,7 @@ static void BM_semaphore_sem_getvalue(benchmark::State& state) {
sem_getvalue(&semaphore, &dummy);
}
}
-BENCHMARK(BM_semaphore_sem_getvalue);
+BIONIC_BENCHMARK(BM_semaphore_sem_getvalue);
static void BM_semaphore_sem_wait_sem_post(benchmark::State& state) {
sem_t semaphore;
@@ -42,7 +43,7 @@ static void BM_semaphore_sem_wait_sem_post(benchmark::State& state) {
sem_post(&semaphore);
}
}
-BENCHMARK(BM_semaphore_sem_wait_sem_post);
+BIONIC_BENCHMARK(BM_semaphore_sem_wait_sem_post);
// This test reports the overhead of the underlying futex wake syscall on
// the producer. It does not report the overhead from issuing the wake to the
@@ -119,7 +120,9 @@ class SemaphoreFixture : public benchmark::Fixture {
bool setup = false;
};
-BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
+// This is commented out because dynamic benchmark registering doesn't currently support fixtures.
+// Uncomment it and recompile to run this benchmark on every run.
+/* BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
while (state.KeepRunning()) {
state.PauseTiming();
@@ -149,4 +152,4 @@ BENCHMARK_F(SemaphoreFixture, semaphore_sem_post)(benchmark::State& state) {
param.sched_priority = 0;
sched_setscheduler(0, SCHED_IDLE, &param);
}
-}
+}*/
diff --git a/benchmarks/stdio_benchmark.cpp b/benchmarks/stdio_benchmark.cpp
index f49677956..756a698bb 100644
--- a/benchmarks/stdio_benchmark.cpp
+++ b/benchmarks/stdio_benchmark.cpp
@@ -19,12 +19,7 @@
#include <stdlib.h>
#include <benchmark/benchmark.h>
-
-constexpr auto KB = 1024;
-
-#define AT_COMMON_SIZES \
- Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(8)->Arg(16)->Arg(32)->Arg(64)->Arg(512)-> \
- Arg(1*KB)->Arg(4*KB)->Arg(8*KB)->Arg(16*KB)->Arg(64*KB)
+#include "util.h"
template <typename Fn>
void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) {
@@ -50,22 +45,22 @@ void ReadWriteTest(benchmark::State& state, Fn f, bool buffered) {
void BM_stdio_fread(benchmark::State& state) {
ReadWriteTest(state, fread, true);
}
-BENCHMARK(BM_stdio_fread)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fread);
void BM_stdio_fwrite(benchmark::State& state) {
ReadWriteTest(state, fwrite, true);
}
-BENCHMARK(BM_stdio_fwrite)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fwrite);
void BM_stdio_fread_unbuffered(benchmark::State& state) {
ReadWriteTest(state, fread, false);
}
-BENCHMARK(BM_stdio_fread_unbuffered)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fread_unbuffered);
void BM_stdio_fwrite_unbuffered(benchmark::State& state) {
ReadWriteTest(state, fwrite, false);
}
-BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES;
+BIONIC_BENCHMARK(BM_stdio_fwrite_unbuffered);
static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
char buf[1024];
@@ -80,9 +75,9 @@ static void FopenFgetsFclose(benchmark::State& state, bool no_locking) {
static void BM_stdio_fopen_fgets_fclose_locking(benchmark::State& state) {
FopenFgetsFclose(state, false);
}
-BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
+BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
void BM_stdio_fopen_fgets_fclose_no_locking(benchmark::State& state) {
FopenFgetsFclose(state, true);
}
-BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
+BIONIC_BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);
diff --git a/benchmarks/string_benchmark.cpp b/benchmarks/string_benchmark.cpp
index 2ab65a891..729b20dbd 100644
--- a/benchmarks/string_benchmark.cpp
+++ b/benchmarks/string_benchmark.cpp
@@ -18,27 +18,7 @@
#include <string.h>
#include <benchmark/benchmark.h>
-#include "util.h"
-
-constexpr auto KB = 1024;
-
-// NOTE: these constants are temporary replacements for AT_COMMON_SIZES until
-// the new interface for Bionic benchmarks is implemented.
-
-// Set all four to 0 to test normal alignment.
-#define AT_SRC_ALIGN 0
-#define AT_DST_ALIGN 0
-
-#define AT_ALIGNED_TWOBUF \
- Args({(8), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
- Args({(512), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(1*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
- Args({(8*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(16*KB), AT_SRC_ALIGN, AT_DST_ALIGN})-> \
- Args({(32*KB), AT_SRC_ALIGN, AT_DST_ALIGN})->Args({(64*KB), AT_SRC_ALIGN, AT_DST_ALIGN})
-
-#define AT_ALIGNED_ONEBUF \
- Args({(8), AT_SRC_ALIGN})->Args({(64), AT_SRC_ALIGN})->Args({(512), AT_SRC_ALIGN})-> \
- Args({(1*KB), AT_SRC_ALIGN})->Args({(8*KB), AT_SRC_ALIGN})->Args({(16*KB), AT_SRC_ALIGN})-> \
- Args({(32*KB), AT_SRC_ALIGN})->Args({(64*KB), AT_SRC_ALIGN})
+#include <util.h>
static void BM_string_memcmp(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -57,7 +37,7 @@ static void BM_string_memcmp(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memcmp)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memcmp);
static void BM_string_memcpy(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -75,7 +55,7 @@ static void BM_string_memcpy(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memcpy)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memcpy);
static void BM_string_memmove_non_overlapping(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -93,7 +73,7 @@ static void BM_string_memmove_non_overlapping(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memmove_non_overlapping)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_memmove_non_overlapping);
static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -108,7 +88,7 @@ static void BM_string_memmove_overlap_dst_before_src(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memmove_overlap_dst_before_src)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memmove_overlap_dst_before_src);
static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -123,7 +103,7 @@ static void BM_string_memmove_overlap_src_before_dst(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memmove_overlap_src_before_dst)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memmove_overlap_src_before_dst);
static void BM_string_memset(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -138,7 +118,7 @@ static void BM_string_memset(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_memset)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_memset);
static void BM_string_strlen(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -155,7 +135,7 @@ static void BM_string_strlen(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strlen)->AT_ALIGNED_ONEBUF;
+BIONIC_BENCHMARK(BM_string_strlen);
static void BM_string_strcat_copy_only(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -178,7 +158,7 @@ static void BM_string_strcat_copy_only(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strcat_copy_only)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_copy_only);
static void BM_string_strcat_seek_only(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -199,7 +179,7 @@ static void BM_string_strcat_seek_only(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strcat_seek_only)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_seek_only);
static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -220,7 +200,7 @@ static void BM_string_strcat_half_copy_half_seek(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strcat_half_copy_half_seek)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcat_half_copy_half_seek);
static void BM_string_strcpy(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -239,7 +219,7 @@ static void BM_string_strcpy(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strcpy)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcpy);
static void BM_string_strcmp(benchmark::State& state) {
const size_t nbytes = state.range(0);
@@ -260,4 +240,4 @@ static void BM_string_strcmp(benchmark::State& state) {
state.SetBytesProcessed(uint64_t(state.iterations()) * uint64_t(nbytes));
}
-BENCHMARK(BM_string_strcmp)->AT_ALIGNED_TWOBUF;
+BIONIC_BENCHMARK(BM_string_strcmp);
diff --git a/benchmarks/suites/full.xml b/benchmarks/suites/full.xml
new file mode 100644
index 000000000..707a3d626
--- /dev/null
+++ b/benchmarks/suites/full.xml
@@ -0,0 +1,267 @@
+<fn>
+ <name>BM_empty</name>
+</fn>
+<fn>
+ <name>BM_load_relaxed</name>
+</fn>
+<fn>
+ <name>BM_load_acquire</name>
+</fn>
+<fn>
+ <name>BM_store_release</name>
+</fn>
+<fn>
+ <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_acquire_fence</name>
+</fn>
+<fn>
+ <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_math_log10</name>
+</fn>
+<fn>
+ <name>BM_math_logb</name>
+</fn>
+<fn>
+ <name>BM_math_isfinite_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isfinite</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isinf_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isinf</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isnan_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isnan</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isnormal_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_isnormal</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+ <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+ <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+ <name>BM_math_fpclassify</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_signbit_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_signbit</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_fabs_macro</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_math_fabs</name>
+ <args>MATH_COMMON</args>
+</fn>
+<fn>
+ <name>BM_property_get</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_find</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_read</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_serial</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_pthread_self</name>
+</fn>
+<fn>
+ <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_once</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+ <name>BM_pthread_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+ <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+ <name>BM_stdio_fread</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fread_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_locking</name>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_non_overlapping</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_dst_before_src</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_src_before_dst</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memset</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_copy_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_seek_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_half_copy_half_seek</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_time</name>
+</fn>
+<fn>
+ <name>BM_time_localtime</name>
+</fn>
+<fn>
+ <name>BM_time_localtime_r</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+ <name>BM_unistd_gettid</name>
+</fn>
+<fn>
+ <name>BM_unistd_gettid_syscall</name>
+</fn>
diff --git a/benchmarks/suites/host.xml b/benchmarks/suites/host.xml
new file mode 100644
index 000000000..c4d0d3a3e
--- /dev/null
+++ b/benchmarks/suites/host.xml
@@ -0,0 +1,244 @@
+<fn>
+ <name>BM_empty</name>
+</fn>
+<fn>
+ <name>BM_load_relaxed</name>
+</fn>
+<fn>
+ <name>BM_load_acquire</name>
+</fn>
+<fn>
+ <name>BM_store_release</name>
+</fn>
+<fn>
+ <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_acquire_fence</name>
+</fn>
+<fn>
+ <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_math_log10</name>
+</fn>
+<fn>
+ <name>BM_math_logb</name>
+</fn>
+<fn>
+ <name>BM_math_isfinite_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isfinite</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isinf_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isinf</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnan_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnan</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnormal_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+ <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+ <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+ <name>BM_math_fpclassify</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_signbit_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_signbit</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_fabs_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_fabs</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_pthread_self</name>
+</fn>
+<fn>
+ <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_once</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+ <name>BM_pthread_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+ <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+ <name>BM_stdio_fread</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fread_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_locking</name>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_non_overlapping</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_dst_before_src</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_src_before_dst</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memset</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_copy_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_seek_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_half_copy_half_seek</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_time</name>
+</fn>
+<fn>
+ <name>BM_time_localtime</name>
+</fn>
+<fn>
+ <name>BM_time_localtime_r</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+ <name>BM_unistd_gettid_syscall</name>
+</fn>
diff --git a/benchmarks/suites/test_alignment.xml b/benchmarks/suites/test_alignment.xml
new file mode 100644
index 000000000..20df3202d
--- /dev/null
+++ b/benchmarks/suites/test_alignment.xml
@@ -0,0 +1,50 @@
+<fn>
+ <name>BM_string_memcmp</name>
+ <iterations>1</iterations>
+ <args>AT_2_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <iterations>1</iterations>
+ <args>AT_4_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <iterations>1</iterations>
+ <args>AT_16_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <iterations>1</iterations>
+ <args>AT_512_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <iterations>1</iterations>
+ <args>AT_2048_ALIGN_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <iterations>1</iterations>
+ <args>AT_2_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <iterations>1</iterations>
+ <args>AT_4_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <iterations>1</iterations>
+ <args>AT_16_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <iterations>1</iterations>
+ <args>AT_512_ALIGN_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <iterations>1</iterations>
+ <args>AT_2048_ALIGN_ONEBUF</args>
+</fn>
diff --git a/benchmarks/suites/test_from_each.xml b/benchmarks/suites/test_from_each.xml
new file mode 100644
index 000000000..01183650a
--- /dev/null
+++ b/benchmarks/suites/test_from_each.xml
@@ -0,0 +1,30 @@
+<fn>
+ <name>BM_empty</name>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_property_get</name>
+ <args>1</args>
+</fn>
+<fn>
+ <name>BM_pthread_self</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+ <name>BM_stdio_fread</name>
+ <args>64</args>
+</fn>
+<fn>
+ <name>BM_string_memcpy</name>
+ <args>512 4 4</args>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid</name>
+</fn>
diff --git a/benchmarks/suites/test_full.xml b/benchmarks/suites/test_full.xml
new file mode 100644
index 000000000..f9d97ee4f
--- /dev/null
+++ b/benchmarks/suites/test_full.xml
@@ -0,0 +1,261 @@
+<fn>
+ <name>BM_empty</name>
+</fn>
+<fn>
+ <name>BM_load_relaxed</name>
+</fn>
+<fn>
+ <name>BM_load_acquire</name>
+</fn>
+<fn>
+ <name>BM_store_release</name>
+</fn>
+<fn>
+ <name>BM_store_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_relaxed</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_seq_cst</name>
+</fn>
+<fn>
+ <name>BM_acquire_fence</name>
+</fn>
+<fn>
+ <name>BM_seq_cst_fence</name>
+</fn>
+<fn>
+ <name>BM_fetch_add_cs</name>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_math_log10</name>
+</fn>
+<fn>
+ <name>BM_math_logb</name>
+</fn>
+<fn>
+ <name>BM_math_isfinite_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isfinite</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isinf_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isinf</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnan_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnan</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnormal_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_isnormal</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_sin_fast</name>
+</fn>
+<fn>
+ <name>BM_math_sin_feupdateenv</name>
+</fn>
+<fn>
+ <name>BM_math_sin_fesetenv</name>
+</fn>
+<fn>
+ <name>BM_math_fpclassify</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_signbit_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_signbit</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_fabs_macro</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_math_fabs</name>
+ <args>0</args>
+</fn>
+<fn>
+ <name>BM_property_get</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_find</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_read</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_property_serial</name>
+ <args>NUM_PROPS</args>
+</fn>
+<fn>
+ <name>BM_pthread_self</name>
+</fn>
+<fn>
+ <name>BM_pthread_getspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_setspecific</name>
+</fn>
+<fn>
+ <name>BM_pthread_once</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_ERRORCHECK</name>
+</fn>
+<fn>
+ <name>BM_pthread_mutex_lock_RECURSIVE</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_read</name>
+</fn>
+<fn>
+ <name>BM_pthread_rwlock_write</name>
+</fn>
+<fn>
+ <name>BM_pthread_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_create_and_run</name>
+</fn>
+<fn>
+ <name>BM_pthread_exit_and_join</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_create</name>
+</fn>
+<fn>
+ <name>BM_pthread_key_delete</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_getvalue</name>
+</fn>
+<fn>
+ <name>BM_semaphore_sem_wait_sem_post</name>
+</fn>
+<fn>
+ <name>BM_stdio_fread</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fread_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fwrite_unbuffered</name>
+ <args>AT_COMMON_SIZES</args>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_locking</name>
+</fn>
+<fn>
+ <name>BM_stdio_fopen_fgets_fclose_no_locking</name>
+</fn>
+<fn>
+ <name>BM_string_memcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_non_overlapping</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_dst_before_src</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memmove_overlap_src_before_dst</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_memset</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strlen</name>
+ <args>AT_ALIGNED_ONEBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_copy_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_seek_only</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcat_half_copy_half_seek</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcpy</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_string_strcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime</name>
+</fn>
+<fn>
+ <name>BM_time_clock_gettime_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday</name>
+</fn>
+<fn>
+ <name>BM_time_gettimeofday_syscall</name>
+</fn>
+<fn>
+ <name>BM_time_time</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid</name>
+</fn>
+<fn>
+ <name>BM_unistd_getpid_syscall</name>
+</fn>
+<fn>
+ <name>BM_unistd_gettid</name>
+</fn>
+<fn>
+ <name>BM_unistd_gettid_syscall</name>
+</fn>
diff --git a/benchmarks/suites/test_medium.xml b/benchmarks/suites/test_medium.xml
new file mode 100644
index 000000000..9528af35e
--- /dev/null
+++ b/benchmarks/suites/test_medium.xml
@@ -0,0 +1,16 @@
+<fn>
+ <name>BM_string_memcmp</name>
+ <args>AT_ALIGNED_TWOBUF</args>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_string_memcpy</name>
+ <iterations>25</iterations>
+ <args>512 4 4</args>
+</fn>
+<fn>
+ <name>BM_property_get</name>
+ <args>1</args>
+</fn>
diff --git a/benchmarks/suites/test_small.xml b/benchmarks/suites/test_small.xml
new file mode 100644
index 000000000..a4cc28527
--- /dev/null
+++ b/benchmarks/suites/test_small.xml
@@ -0,0 +1,11 @@
+<fn>
+ <name>BM_string_memcmp</name>
+ <args>8 8 8</args>
+</fn>
+<fn>
+ <name>BM_math_sqrt</name>
+</fn>
+<fn>
+ <name>BM_property_get</name>
+ <args>1</args>
+</fn>
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
new file mode 100644
index 000000000..a9e303106
--- /dev/null
+++ b/benchmarks/tests/interface_test.cpp
@@ -0,0 +1,526 @@
+/*
+ * Copyright (C) 2014 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 <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <regex>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+class SystemTests : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ raw_output_ = "";
+ sanitized_output_ = "";
+ exitcode_ = 0;
+ }
+
+ void SanitizeOutput();
+
+ void Exec(std::vector<const char*> args);
+ void ExecAndCapture(std::vector<const char*> args);
+ void RunTest(std::vector<const char*> extra_args = {});
+ void Verify(const std::string& expected_output, int expected_exitcode,
+ std::vector<const char*> extra_args = {});
+
+ std::string raw_output_;
+ std::string sanitized_output_;
+ int exitcode_;
+ pid_t pid_;
+ int fd_;
+};
+
+void SystemTests::SanitizeOutput() {
+ // Cut off anything after the arguments, since that varies with time.
+ sanitized_output_ = std::regex_replace(raw_output_, std::regex(".+(BM_\\S+) +.+"), "$1");
+
+ // Remove everything before the header.
+ sanitized_output_.erase(0, sanitized_output_.find("------------------------------------------------"));
+
+ // Remove the header.
+ sanitized_output_.erase(0, sanitized_output_.find("BM_"));
+
+ // Remove any hanging output.
+ sanitized_output_.erase(sanitized_output_.find_last_of("BM_\\S+\n") + 1);
+}
+
+static void GetExe(std::string* exe_name) {
+ char path[PATH_MAX];
+ ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
+ ASSERT_TRUE(path_len >= 0);
+ *exe_name = std::string(std::regex_replace(path, std::regex("-tests"), ""));
+}
+
+void SystemTests::Exec(std::vector<const char*> args) {
+ int fds[2];
+ ASSERT_NE(-1, pipe(fds));
+ ASSERT_NE(-1, fcntl(fds[0], F_SETFL, O_NONBLOCK));
+
+ if ((pid_ = fork()) == 0) {
+ // Run the test.
+ close(fds[0]);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+ ASSERT_NE(0, dup2(fds[1], STDOUT_FILENO));
+ ASSERT_NE(0, dup2(fds[1], STDERR_FILENO));
+ close(fds[1]);
+
+ std::string exe_name;
+ GetExe(&exe_name);
+ args.insert(args.begin(), exe_name.c_str());
+ args.push_back(nullptr);
+ execv(args[0], reinterpret_cast<char* const*>(const_cast<char**>(args.data())));
+ exit(1);
+ }
+ ASSERT_NE(-1, pid_);
+
+ close(fds[1]);
+ fd_ = fds[0];
+}
+
+void SystemTests::Verify(const std::string& expected_output,
+ int expected_exitcode, std::vector<const char*> extra_args) {
+ std::vector<const char*> args;
+ for (const auto& arg : extra_args) {
+ args.push_back(arg);
+ }
+
+ Exec(args);
+
+ raw_output_ = "";
+ while (true) {
+ char buffer[4097];
+ ssize_t bytes = TEMP_FAILURE_RETRY(read(fd_, buffer, sizeof(buffer) - 1));
+ if (bytes == -1 && errno == EAGAIN) {
+ continue;
+ }
+ ASSERT_NE(-1, bytes);
+ if (bytes == 0) {
+ break;
+ }
+ buffer[bytes] = '\0';
+ raw_output_ += buffer;
+ }
+ close(fd_);
+
+ int status;
+ ASSERT_EQ(pid_, TEMP_FAILURE_RETRY(waitpid(pid_, &status, 0))) << "Test output:\n" << raw_output_;
+ exitcode_ = WEXITSTATUS(status);
+ SanitizeOutput();
+
+ ASSERT_EQ(expected_exitcode, exitcode_) << "Test output:\n" << raw_output_;
+ if (!expected_output.empty()) {
+ ASSERT_EQ(expected_output, sanitized_output_);
+ }
+
+}
+
+TEST_F(SystemTests, full_suite) {
+ std::string expected =
+ "BM_empty/iterations:1\n"
+ "BM_load_relaxed/iterations:1\n"
+ "BM_load_acquire/iterations:1\n"
+ "BM_store_release/iterations:1\n"
+ "BM_store_seq_cst/iterations:1\n"
+ "BM_fetch_add_relaxed/iterations:1\n"
+ "BM_fetch_add_seq_cst/iterations:1\n"
+ "BM_acquire_fence/iterations:1\n"
+ "BM_seq_cst_fence/iterations:1\n"
+ "BM_fetch_add_cs/iterations:1\n"
+ "BM_math_sqrt/iterations:1\n"
+ "BM_math_log10/iterations:1\n"
+ "BM_math_logb/iterations:1\n"
+ "BM_math_isfinite_macro/0/iterations:1\n"
+ "BM_math_isfinite/0/iterations:1\n"
+ "BM_math_isinf_macro/0/iterations:1\n"
+ "BM_math_isinf/0/iterations:1\n"
+ "BM_math_isnan_macro/0/iterations:1\n"
+ "BM_math_isnan/0/iterations:1\n"
+ "BM_math_isnormal_macro/0/iterations:1\n"
+ "BM_math_isnormal/0/iterations:1\n"
+ "BM_math_sin_fast/iterations:1\n"
+ "BM_math_sin_feupdateenv/iterations:1\n"
+ "BM_math_sin_fesetenv/iterations:1\n"
+ "BM_math_fpclassify/0/iterations:1\n"
+ "BM_math_signbit_macro/0/iterations:1\n"
+ "BM_math_signbit/0/iterations:1\n"
+ "BM_math_fabs_macro/0/iterations:1\n"
+ "BM_math_fabs/0/iterations:1\n"
+ "BM_property_get/1/iterations:1\n"
+ "BM_property_get/4/iterations:1\n"
+ "BM_property_get/16/iterations:1\n"
+ "BM_property_get/64/iterations:1\n"
+ "BM_property_get/128/iterations:1\n"
+ "BM_property_get/256/iterations:1\n"
+ "BM_property_get/512/iterations:1\n"
+ "BM_property_find/1/iterations:1\n"
+ "BM_property_find/4/iterations:1\n"
+ "BM_property_find/16/iterations:1\n"
+ "BM_property_find/64/iterations:1\n"
+ "BM_property_find/128/iterations:1\n"
+ "BM_property_find/256/iterations:1\n"
+ "BM_property_find/512/iterations:1\n"
+ "BM_property_read/1/iterations:1\n"
+ "BM_property_read/4/iterations:1\n"
+ "BM_property_read/16/iterations:1\n"
+ "BM_property_read/64/iterations:1\n"
+ "BM_property_read/128/iterations:1\n"
+ "BM_property_read/256/iterations:1\n"
+ "BM_property_read/512/iterations:1\n"
+ "BM_property_serial/1/iterations:1\n"
+ "BM_property_serial/4/iterations:1\n"
+ "BM_property_serial/16/iterations:1\n"
+ "BM_property_serial/64/iterations:1\n"
+ "BM_property_serial/128/iterations:1\n"
+ "BM_property_serial/256/iterations:1\n"
+ "BM_property_serial/512/iterations:1\n"
+ "BM_pthread_self/iterations:1\n"
+ "BM_pthread_getspecific/iterations:1\n"
+ "BM_pthread_setspecific/iterations:1\n"
+ "BM_pthread_once/iterations:1\n"
+ "BM_pthread_mutex_lock/iterations:1\n"
+ "BM_pthread_mutex_lock_ERRORCHECK/iterations:1\n"
+ "BM_pthread_mutex_lock_RECURSIVE/iterations:1\n"
+ "BM_pthread_rwlock_read/iterations:1\n"
+ "BM_pthread_rwlock_write/iterations:1\n"
+ "BM_pthread_create/iterations:1\n"
+ "BM_pthread_create_and_run/iterations:1\n"
+ "BM_pthread_exit_and_join/iterations:1\n"
+ "BM_pthread_key_create/iterations:1\n"
+ "BM_pthread_key_delete/iterations:1\n"
+ "BM_semaphore_sem_getvalue/iterations:1\n"
+ "BM_semaphore_sem_wait_sem_post/iterations:1\n"
+ "BM_stdio_fread/8/iterations:1\n"
+ "BM_stdio_fread/64/iterations:1\n"
+ "BM_stdio_fread/512/iterations:1\n"
+ "BM_stdio_fread/1024/iterations:1\n"
+ "BM_stdio_fread/8192/iterations:1\n"
+ "BM_stdio_fread/16384/iterations:1\n"
+ "BM_stdio_fread/32768/iterations:1\n"
+ "BM_stdio_fread/65536/iterations:1\n"
+ "BM_stdio_fwrite/8/iterations:1\n"
+ "BM_stdio_fwrite/64/iterations:1\n"
+ "BM_stdio_fwrite/512/iterations:1\n"
+ "BM_stdio_fwrite/1024/iterations:1\n"
+ "BM_stdio_fwrite/8192/iterations:1\n"
+ "BM_stdio_fwrite/16384/iterations:1\n"
+ "BM_stdio_fwrite/32768/iterations:1\n"
+ "BM_stdio_fwrite/65536/iterations:1\n"
+ "BM_stdio_fread_unbuffered/8/iterations:1\n"
+ "BM_stdio_fread_unbuffered/64/iterations:1\n"
+ "BM_stdio_fread_unbuffered/512/iterations:1\n"
+ "BM_stdio_fread_unbuffered/1024/iterations:1\n"
+ "BM_stdio_fread_unbuffered/8192/iterations:1\n"
+ "BM_stdio_fread_unbuffered/16384/iterations:1\n"
+ "BM_stdio_fread_unbuffered/32768/iterations:1\n"
+ "BM_stdio_fread_unbuffered/65536/iterations:1\n"
+ "BM_stdio_fwrite_unbuffered/8/iterations:1\n"
+ "BM_stdio_fwrite_unbuffered/64/iterations:1\n"
+ "BM_stdio_fwrite_unbuffered/512/iterations:1\n"
+ "BM_stdio_fwrite_unbuffered/1024/iterations:1\n"
+ "BM_stdio_fwrite_unbuffered/8192/iterations:1\n"
+ "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_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"
+ "BM_string_memcmp/1024/0/0/iterations:1\n"
+ "BM_string_memcmp/8192/0/0/iterations:1\n"
+ "BM_string_memcmp/16384/0/0/iterations:1\n"
+ "BM_string_memcmp/32768/0/0/iterations:1\n"
+ "BM_string_memcmp/65536/0/0/iterations:1\n"
+ "BM_string_memcpy/8/0/0/iterations:1\n"
+ "BM_string_memcpy/64/0/0/iterations:1\n"
+ "BM_string_memcpy/512/0/0/iterations:1\n"
+ "BM_string_memcpy/1024/0/0/iterations:1\n"
+ "BM_string_memcpy/8192/0/0/iterations:1\n"
+ "BM_string_memcpy/16384/0/0/iterations:1\n"
+ "BM_string_memcpy/32768/0/0/iterations:1\n"
+ "BM_string_memcpy/65536/0/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/8/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/64/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/512/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/1024/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/8192/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/16384/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/32768/0/iterations:1\n"
+ "BM_string_memmove_non_overlapping/65536/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/8/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/64/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/512/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/1024/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/8192/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/16384/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/32768/0/iterations:1\n"
+ "BM_string_memmove_overlap_dst_before_src/65536/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/8/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/64/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/512/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/1024/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/8192/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/16384/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/32768/0/iterations:1\n"
+ "BM_string_memmove_overlap_src_before_dst/65536/0/iterations:1\n"
+ "BM_string_memset/8/0/iterations:1\n"
+ "BM_string_memset/64/0/iterations:1\n"
+ "BM_string_memset/512/0/iterations:1\n"
+ "BM_string_memset/1024/0/iterations:1\n"
+ "BM_string_memset/8192/0/iterations:1\n"
+ "BM_string_memset/16384/0/iterations:1\n"
+ "BM_string_memset/32768/0/iterations:1\n"
+ "BM_string_memset/65536/0/iterations:1\n"
+ "BM_string_strlen/8/0/iterations:1\n"
+ "BM_string_strlen/64/0/iterations:1\n"
+ "BM_string_strlen/512/0/iterations:1\n"
+ "BM_string_strlen/1024/0/iterations:1\n"
+ "BM_string_strlen/8192/0/iterations:1\n"
+ "BM_string_strlen/16384/0/iterations:1\n"
+ "BM_string_strlen/32768/0/iterations:1\n"
+ "BM_string_strlen/65536/0/iterations:1\n"
+ "BM_string_strcat_copy_only/8/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/64/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/512/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/1024/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/8192/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/16384/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/32768/0/0/iterations:1\n"
+ "BM_string_strcat_copy_only/65536/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/8/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/64/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/512/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/1024/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/8192/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/16384/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/32768/0/0/iterations:1\n"
+ "BM_string_strcat_seek_only/65536/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/8/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/64/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/512/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/1024/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/8192/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/16384/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/32768/0/0/iterations:1\n"
+ "BM_string_strcat_half_copy_half_seek/65536/0/0/iterations:1\n"
+ "BM_string_strcpy/8/0/0/iterations:1\n"
+ "BM_string_strcpy/64/0/0/iterations:1\n"
+ "BM_string_strcpy/512/0/0/iterations:1\n"
+ "BM_string_strcpy/1024/0/0/iterations:1\n"
+ "BM_string_strcpy/8192/0/0/iterations:1\n"
+ "BM_string_strcpy/16384/0/0/iterations:1\n"
+ "BM_string_strcpy/32768/0/0/iterations:1\n"
+ "BM_string_strcpy/65536/0/0/iterations:1\n"
+ "BM_string_strcmp/8/0/0/iterations:1\n"
+ "BM_string_strcmp/64/0/0/iterations:1\n"
+ "BM_string_strcmp/512/0/0/iterations:1\n"
+ "BM_string_strcmp/1024/0/0/iterations:1\n"
+ "BM_string_strcmp/8192/0/0/iterations:1\n"
+ "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_time_clock_gettime/iterations:1\n"
+ "BM_time_clock_gettime_syscall/iterations:1\n"
+ "BM_time_gettimeofday/iterations:1\n"
+ "BM_time_gettimeofday_syscall/iterations:1\n"
+ "BM_time_time/iterations:1\n"
+ "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";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_full.xml",
+ "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, small) {
+ std::string expected =
+ "BM_string_memcmp/8/8/8\n"
+ "BM_math_sqrt\n"
+ "BM_property_get/1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_small.xml"});
+}
+
+TEST_F(SystemTests, medium) {
+ std::string expected =
+ "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"
+ "BM_string_memcmp/1024/0/0/iterations:1\n"
+ "BM_string_memcmp/8192/0/0/iterations:1\n"
+ "BM_string_memcmp/16384/0/0/iterations:1\n"
+ "BM_string_memcmp/32768/0/0/iterations:1\n"
+ "BM_string_memcmp/65536/0/0/iterations:1\n"
+ "BM_math_sqrt/iterations:1\n"
+ "BM_string_memcpy/512/4/4/iterations:25\n"
+ "BM_property_get/1/iterations:1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_medium.xml",
+ "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, from_each) {
+ std::string expected =
+ "BM_empty/iterations:1\n"
+ "BM_math_sqrt/iterations:1\n"
+ "BM_property_get/1/iterations:1\n"
+ "BM_pthread_self/iterations:1\n"
+ "BM_semaphore_sem_getvalue/iterations:1\n"
+ "BM_stdio_fread/64/iterations:1\n"
+ "BM_string_memcpy/512/4/4/iterations:1\n"
+ "BM_time_clock_gettime/iterations:1\n"
+ "BM_unistd_getpid/iterations:1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_from_each.xml",
+ "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, cmd_args) {
+ std::string expected =
+ "BM_string_memcpy/8/8/8/iterations:1\n"
+ "BM_math_log10/iterations:1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy 8 8 8",
+ "--bionic_extra=BM_math_log10",
+ "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, cmd_args_no_iter) {
+ std::string expected =
+ "BM_string_memcpy/8/8/8\n"
+ "BM_math_log10\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy 8 8 8",
+ "--bionic_extra=BM_math_log10"});
+}
+
+TEST_F(SystemTests, xml_and_args) {
+ std::string expected =
+ "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"
+ "BM_string_memcmp/1024/0/0/iterations:1\n"
+ "BM_string_memcmp/8192/0/0/iterations:1\n"
+ "BM_string_memcmp/16384/0/0/iterations:1\n"
+ "BM_string_memcmp/32768/0/0/iterations:1\n"
+ "BM_string_memcmp/65536/0/0/iterations:1\n"
+ "BM_math_sqrt/iterations:1\n"
+ "BM_string_memcpy/512/4/4/iterations:25\n"
+ "BM_property_get/1/iterations:1\n"
+ "BM_string_memcpy/8/0/0/iterations:1\n"
+ "BM_string_memcpy/64/0/0/iterations:1\n"
+ "BM_string_memcpy/512/0/0/iterations:1\n"
+ "BM_string_memcpy/1024/0/0/iterations:1\n"
+ "BM_string_memcpy/8192/0/0/iterations:1\n"
+ "BM_string_memcpy/16384/0/0/iterations:1\n"
+ "BM_string_memcpy/32768/0/0/iterations:1\n"
+ "BM_string_memcpy/65536/0/0/iterations:1\n"
+ "BM_math_log10/iterations:1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_extra=BM_string_memcpy AT_ALIGNED_TWOBUF",
+ "--bionic_extra=BM_math_log10",
+ "--bionic_cpu -1",
+ "--bionic_xml=suites/test_medium.xml",
+ "--bionic_iterations=1"});
+}
+
+TEST_F(SystemTests, alignment) {
+ std::string expected =
+ "BM_string_memcmp/8/2/2/iterations:1\n"
+ "BM_string_memcmp/64/2/2/iterations:1\n"
+ "BM_string_memcmp/512/2/2/iterations:1\n"
+ "BM_string_memcmp/1024/2/2/iterations:1\n"
+ "BM_string_memcmp/8192/2/2/iterations:1\n"
+ "BM_string_memcmp/16384/2/2/iterations:1\n"
+ "BM_string_memcmp/32768/2/2/iterations:1\n"
+ "BM_string_memcmp/65536/2/2/iterations:1\n"
+ "BM_string_memcmp/8/4/4/iterations:1\n"
+ "BM_string_memcmp/64/4/4/iterations:1\n"
+ "BM_string_memcmp/512/4/4/iterations:1\n"
+ "BM_string_memcmp/1024/4/4/iterations:1\n"
+ "BM_string_memcmp/8192/4/4/iterations:1\n"
+ "BM_string_memcmp/16384/4/4/iterations:1\n"
+ "BM_string_memcmp/32768/4/4/iterations:1\n"
+ "BM_string_memcmp/65536/4/4/iterations:1\n"
+ "BM_string_memcmp/8/16/16/iterations:1\n"
+ "BM_string_memcmp/64/16/16/iterations:1\n"
+ "BM_string_memcmp/512/16/16/iterations:1\n"
+ "BM_string_memcmp/1024/16/16/iterations:1\n"
+ "BM_string_memcmp/8192/16/16/iterations:1\n"
+ "BM_string_memcmp/16384/16/16/iterations:1\n"
+ "BM_string_memcmp/32768/16/16/iterations:1\n"
+ "BM_string_memcmp/65536/16/16/iterations:1\n"
+ "BM_string_memcmp/8/512/512/iterations:1\n"
+ "BM_string_memcmp/64/512/512/iterations:1\n"
+ "BM_string_memcmp/512/512/512/iterations:1\n"
+ "BM_string_memcmp/1024/512/512/iterations:1\n"
+ "BM_string_memcmp/8192/512/512/iterations:1\n"
+ "BM_string_memcmp/16384/512/512/iterations:1\n"
+ "BM_string_memcmp/32768/512/512/iterations:1\n"
+ "BM_string_memcmp/65536/512/512/iterations:1\n"
+ "BM_string_memcmp/8/2048/2048/iterations:1\n"
+ "BM_string_memcmp/64/2048/2048/iterations:1\n"
+ "BM_string_memcmp/512/2048/2048/iterations:1\n"
+ "BM_string_memcmp/1024/2048/2048/iterations:1\n"
+ "BM_string_memcmp/8192/2048/2048/iterations:1\n"
+ "BM_string_memcmp/16384/2048/2048/iterations:1\n"
+ "BM_string_memcmp/32768/2048/2048/iterations:1\n"
+ "BM_string_memcmp/65536/2048/2048/iterations:1\n"
+ "BM_string_strlen/8/2/iterations:1\n"
+ "BM_string_strlen/64/2/iterations:1\n"
+ "BM_string_strlen/512/2/iterations:1\n"
+ "BM_string_strlen/1024/2/iterations:1\n"
+ "BM_string_strlen/8192/2/iterations:1\n"
+ "BM_string_strlen/16384/2/iterations:1\n"
+ "BM_string_strlen/32768/2/iterations:1\n"
+ "BM_string_strlen/65536/2/iterations:1\n"
+ "BM_string_strlen/8/4/iterations:1\n"
+ "BM_string_strlen/64/4/iterations:1\n"
+ "BM_string_strlen/512/4/iterations:1\n"
+ "BM_string_strlen/1024/4/iterations:1\n"
+ "BM_string_strlen/8192/4/iterations:1\n"
+ "BM_string_strlen/16384/4/iterations:1\n"
+ "BM_string_strlen/32768/4/iterations:1\n"
+ "BM_string_strlen/65536/4/iterations:1\n"
+ "BM_string_strlen/8/16/iterations:1\n"
+ "BM_string_strlen/64/16/iterations:1\n"
+ "BM_string_strlen/512/16/iterations:1\n"
+ "BM_string_strlen/1024/16/iterations:1\n"
+ "BM_string_strlen/8192/16/iterations:1\n"
+ "BM_string_strlen/16384/16/iterations:1\n"
+ "BM_string_strlen/32768/16/iterations:1\n"
+ "BM_string_strlen/65536/16/iterations:1\n"
+ "BM_string_strlen/8/512/iterations:1\n"
+ "BM_string_strlen/64/512/iterations:1\n"
+ "BM_string_strlen/512/512/iterations:1\n"
+ "BM_string_strlen/1024/512/iterations:1\n"
+ "BM_string_strlen/8192/512/iterations:1\n"
+ "BM_string_strlen/16384/512/iterations:1\n"
+ "BM_string_strlen/32768/512/iterations:1\n"
+ "BM_string_strlen/65536/512/iterations:1\n"
+ "BM_string_strlen/8/2048/iterations:1\n"
+ "BM_string_strlen/64/2048/iterations:1\n"
+ "BM_string_strlen/512/2048/iterations:1\n"
+ "BM_string_strlen/1024/2048/iterations:1\n"
+ "BM_string_strlen/8192/2048/iterations:1\n"
+ "BM_string_strlen/16384/2048/iterations:1\n"
+ "BM_string_strlen/32768/2048/iterations:1\n"
+ "BM_string_strlen/65536/2048/iterations:1\n";
+ Verify(expected, 0, std::vector<const char *>{"--bionic_xml=suites/test_alignment.xml",
+ "--bionic_iterations=100"});
+}
diff --git a/benchmarks/time_benchmark.cpp b/benchmarks/time_benchmark.cpp
index c90dfadce..4c6d5ddf2 100644
--- a/benchmarks/time_benchmark.cpp
+++ b/benchmarks/time_benchmark.cpp
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <benchmark/benchmark.h>
+#include "util.h"
static void BM_time_clock_gettime(benchmark::State& state) {
timespec t;
@@ -27,7 +28,7 @@ static void BM_time_clock_gettime(benchmark::State& state) {
clock_gettime(CLOCK_MONOTONIC, &t);
}
}
-BENCHMARK(BM_time_clock_gettime);
+BIONIC_BENCHMARK(BM_time_clock_gettime);
static void BM_time_clock_gettime_syscall(benchmark::State& state) {
timespec t;
@@ -35,7 +36,7 @@ static void BM_time_clock_gettime_syscall(benchmark::State& state) {
syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &t);
}
}
-BENCHMARK(BM_time_clock_gettime_syscall);
+BIONIC_BENCHMARK(BM_time_clock_gettime_syscall);
static void BM_time_gettimeofday(benchmark::State& state) {
timeval tv;
@@ -43,7 +44,7 @@ static void BM_time_gettimeofday(benchmark::State& state) {
gettimeofday(&tv, nullptr);
}
}
-BENCHMARK(BM_time_gettimeofday);
+BIONIC_BENCHMARK(BM_time_gettimeofday);
void BM_time_gettimeofday_syscall(benchmark::State& state) {
timeval tv;
@@ -51,14 +52,14 @@ void BM_time_gettimeofday_syscall(benchmark::State& state) {
syscall(__NR_gettimeofday, &tv, nullptr);
}
}
-BENCHMARK(BM_time_gettimeofday_syscall);
+BIONIC_BENCHMARK(BM_time_gettimeofday_syscall);
void BM_time_time(benchmark::State& state) {
while (state.KeepRunning()) {
time(nullptr);
}
}
-BENCHMARK(BM_time_time);
+BIONIC_BENCHMARK(BM_time_time);
void BM_time_localtime(benchmark::State& state) {
time_t t = time(nullptr);
@@ -66,7 +67,7 @@ void BM_time_localtime(benchmark::State& state) {
localtime(&t);
}
}
-BENCHMARK(BM_time_localtime);
+BIONIC_BENCHMARK(BM_time_localtime);
void BM_time_localtime_r(benchmark::State& state) {
time_t t = time(nullptr);
@@ -75,4 +76,4 @@ void BM_time_localtime_r(benchmark::State& state) {
localtime_r(&t, &tm);
}
}
-BENCHMARK(BM_time_localtime_r);
+BIONIC_BENCHMARK(BM_time_localtime_r);
diff --git a/benchmarks/unistd_benchmark.cpp b/benchmarks/unistd_benchmark.cpp
index b78d3eb61..98e885843 100644
--- a/benchmarks/unistd_benchmark.cpp
+++ b/benchmarks/unistd_benchmark.cpp
@@ -18,20 +18,21 @@
#include <unistd.h>
#include <benchmark/benchmark.h>
+#include "util.h"
static void BM_unistd_getpid(benchmark::State& state) {
while (state.KeepRunning()) {
getpid();
}
}
-BENCHMARK(BM_unistd_getpid);
+BIONIC_BENCHMARK(BM_unistd_getpid);
static void BM_unistd_getpid_syscall(benchmark::State& state) {
while (state.KeepRunning()) {
syscall(__NR_getpid);
}
}
-BENCHMARK(BM_unistd_getpid_syscall);
+BIONIC_BENCHMARK(BM_unistd_getpid_syscall);
#if defined(__BIONIC__)
@@ -43,7 +44,7 @@ static void BM_unistd_gettid(benchmark::State& state) {
gettid_fp();
}
}
-BENCHMARK(BM_unistd_gettid);
+BIONIC_BENCHMARK(BM_unistd_gettid);
#endif
@@ -52,6 +53,4 @@ void BM_unistd_gettid_syscall(benchmark::State& state) {
syscall(__NR_gettid);
}
}
-BENCHMARK(BM_unistd_gettid_syscall);
-
-BENCHMARK_MAIN()
+BIONIC_BENCHMARK(BM_unistd_gettid_syscall);
diff --git a/benchmarks/util.cpp b/benchmarks/util.cpp
index d9641cfa4..9afca6f7e 100644
--- a/benchmarks/util.cpp
+++ b/benchmarks/util.cpp
@@ -19,11 +19,11 @@
#include <sched.h>
#include <stdio.h>
#include <string.h>
+
#include <cstdlib>
-#include <vector>
// This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
-char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask) {
+char* GetAlignedMemory(char* orig_ptr, size_t alignment, size_t or_mask) {
if ((alignment & (alignment - 1)) != 0) {
fprintf(stderr, "warning: alignment passed into GetAlignedMemory is not a power of two.\n");
std::abort();
@@ -44,12 +44,12 @@ char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask) {
return reinterpret_cast<char*>(ptr);
}
-char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes) {
+char* GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes) {
buf->resize(nbytes + 3 * alignment);
return GetAlignedMemory(buf->data(), alignment, 0);
}
-char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
+char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte) {
char* buf_aligned = GetAlignedPtr(buf, alignment, nbytes);
memset(buf_aligned, fill_byte, nbytes);
return buf_aligned;
@@ -64,7 +64,7 @@ bool LockToCPU(int) {
#else
-bool LockToCPU(int cpu_to_lock) {
+bool LockToCPU(long cpu_to_lock) {
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
@@ -81,7 +81,7 @@ bool LockToCPU(int cpu_to_lock) {
}
}
} else if (!CPU_ISSET(cpu_to_lock, &cpuset)) {
- printf("Cpu %d does not exist.\n", cpu_to_lock);
+ printf("Cpu %ld does not exist.\n", cpu_to_lock);
return false;
}
diff --git a/benchmarks/util.h b/benchmarks/util.h
index bd3d51588..c8c39e315 100644
--- a/benchmarks/util.h
+++ b/benchmarks/util.h
@@ -17,15 +17,43 @@
#ifndef _BIONIC_BENCHMARKS_UTIL_H_
#define _BIONIC_BENCHMARKS_UTIL_H_
+#include <map>
+#include <mutex>
+#include <string>
#include <vector>
+typedef void (*benchmark_func_t) (void);
+
+extern std::mutex g_map_lock;
+
+extern std::map<std::string, benchmark_func_t> g_str_to_func;
+
+static int __attribute__((unused)) EmplaceBenchmark (std::string fn_name, benchmark_func_t fn_ptr) {
+ g_map_lock.lock();
+ g_str_to_func.emplace(std::string(fn_name), fn_ptr);
+ g_map_lock.unlock();
+ return 0;
+}
+
+#define BIONIC_BENCHMARK(n) \
+ int _bionic_benchmark_##n __attribute__((unused)) = EmplaceBenchmark(std::string(#n), reinterpret_cast<benchmark_func_t>(n))
+
+constexpr auto KB = 1024;
+
+typedef struct {
+ long cpu_to_lock;
+ long num_iterations;
+ std::string xmlpath;
+ std::vector<std::string> extra_benchmarks;
+} bench_opts_t;
+
// This function returns a pointer less than 2 * alignment + or_mask bytes into the array.
-char *GetAlignedMemory(char *orig_ptr, size_t alignment, size_t or_mask);
+char* GetAlignedMemory(char* orig_ptr, size_t alignment, size_t or_mask);
-char *GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
+char* GetAlignedPtr(std::vector<char>* buf, size_t alignment, size_t nbytes);
-char *GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
+char* GetAlignedPtrFilled(std::vector<char>* buf, size_t alignment, size_t nbytes, char fill_byte);
-bool LockToCPU(int cpu_to_lock);
+bool LockToCPU(long cpu_to_lock);
#endif // _BIONIC_BENCHMARKS_UTIL_H