summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sudheer Shanka <sudheersai@google.com> 2022-03-23 19:36:13 -0700
committer Sudheer Shanka <sudheersai@google.com> 2022-03-26 17:21:38 -0700
commit02f0e25661b44d0dfcbda3e0460b9ca46d07d9c5 (patch)
tree094fe4570f140d260d260e1ee366718e34661394
parentd7b3be3e0bcc73f433725afc1f84e11a3567d555 (diff)
Add read/write perf tests for BlobStore.
These tests will help us understand the difference between local reads/writes vs blobstore reads/writes. Bug: 226954650 Test: atest ./apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java Change-Id: Ibcc8497b4c32e90824b89e836716bdeb7490227b
-rw-r--r--apct-tests/perftests/blobstore/Android.bp27
-rw-r--r--apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java119
-rw-r--r--tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java17
-rw-r--r--tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java22
4 files changed, 156 insertions, 29 deletions
diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp
index 25c4250729c4..9064b4494ed1 100644
--- a/apct-tests/perftests/blobstore/Android.bp
+++ b/apct-tests/perftests/blobstore/Android.bp
@@ -22,17 +22,18 @@ package {
}
android_test {
- name: "BlobStorePerfTests",
- srcs: ["src/**/*.java"],
- static_libs: [
- "BlobStoreTestUtils",
- "androidx.test.rules",
- "androidx.annotation_annotation",
- "apct-perftests-utils",
- "ub-uiautomator",
- "collector-device-lib-platform",
- ],
- platform_apis: true,
- test_suites: ["device-tests"],
- certificate: "platform",
+ name: "BlobStorePerfTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "BlobStoreTestUtils",
+ "androidx.test.rules",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ "ub-uiautomator",
+ "collector-device-lib-platform",
+ "androidx.benchmark_benchmark-macro",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
}
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index faf61a756170..665e986b91e5 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -15,15 +15,20 @@
*/
package com.android.perftests.blob;
+import static com.android.utils.blob.Utils.acquireLease;
+
import android.app.blob.BlobHandle;
import android.app.blob.BlobStoreManager;
import android.content.Context;
+import android.os.ParcelFileDescriptor;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.PerfManualStatusReporter;
import android.perftests.utils.TraceMarkParser;
import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
import android.support.test.uiautomator.UiDevice;
+import android.util.DataUnit;
+import androidx.benchmark.macro.MacrobenchmarkScope;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -36,12 +41,16 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.List;
+import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@@ -53,6 +62,8 @@ public class BlobStorePerfTests {
// From f/b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
private static final String ATRACE_COMPUTE_DIGEST_PREFIX = "computeBlobDigest-";
+ public static final int BUFFER_SIZE_BYTES = 16 * 1024;
+
private Context mContext;
private BlobStoreManager mBlobStoreManager;
private AtraceUtils mAtraceUtils;
@@ -85,6 +96,8 @@ public class BlobStorePerfTests {
@After
public void tearDown() {
+ mContext.getFilesDir().delete();
+ runShellCommand("cmd package clear " + mContext.getPackageName());
runShellCommand("cmd blob_store idle-maintenance");
}
@@ -109,6 +122,110 @@ public class BlobStorePerfTests {
}
}
+ @Test
+ public void testDirectReads() throws Exception {
+ final File file = new File(mContext.getDataDir(), "test_read_file");
+ final long sizeBytes = DataUnit.MEBIBYTES.toBytes(fileSizeInMb);
+ try (FileOutputStream outputStream = new FileOutputStream(file)) {
+ writeData(outputStream, sizeBytes);
+ }
+
+ long durationNs = 0;
+ while (mState.keepRunning(durationNs)) {
+ dropCache();
+ try (FileInputStream inputStream = new FileInputStream(file)) {
+ final long startTimeNs = System.nanoTime();
+ readData(inputStream, sizeBytes);
+ durationNs = System.nanoTime() - startTimeNs;
+ }
+ }
+ }
+
+ @Test
+ public void testBlobStoreReads() throws Exception {
+ final FakeBlobData blobData = prepareDataBlob(fileSizeInMb);
+ commitBlob(blobData);
+ acquireLease(mContext, blobData.getBlobHandle(), "Test Desc");
+ final long sizeBytes = DataUnit.MEBIBYTES.toBytes(fileSizeInMb);
+
+ long durationNs = 0;
+ while (mState.keepRunning(durationNs)) {
+ dropCache();
+ try (FileInputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(
+ mBlobStoreManager.openBlob(blobData.getBlobHandle()))) {
+ final long startTimeNs = System.nanoTime();
+ readData(inputStream, sizeBytes);
+ durationNs = System.nanoTime() - startTimeNs;
+ }
+ }
+
+ deleteBlob(blobData.getBlobHandle());
+ }
+
+ @Test
+ public void testDirectWrites() throws Exception {
+ final File file = new File(mContext.getDataDir(), "test_write_file");
+ final long sizeBytes = DataUnit.MEBIBYTES.toBytes(fileSizeInMb);
+
+ long durationNs = 0;
+ while (mState.keepRunning(durationNs)) {
+ file.delete();
+ dropCache();
+ try (FileOutputStream outputStream = new FileOutputStream(file)) {
+ final long startTimeNs = System.nanoTime();
+ writeData(outputStream, sizeBytes);
+ durationNs = System.nanoTime() - startTimeNs;
+ }
+ }
+ }
+
+ @Test
+ public void testBlobStoreWrites() throws Exception {
+ final FakeBlobData blobData = prepareDataBlob(fileSizeInMb);
+ final long sizeBytes = DataUnit.MEBIBYTES.toBytes(fileSizeInMb);
+
+ long durationNs = 0;
+ while (mState.keepRunning(durationNs)) {
+ final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
+ try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
+ dropCache();
+ try (FileOutputStream outputStream = new ParcelFileDescriptor
+ .AutoCloseOutputStream(session.openWrite(0, sizeBytes))) {
+ final long startTimeNs = System.nanoTime();
+ writeData(outputStream, sizeBytes);
+ durationNs = System.nanoTime() - startTimeNs;
+ }
+ }
+ mBlobStoreManager.abandonSession(sessionId);
+ }
+ }
+
+ private void readData(FileInputStream inputStream, long sizeBytes) throws Exception {
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ long bytesRead = 0;
+ while (bytesRead < sizeBytes) {
+ bytesRead += inputStream.read(buffer);
+ }
+ }
+
+ private void writeData(FileOutputStream outputStream, long sizeBytes) throws Exception {
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ long bytesWritten = 0;
+ final Random random = new Random(0);
+ while (bytesWritten < sizeBytes) {
+ random.nextBytes(buffer);
+ final int toWrite = (bytesWritten + buffer.length <= sizeBytes)
+ ? buffer.length : (int) (sizeBytes - bytesWritten);
+ outputStream.write(buffer, 0, toWrite);
+ bytesWritten += toWrite;
+ }
+ }
+
+ private void dropCache() {
+ final MacrobenchmarkScope scope = new MacrobenchmarkScope(mContext.getPackageName(), false);
+ scope.dropKernelPageCache();
+ }
+
private void collectDigestDurationsFromTrace(TraceMarkParser parser, List<Long> durations) {
mAtraceUtils.performDump(parser, (key, slices) -> {
for (TraceMarkSlice slice : slices) {
@@ -119,7 +236,7 @@ public class BlobStorePerfTests {
private FakeBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
final FakeBlobData blobData = new FakeBlobData.Builder(mContext)
- .setFileSize(fileSizeInMb * 1024 * 1024 /* bytes */)
+ .setFileSize(DataUnit.MEBIBYTES.toBytes(fileSizeInMb))
.build();
blobData.prepare();
return blobData;
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java
index 56db4f98e160..f4692983675d 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java
@@ -17,6 +17,7 @@ package com.android.utils.blob;
import static com.android.utils.blob.Utils.BUFFER_SIZE_BYTES;
import static com.android.utils.blob.Utils.copy;
+import static com.android.utils.blob.Utils.writeRandomData;
import static com.google.common.truth.Truth.assertThat;
@@ -123,7 +124,7 @@ public class FakeBlobData {
public void prepare() throws Exception {
try (RandomAccessFile file = new RandomAccessFile(mFile, "rw")) {
- writeRandomData(file, mFileSize);
+ writeRandomData(file, mRandom, mFileSize);
}
mFileDigest = FileUtils.digest(mFile, "SHA-256");
mExpiryTimeMs = System.currentTimeMillis() + mExpiryDurationMs;
@@ -239,18 +240,4 @@ public class FakeBlobData {
}
return digest.digest();
}
-
- private void writeRandomData(RandomAccessFile file, long fileSize)
- throws Exception {
- long bytesWritten = 0;
- final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
- while (bytesWritten < fileSize) {
- mRandom.nextBytes(buffer);
- final int toWrite = (bytesWritten + buffer.length <= fileSize)
- ? buffer.length : (int) (fileSize - bytesWritten);
- file.seek(bytesWritten);
- file.write(buffer, 0, toWrite);
- bytesWritten += toWrite;
- }
- }
}
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
index 2d230a74a477..f6c0e6dbcf22 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/Utils.java
@@ -30,11 +30,14 @@ import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.RandomAccessFile;
+import java.util.Random;
public class Utils {
public static final String TAG = "BlobStoreTest";
@@ -164,6 +167,25 @@ public class Utils {
runShellCmd("cmd blob_store idle-maintenance");
}
+ public static void writeRandomData(File file, long fileSizeBytes)
+ throws Exception {
+ writeRandomData(new RandomAccessFile(file, "rw"), new Random(0), fileSizeBytes);
+ }
+
+ public static void writeRandomData(RandomAccessFile file, Random random, long fileSizeBytes)
+ throws Exception {
+ long bytesWritten = 0;
+ final byte[] buffer = new byte[BUFFER_SIZE_BYTES];
+ while (bytesWritten < fileSizeBytes) {
+ random.nextBytes(buffer);
+ final int toWrite = (bytesWritten + buffer.length <= fileSizeBytes)
+ ? buffer.length : (int) (fileSizeBytes - bytesWritten);
+ file.seek(bytesWritten);
+ file.write(buffer, 0, toWrite);
+ bytesWritten += toWrite;
+ }
+ }
+
public static String runShellCmd(String cmd) throws IOException {
final UiDevice uiDevice = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation());