OSDN Git Service

Merge "Update binder benchmark to use google-benchmark" into nyc-dev
authorJulien Desprez <jdesprez@google.com>
Tue, 29 Mar 2016 18:55:25 +0000 (18:55 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Tue, 29 Mar 2016 18:55:26 +0000 (18:55 +0000)
tests/binder/benchmarks/Android.mk
tests/binder/benchmarks/binderAddInts.cpp

index eb2ead2..2a537cf 100644 (file)
@@ -37,4 +37,4 @@ LOCAL_C_INCLUDES += \
 LOCAL_MODULE := binderAddInts
 LOCAL_SRC_FILES := binderAddInts.cpp
 
-include $(BUILD_EXECUTABLE)
+include $(BUILD_NATIVE_BENCHMARK)
index f1b2e72..d0b2910 100644 (file)
  */
 
 /*
- * Binder add integers benchmark
+ * Binder add integers benchmark (Using google-benchmark library)
  *
- * Measures the rate at which a short binder IPC operation can be
- * performed.  The operation consists of the client sending a parcel
- * that contains two integers.  For each parcel that the server
- * receives, it adds the two integers and sends the sum back to
- * the client.
- *
- * This benchmark supports the following command-line options:
- *
- *   -c cpu - bind client to specified cpu (default: unbound)
- *   -s cpu - bind server to specified cpu (default: unbound)
- *   -n num - perform IPC operation num times (default: 1000)
- *   -d time - delay specified amount of seconds after each
- *             IPC operation. (default 1e-3)
  */
 
 #include <cerrno>
@@ -49,6 +36,9 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+
+#include <benchmark/benchmark.h>
+
 #include <utils/Log.h>
 #include <testUtil.h>
 
@@ -62,13 +52,11 @@ String16 serviceName("test.binderAddInts");
 struct options {
     int serverCPU;
     int clientCPU;
-    unsigned int iterations;
     float        iterDelay; // End of iteration delay in seconds
 } options = { // Set defaults
     unbound, // Server CPU
     unbound, // Client CPU
-    1000,    // Iterations
-    1e-3,    // End of iteration delay
+    0.0,    // End of iteration delay
 };
 
 class AddIntsService : public BBinder
@@ -89,152 +77,13 @@ class AddIntsService : public BBinder
     int cpu_;
 };
 
-struct Duration {
-    double value;
-    friend std::ostream& operator<<(std::ostream& stream, const Duration& d) {
-        static const char *SUFFIXES[] = {"s", "ms", "us", "ns"};
-        size_t suffix = 0;
-        double temp = d.value;
-        while (temp < .1 && suffix < 3) {
-            temp *= 1000;
-            suffix++;
-        }
-        stream << temp << SUFFIXES[suffix];
-        return stream;
-    }
-};
-
 // File scope function prototypes
 static bool server(void);
-static void client(void);
+static void BM_client(benchmark::State& state);
 static void bindCPU(unsigned int cpu);
 static ostream &operator<<(ostream &stream, const String16& str);
 static ostream &operator<<(ostream &stream, const cpu_set_t& set);
 
-int main(int argc, char *argv[])
-{
-    int rv;
-
-    // Determine CPUs available for use.
-    // This testcase limits its self to using CPUs that were
-    // available at the start of the benchmark.
-    cpu_set_t availCPUs;
-    if ((rv = sched_getaffinity(0, sizeof(availCPUs), &availCPUs)) != 0) {
-        cerr << "sched_getaffinity failure, rv: " << rv
-            << " errno: " << errno << endl;
-        exit(1);
-    }
-
-    // Parse command line arguments
-    int opt;
-    while ((opt = getopt(argc, argv, "s:c:n:d:?")) != -1) {
-        char *chptr; // character pointer for command-line parsing
-
-        switch (opt) {
-        case 'c': // client CPU
-        case 's': { // server CPU
-            // Parse the CPU number
-            int cpu = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                cerr << "Invalid cpu specified for -" << (char) opt
-                    << " option of: " << optarg << endl;
-                exit(2);
-            }
-
-            // Is the CPU available?
-            if (!CPU_ISSET(cpu, &availCPUs)) {
-                cerr << "CPU " << optarg << " not currently available" << endl;
-                cerr << "  Available CPUs: " << availCPUs << endl;
-                exit(3);
-            }
-
-            // Record the choice
-            *((opt == 'c') ? &options.clientCPU : &options.serverCPU) = cpu;
-            break;
-        }
-
-        case 'n': // iterations
-            options.iterations = strtoul(optarg, &chptr, 10);
-            if (*chptr != '\0') {
-                cerr << "Invalid iterations specified of: " << optarg << endl;
-                exit(4);
-            }
-            if (options.iterations < 1) {
-                cerr << "Less than 1 iteration specified by: "
-                    << optarg << endl;
-                exit(5);
-            }
-            break;
-
-        case 'd': // Delay between each iteration
-            options.iterDelay = strtod(optarg, &chptr);
-            if ((*chptr != '\0') || (options.iterDelay < 0.0)) {
-                cerr << "Invalid delay specified of: " << optarg << endl;
-                exit(6);
-            }
-            break;
-
-        case '?':
-        default:
-            cerr << basename(argv[0]) << " [options]" << endl;
-            cerr << "  options:" << endl;
-            cerr << "    -s cpu - server CPU number" << endl;
-            cerr << "    -c cpu - client CPU number" << endl;
-            cerr << "    -n num - iterations" << endl;
-            cerr << "    -d time - delay after operation in seconds" << endl;
-            exit(((optopt == 0) || (optopt == '?')) ? 0 : 7);
-        }
-    }
-
-    // Display selected options
-    cout << "serverCPU: ";
-    if (options.serverCPU == unbound) {
-        cout << " unbound";
-    } else {
-        cout << options.serverCPU;
-    }
-    cout << endl;
-    cout << "clientCPU: ";
-    if (options.clientCPU == unbound) {
-        cout << " unbound";
-    } else {
-        cout << options.clientCPU;
-    }
-    cout << endl;
-    cout << "iterations: " << options.iterations << endl;
-    cout << "iterDelay: " << options.iterDelay << endl;
-
-    // Fork client, use this process as server
-    fflush(stdout);
-    switch (pid_t pid = fork()) {
-    case 0: // Child
-        client();
-        return 0;
-
-    default: // Parent
-        if (!server()) { break; }
-
-        // Wait for all children to end
-        do {
-            int stat;
-            rv = wait(&stat);
-            if ((rv == -1) && (errno == ECHILD)) { break; }
-            if (rv == -1) {
-                cerr << "wait failed, rv: " << rv << " errno: "
-                    << errno << endl;
-                perror(NULL);
-                exit(8);
-            }
-        } while (1);
-        return 0;
-
-    case -1: // Error
-        exit(9);
-    }
-
-    return 0;
-}
-
 static bool server(void)
 {
     int rv;
@@ -254,12 +103,11 @@ static bool server(void)
     return true;
 }
 
-static void client(void)
+static void BM_client(benchmark::State& state)
 {
+    server();
     int rv;
     sp<IServiceManager> sm = defaultServiceManager();
-    double min = FLT_MAX, max = 0.0, total = 0.0; // Time in seconds for all
-                                                  // the IPC calls.
 
     // If needed bind to client CPU
     if (options.clientCPU != unbound) { bindCPU(options.clientCPU); }
@@ -278,38 +126,31 @@ static void client(void)
         return;
     }
 
-    // Perform the IPC operations
-    for (unsigned int iter = 0; iter < options.iterations; iter++) {
+    unsigned int iter = 0;
+    // Perform the IPC operations in the benchmark
+    while (state.KeepRunning()) {
         Parcel send, reply;
 
         // Create parcel to be sent.  Will use the iteration cound
         // and the iteration count + 3 as the two integer values
         // to be sent.
+        state.PauseTiming();
         int val1 = iter;
         int val2 = iter + 3;
         int expected = val1 + val2;  // Expect to get the sum back
         send.writeInt32(val1);
         send.writeInt32(val2);
-
+        state.ResumeTiming();
         // Send the parcel, while timing how long it takes for
         // the answer to return.
-        struct timespec start;
-        clock_gettime(CLOCK_MONOTONIC, &start);
         if ((rv = binder->transact(AddIntsService::ADD_INTS,
             send, &reply)) != 0) {
             cerr << "binder->transact failed, rv: " << rv
                 << " errno: " << errno << endl;
             exit(10);
         }
-        struct timespec current;
-        clock_gettime(CLOCK_MONOTONIC, &current);
-
-        // Calculate how long this operation took and update the stats
-        struct timespec deltaTimespec = tsDelta(&start, &current);
-        double delta = ts2double(&deltaTimespec);
-        min = (delta < min) ? delta : min;
-        max = (delta > max) ? delta : max;
-        total += delta;
+
+        state.PauseTiming();
         int result = reply.readInt32();
         if (result != (int) (iter + iter + 3)) {
             cerr << "Unexpected result for iteration " << iter << endl;
@@ -318,15 +159,11 @@ static void client(void)
         }
 
         if (options.iterDelay > 0.0) { testDelaySpin(options.iterDelay); }
+        state.ResumeTiming();
     }
-
-    // Display the results
-    cout << fixed << setprecision(2)
-        << "Time per iteration min: " << Duration{min}
-        << " avg: " << Duration{total / options.iterations}
-        << " max: " << Duration{max}
-        << endl;
 }
+BENCHMARK(BM_client);
+
 
 AddIntsService::AddIntsService(int cpu): cpu_(cpu) {
     if (cpu != unbound) { bindCPU(cpu); }
@@ -406,3 +243,68 @@ static ostream &operator<<(ostream &stream, const cpu_set_t& set)
 
     return stream;
 }
+
+int main(int argc, char *argv[])
+{
+    int rv;
+    ::benchmark::Initialize(&argc, argv);
+    // Determine CPUs available for use.
+    // This testcase limits its self to using CPUs that were
+    // available at the start of the benchmark.
+    cpu_set_t availCPUs;
+    if ((rv = sched_getaffinity(0, sizeof(availCPUs), &availCPUs)) != 0) {
+        cerr << "sched_getaffinity failure, rv: " << rv
+            << " errno: " << errno << endl;
+        exit(1);
+    }
+
+    // Parse command line arguments
+    int opt;
+    while ((opt = getopt(argc, argv, "s:c:d:?")) != -1) {
+        char *chptr; // character pointer for command-line parsing
+
+        switch (opt) {
+        case 'c': // client CPU
+        case 's': { // server CPU
+            // Parse the CPU number
+            int cpu = strtoul(optarg, &chptr, 10);
+            if (*chptr != '\0') {
+                cerr << "Invalid cpu specified for -" << (char) opt
+                    << " option of: " << optarg << endl;
+                exit(2);
+            }
+
+            // Is the CPU available?
+            if (!CPU_ISSET(cpu, &availCPUs)) {
+                cerr << "CPU " << optarg << " not currently available" << endl;
+                cerr << "  Available CPUs: " << availCPUs << endl;
+                exit(3);
+            }
+
+            // Record the choice
+            *((opt == 'c') ? &options.clientCPU : &options.serverCPU) = cpu;
+            break;
+        }
+
+        case 'd': // delay between each iteration
+            options.iterDelay = strtod(optarg, &chptr);
+            if ((*chptr != '\0') || (options.iterDelay < 0.0)) {
+                cerr << "Invalid delay specified of: " << optarg << endl;
+                exit(6);
+            }
+            break;
+
+        case '?':
+        default:
+            cerr << basename(argv[0]) << " [options]" << endl;
+            cerr << "  options:" << endl;
+            cerr << "    -s cpu - server CPU number" << endl;
+            cerr << "    -c cpu - client CPU number" << endl;
+            cerr << "    -d time - delay after operation in seconds" << endl;
+            exit(((optopt == 0) || (optopt == '?')) ? 0 : 7);
+        }
+    }
+
+    ::benchmark::RunSpecifiedBenchmarks();
+}
+