Add vsock RPC Binder roundtrip microbenchmark
Knowing how long it takes for a VM to reply to a request is a useful
metric to track. Add a microbenchmark that adds two ints many, many
times and measure the individual response times.
Test: atest MicrodroidBenchmarkApp
Change-Id: I533fcc2587fda029da35ecbcde17152e6a40b9fc
diff --git a/tests/aidl/com/android/microdroid/testservice/IBenchmarkService.aidl b/tests/aidl/com/android/microdroid/testservice/IBenchmarkService.aidl
index c8c8660..1eda67e 100644
--- a/tests/aidl/com/android/microdroid/testservice/IBenchmarkService.aidl
+++ b/tests/aidl/com/android/microdroid/testservice/IBenchmarkService.aidl
@@ -41,4 +41,7 @@
/** Runs the vsock server on VM and receives data. */
void runVsockServerAndReceiveData(int serverFd, int numBytesToReceive);
+
+ /** Adds two numbers and returns the result. */
+ int add(int a, int b);
}
diff --git a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
index e979f30..a81d817 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -57,6 +57,7 @@
import java.util.List;
import java.util.Map;
import java.util.OptionalLong;
+import java.util.Random;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
@@ -566,4 +567,66 @@
}
}
}
+
+ @Test
+ public void testVsockRpcBinderLatency() throws Exception {
+ VirtualMachineConfig config =
+ newVmConfigBuilder()
+ .setPayloadConfigPath("assets/vm_config_io.json")
+ .setDebugLevel(DEBUG_LEVEL_NONE)
+ .build();
+
+ List<Double> requestLatencies = new ArrayList<>(IO_TEST_TRIAL_COUNT);
+ for (int i = 0; i < IO_TEST_TRIAL_COUNT; ++i) {
+ String vmName = "test_vm_request_" + i;
+ VirtualMachine vm = forceCreateNewVirtualMachine(vmName, config);
+ BenchmarkVmListener.create(new VsockRpcBinderLatencyListener(requestLatencies))
+ .runToFinish(TAG, vm);
+ }
+ reportMetrics(requestLatencies, "vsock/rpcbinder/request_latency", "ms");
+ }
+
+ private static class VsockRpcBinderLatencyListener
+ implements BenchmarkVmListener.InnerListener {
+ private static final int NUM_REQUESTS = 10000;
+ private static final int NUM_WARMUP_REQUESTS = 10;
+
+ private final List<Double> mResults;
+
+ VsockRpcBinderLatencyListener(List<Double> results) {
+ mResults = results;
+ }
+
+ @Override
+ public void onPayloadReady(VirtualMachine vm, IBenchmarkService benchmarkService)
+ throws RemoteException {
+ // Warm up a few times.
+ Random rand = new Random();
+ for (int i = 0; i < NUM_WARMUP_REQUESTS; i++) {
+ int a = rand.nextInt();
+ int b = rand.nextInt();
+ int c = benchmarkService.add(a, b);
+ assertThat(c).isEqualTo(a + b);
+ }
+
+ // Use the VM to compute Fibonnacci numbers, save timestamps between requests.
+ int a = 0;
+ int b = 1;
+ int c;
+ long timestamps[] = new long[NUM_REQUESTS + 1];
+ for (int i = 0; i < NUM_REQUESTS; i++) {
+ timestamps[i] = System.nanoTime();
+ c = benchmarkService.add(a, b);
+ a = b;
+ b = c;
+ }
+ timestamps[NUM_REQUESTS] = System.nanoTime();
+
+ // Log individual request latencies.
+ for (int i = 0; i < NUM_REQUESTS; i++) {
+ long diff = timestamps[i + 1] - timestamps[i];
+ mResults.add((double) diff / NANO_TO_MILLI);
+ }
+ }
+ }
}
diff --git a/tests/benchmark/src/native/benchmarkbinary.cpp b/tests/benchmark/src/native/benchmarkbinary.cpp
index 6cfc71d..022698f 100644
--- a/tests/benchmark/src/native/benchmarkbinary.cpp
+++ b/tests/benchmark/src/native/benchmarkbinary.cpp
@@ -96,6 +96,11 @@
return resultStatus(res);
}
+ ndk::ScopedAStatus add(int32_t a, int32_t b, int32_t* out) override {
+ *out = a + b;
+ return ndk::ScopedAStatus::ok();
+ }
+
private:
/**
* Measures the read rate for reading the given file.