Merge "Add read/write perf tests for BlobStore." into tm-dev

This commit is contained in:
TreeHugger Robot
2022-03-28 05:03:53 +00:00
committed by Android (Google) Code Review
4 changed files with 156 additions and 29 deletions

View File

@@ -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",
}

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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());