Merge "Orderly VM shutdown, part 1"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index cf90c76..33498d3 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -25,6 +25,9 @@
},
{
"name": "MicrodroidBenchmarkApp"
+ },
+ {
+ "name": "ComposBenchmarkApp"
}
],
"imports": [
diff --git a/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java b/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
index e4fb5ff..be9bb50 100644
--- a/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
+++ b/compos/benchmark/src/java/com/android/compos/benchmark/ComposBenchmark.java
@@ -24,7 +24,6 @@
import android.os.ParcelFileDescriptor;
import android.util.Log;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,7 +36,6 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.time.Duration;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -47,7 +45,9 @@
public class ComposBenchmark {
private static final String TAG = "ComposBenchmark";
private static final int BUFFER_SIZE = 1024;
- private static final int ROUND_COUNT = 10;
+ private static final int ROUND_COUNT = 5;
+ private static final double NANOS_IN_SEC = 1_000_000_000.0;
+ private static final String METRIC_PREFIX = "avf_perf/compos/";
private Instrumentation mInstrumentation;
@@ -56,9 +56,29 @@
mInstrumentation = getInstrumentation();
}
- @After
- public void cleanup() {
+ private void reportMetric(String name, String unit, double[] values) {
+ double sum = 0;
+ double squareSum = 0;
+ double min = Double.MAX_VALUE;
+ double max = Double.MIN_VALUE;
+ for (double val : values) {
+ sum += val;
+ squareSum += val * val;
+ min = val < min ? val : min;
+ max = val > max ? val : max;
+ }
+
+ double average = sum / values.length;
+ double variance = squareSum / values.length - average * average;
+ double stdev = Math.sqrt(variance);
+
+ Bundle bundle = new Bundle();
+ bundle.putDouble(METRIC_PREFIX + name + "_average_" + unit, average);
+ bundle.putDouble(METRIC_PREFIX + name + "_min_" + unit, min);
+ bundle.putDouble(METRIC_PREFIX + name + "_max_" + unit, max);
+ bundle.putDouble(METRIC_PREFIX + name + "_stdev_" + unit, stdev);
+ mInstrumentation.sendStatus(0, bundle);
}
public byte[] executeCommandBlocking(String command) {
@@ -98,34 +118,25 @@
}
@Test
- public void testCompilationInVM()
- throws InterruptedException, IOException {
+ public void testGuestCompileTime() throws InterruptedException, IOException {
final String command = "/apex/com.android.compos/bin/composd_cmd test-compile";
- Long[] compileSecArray = new Long[ROUND_COUNT];
+ double[] compileTime = new double[ROUND_COUNT];
for (int round = 0; round < ROUND_COUNT; ++round) {
Long compileStartTime = System.nanoTime();
String output = executeCommand(command);
Long compileEndTime = System.nanoTime();
- Long compileSec = Duration.ofNanos(compileEndTime - compileStartTime).getSeconds();
Pattern pattern = Pattern.compile("All Ok");
Matcher matcher = pattern.matcher(output);
assertTrue(matcher.find());
- compileSecArray[round] = compileSec;
+ compileTime[round] = (compileEndTime - compileStartTime) / NANOS_IN_SEC;
}
- Long compileSecSum = 0L;
- for (Long num: compileSecArray) {
- compileSecSum += num;
- }
-
- Bundle bundle = new Bundle();
- bundle.putLong("compliation_in_vm_elapse_second", compileSecSum / compileSecArray.length);
- mInstrumentation.sendStatus(0, bundle);
+ reportMetric("guest_compile_time", "s", compileTime);
}
private Timestamp getLatestDex2oatSuccessTime()
@@ -133,7 +144,7 @@
final String command = "logcat -d -e dex2oat";
String output = executeCommand(command);
- String latestTime = "";
+ String latestTime = null;
for (String line : output.split("[\r\n]+")) {
Pattern pattern = Pattern.compile("dex2oat64: dex2oat took");
@@ -143,6 +154,10 @@
}
}
+ if (latestTime == null) {
+ return null;
+ }
+
DateFormat formatter = new SimpleDateFormat("MM-dd hh:mm:ss.SSS");
Date date = formatter.parse(latestTime);
Timestamp timeStampDate = new Timestamp(date.getTime());
@@ -151,35 +166,28 @@
}
@Test
- public void testCompilationInAndroid()
+ public void testHostCompileTime()
throws InterruptedException, IOException, ParseException {
final String command = "/apex/com.android.art/bin/odrefresh --force-compile";
- Long[] compileSecArray = new Long[ROUND_COUNT];
+ double[] compileTime = new double[ROUND_COUNT];
for (int round = 0; round < ROUND_COUNT; ++round) {
Timestamp beforeCompileLatestTime = getLatestDex2oatSuccessTime();
Long compileStartTime = System.nanoTime();
String output = executeCommand(command);
Long compileEndTime = System.nanoTime();
- Long compileSec = Duration.ofNanos(compileEndTime - compileStartTime).getSeconds();
Timestamp afterCompileLatestTime = getLatestDex2oatSuccessTime();
- assertTrue(beforeCompileLatestTime.before(afterCompileLatestTime));
+ assertTrue(afterCompileLatestTime != null);
+ assertTrue(beforeCompileLatestTime == null
+ || beforeCompileLatestTime.before(afterCompileLatestTime));
- compileSecArray[round] = compileSec;
+ compileTime[round] = (compileEndTime - compileStartTime) / NANOS_IN_SEC;
}
- Long compileSecSum = 0L;
- for (Long num: compileSecArray) {
- compileSecSum += num;
- }
-
- Bundle bundle = new Bundle();
- bundle.putLong("compliation_in_android_elapse_second",
- compileSecSum / compileSecArray.length);
- mInstrumentation.sendStatus(0, bundle);
+ reportMetric("host_compile_time", "s", compileTime);
}
}
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 e96f58b..625b638 100644
--- a/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
+++ b/tests/benchmark/src/java/com/android/microdroid/benchmark/MicrodroidBenchmarks.java
@@ -37,7 +37,9 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
@RunWith(Parameterized.class)
public class MicrodroidBenchmarks extends MicrodroidDeviceTestBase {
@@ -47,6 +49,11 @@
private static final String KERNEL_VERSION = SystemProperties.get("ro.kernel.version");
+ private static final String APEX_ETC_FS = "/apex/com.android.virt/etc/fs/";
+ private static final double SIZE_MB = 1024.0 * 1024.0;
+ private static final String MICRODROID_IMG_PREFIX = "microdroid_";
+ private static final String MICRODROID_IMG_SUFFIX = ".img";
+
private boolean isCuttlefish() {
String productName = SystemProperties.get("ro.product.name");
return (null != productName)
@@ -85,7 +92,7 @@
VirtualMachineConfig.Builder builder =
mInner.newVmConfigBuilder("assets/vm_config.json");
VirtualMachineConfig normalConfig =
- builder.debugLevel(DebugLevel.FULL).memoryMib(mem).build();
+ builder.debugLevel(DebugLevel.NONE).memoryMib(mem).build();
mInner.forceCreateNewVirtualMachine("test_vm_minimum_memory", normalConfig);
if (tryBootVm(TAG, "test_vm_minimum_memory").payloadStarted) return true;
@@ -159,4 +166,23 @@
bundle.putDouble("avf_perf/microdroid/boot_time_stdev_ms", stdev);
mInstrumentation.sendStatus(0, bundle);
}
+
+ @Test
+ public void testMicrodroidImageSize() throws IOException {
+ Bundle bundle = new Bundle();
+ for (File file : new File(APEX_ETC_FS).listFiles()) {
+ String name = file.getName();
+
+ if (!name.startsWith(MICRODROID_IMG_PREFIX) || !name.endsWith(MICRODROID_IMG_SUFFIX)) {
+ continue;
+ }
+
+ String base = name.substring(MICRODROID_IMG_PREFIX.length(),
+ name.length() - MICRODROID_IMG_SUFFIX.length());
+ String metric = "avf_perf/microdroid/img_size_" + base + "_MB";
+ double size = Files.size(file.toPath()) / SIZE_MB;
+ bundle.putDouble(metric, size);
+ }
+ mInstrumentation.sendStatus(0, bundle);
+ }
}
diff --git a/tests/vsock_guest.cc b/tests/vsock_guest.cc
index 7a72e11..884c8a4 100644
--- a/tests/vsock_guest.cc
+++ b/tests/vsock_guest.cc
@@ -62,6 +62,16 @@
PLOG(ERROR) << "WriteStringToFd";
return EXIT_FAILURE;
}
+ shutdown(fd.get(), SHUT_WR); // close socket for writing
+
+ // Must not shut down until the server ACKs the message. Shutting down
+ // the VM would otherwise terminate the VMM and reset the server's socket.
+ LOG(INFO) << "Waiting for ACK from the server...";
+ if (!ReadFdToString(fd, &msg)) {
+ PLOG(ERROR) << "ReadFdToString";
+ return EXIT_FAILURE;
+ }
+ shutdown(fd.get(), SHUT_RD); // close socket for reading
LOG(INFO) << "Exiting...";
return EXIT_SUCCESS;
diff --git a/tests/vsock_test.cc b/tests/vsock_test.cc
index 0fc451d..1460660 100644
--- a/tests/vsock_test.cc
+++ b/tests/vsock_test.cc
@@ -48,6 +48,7 @@
static constexpr const char kVmInitrdPath[] = "/data/local/tmp/virt-test/initramfs";
static constexpr const char kVmParams[] = "rdinit=/bin/init bin/vsock_client 2 45678 HelloWorld";
static constexpr const char kTestMessage[] = "HelloWorld";
+static constexpr const char kAckMessage[] = "ACK";
static constexpr const char kPlatformVersion[] = "~1.0";
/** Returns true if the kernel supports unprotected VMs. */
@@ -108,9 +109,13 @@
LOG(INFO) << "Reading message from the client...";
std::string msg;
- ASSERT_TRUE(ReadFdToString(client_fd, &msg));
-
+ ASSERT_TRUE(ReadFdToString(client_fd, &msg)) << strerror(errno);
LOG(INFO) << "Received message: " << msg;
+
+ // The client is waiting for a response to signal it can shut down.
+ LOG(INFO) << "Replying with '" << kAckMessage << "'...";
+ ASSERT_TRUE(WriteStringToFd(kAckMessage, client_fd));
+
ASSERT_EQ(msg, kTestMessage);
}