[benchmark][authfs] Add benchmarks for authfs remote file reading
This CL adds benchmarks for authfs remote files reading with or
without fs-verify verification.
Test: atest AuthFsBenchmarks
Bug: 236123069
Change-Id: I148977cab3bafcef5684898d285490764400710f
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java b/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java
new file mode 100644
index 0000000..0dd4613
--- /dev/null
+++ b/authfs/tests/java/src/com/android/fs/AuthFsBenchmarks.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package com.android.virt.fs;
+
+import static com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestMetrics;
+
+import android.platform.test.annotations.RootPermissionTest;
+
+import com.android.microdroid.test.common.MetricsProcessor;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.metrics.proto.MetricMeasurement.DataType;
+import com.android.tradefed.metrics.proto.MetricMeasurement.Measurements;
+import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@RootPermissionTest
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class AuthFsBenchmarks extends BaseHostJUnit4Test {
+ private static final int TRIAL_COUNT = 5;
+ private static final double NANO_SECS_PER_SEC = 1_000_000_000.;
+ private static final double INPUT_SIZE_IN_MB = 4.;
+
+ /** fs-verity digest (sha256) of testdata/input.4m */
+ private static final String DIGEST_4M =
+ "sha256-f18a268d565348fb4bbf11f10480b198f98f2922eb711de149857b3cecf98a8d";
+
+ @Rule public final AuthFsTestRule mAuthFsTestRule = new AuthFsTestRule();
+ @Rule public final TestMetrics mTestMetrics = new TestMetrics();
+ private MetricsProcessor mMetricsProcessor;
+
+ @BeforeClassWithInfo
+ public static void beforeClassWithDevice(TestInformation testInfo) throws Exception {
+ AuthFsTestRule.setUpClass(testInfo);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ String metricsPrefix =
+ MetricsProcessor.getMetricPrefix(
+ getDevice().getProperty("debug.hypervisor.metrics_tag"));
+ mMetricsProcessor = new MetricsProcessor(metricsPrefix + "authfs/");
+ }
+
+ @AfterClassWithInfo
+ public static void afterClassWithDevice(TestInformation testInfo)
+ throws DeviceNotAvailableException {
+ AuthFsTestRule.tearDownClass(testInfo);
+ }
+
+ @Test
+ public void seqReadRemoteFile() throws Exception {
+ List<Double> transferRates = new ArrayList<>(TRIAL_COUNT);
+ // Cache the file in memory for the host.
+ String cmd = "cat " + mAuthFsTestRule.TEST_DIR + "/input.4m > /dev/null";
+ mAuthFsTestRule.getAndroid().run(cmd);
+ for (int i = 0; i < TRIAL_COUNT + 1; ++i) {
+ mAuthFsTestRule.runFdServerOnAndroid(
+ "--open-ro 3:input.4m --open-ro 4:input.4m.fsv_meta", "--ro-fds 3:4");
+ mAuthFsTestRule.runAuthFsOnMicrodroid("--remote-ro-file 3:" + DIGEST_4M);
+ double elapsedSeconds = measureSeqReadOnMicrodroid("3");
+ transferRates.add(INPUT_SIZE_IN_MB / elapsedSeconds);
+ }
+ reportMetrics(transferRates, "seq_read", "mb_per_sec");
+ }
+
+ private double measureSeqReadOnMicrodroid(String filename) throws DeviceNotAvailableException {
+ String cmd = "cat " + mAuthFsTestRule.MOUNT_DIR + "/" + filename + " > /dev/null";
+ // Ideally, we should measure the time in the VM to avoid the adb and host tests latency.
+ double startTime = System.nanoTime();
+ mAuthFsTestRule.getMicrodroid().run(cmd);
+ double elapsedSeconds = (System.nanoTime() - startTime) / NANO_SECS_PER_SEC;
+ return elapsedSeconds;
+ }
+
+ private void reportMetrics(List<Double> metrics, String name, String unit) {
+ Map<String, Double> stats = mMetricsProcessor.computeStats(metrics, name, unit);
+ for (Map.Entry<String, Double> entry : stats.entrySet()) {
+ Metric metric =
+ Metric.newBuilder()
+ .setType(DataType.RAW)
+ .setMeasurements(
+ Measurements.newBuilder().setSingleDouble(entry.getValue()))
+ .build();
+ mTestMetrics.addTestMetric(entry.getKey(), metric);
+ }
+ }
+}
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java b/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
index 48c6b22..34a403e 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsTestRule.java
@@ -56,7 +56,7 @@
private static final String VM_CONFIG_PATH_IN_APK = "assets/vm_config.json";
/** Test directory on Android where data are located */
- private static final String TEST_DIR = "/data/local/tmp/authfs";
+ static final String TEST_DIR = "/data/local/tmp/authfs";
/** File name of the test APK */
private static final String TEST_APK_NAME = "MicrodroidTestApp.apk";
@@ -65,7 +65,7 @@
private static final String TEST_OUTPUT_DIR = "/data/local/tmp/authfs/output_dir";
/** Mount point of authfs on Microdroid during the test */
- private static final String MOUNT_DIR = "/data/local/tmp";
+ static final String MOUNT_DIR = "/data/local/tmp";
/** VM's log file */
private static final String LOG_PATH = TEST_OUTPUT_DIR + "/log.txt";