blob: 8e0ea9888e4c18da2d1003787611e8a9ddc721a9 [file] [log] [blame]
Sudheer Shankad4ea5e12020-02-04 16:42:17 -08001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.perftests.blob;
17
18import android.app.blob.BlobStoreManager;
19import android.content.Context;
20import android.perftests.utils.ManualBenchmarkState;
21import android.perftests.utils.PerfManualStatusReporter;
22import android.perftests.utils.TraceMarkParser;
23import android.perftests.utils.TraceMarkParser.TraceMarkSlice;
24import android.support.test.uiautomator.UiDevice;
25
26import androidx.test.filters.LargeTest;
27import androidx.test.platform.app.InstrumentationRegistry;
28
29import com.android.utils.blob.DummyBlobData;
30
31import org.junit.After;
32import org.junit.Before;
33import org.junit.Rule;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.junit.runners.Parameterized;
37
38import java.io.IOException;
39import java.util.ArrayList;
40import java.util.Arrays;
41import java.util.Collection;
42import java.util.List;
43import java.util.concurrent.CompletableFuture;
44import java.util.concurrent.TimeUnit;
45
46@LargeTest
47@RunWith(Parameterized.class)
48public class BlobStorePerfTests {
49 // From frameworks/native/cmds/atrace/atrace.cpp
50 private static final String ATRACE_CATEGORY_SYSTEM_SERVER = "ss";
51 // From f/b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
52 private static final String ATRACE_COMPUTE_DIGEST_PREFIX = "computeBlobDigest-";
53
54 private Context mContext;
55 private BlobStoreManager mBlobStoreManager;
56 private AtraceUtils mAtraceUtils;
57 private ManualBenchmarkState mState;
58
59 @Rule
60 public PerfManualStatusReporter mPerfManualStatusReporter = new PerfManualStatusReporter();
61
62 @Parameterized.Parameter(0)
63 public int fileSizeInMb;
64
65 @Parameterized.Parameters(name = "{0}MB")
66 public static Collection<Object[]> getParameters() {
67 return Arrays.asList(new Object[][] {
68 { 25 },
69 { 50 },
70 { 100 },
71 { 200 },
72 });
73 }
74
75 @Before
76 public void setUp() {
77 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
78 mBlobStoreManager = (BlobStoreManager) mContext.getSystemService(
79 Context.BLOB_STORE_SERVICE);
80 mAtraceUtils = AtraceUtils.getInstance(InstrumentationRegistry.getInstrumentation());
81 mState = mPerfManualStatusReporter.getBenchmarkState();
82 }
83
84 @After
85 public void tearDown() {
86 // TODO: Add a blob_store shell command to trigger idle maintenance to avoid hardcoding
87 // job id like this.
88 // From BlobStoreConfig.IDLE_JOB_ID = 191934935.
89 runShellCommand("cmd jobscheduler run -f android 191934935");
90 }
91
92 @Test
93 public void testComputeDigest() throws Exception {
94 mAtraceUtils.startTrace(ATRACE_CATEGORY_SYSTEM_SERVER);
95 try {
96 final List<Long> durations = new ArrayList<>();
97 final DummyBlobData blobData = prepareDataBlob(fileSizeInMb);
98 final TraceMarkParser parser = new TraceMarkParser(
99 line -> line.name.startsWith(ATRACE_COMPUTE_DIGEST_PREFIX));
100 while (mState.keepRunning(durations)) {
101 commitBlob(blobData);
102
103 durations.clear();
104 collectDigestDurationsFromTrace(parser, durations);
Sudheer Shanka25bfe742020-02-06 10:29:10 -0800105 // TODO: get and delete blobId before next iteration.
Sudheer Shankad4ea5e12020-02-04 16:42:17 -0800106 }
107 } finally {
108 mAtraceUtils.stopTrace();
109 }
110 }
111
112 private void collectDigestDurationsFromTrace(TraceMarkParser parser, List<Long> durations) {
113 mAtraceUtils.performDump(parser, (key, slices) -> {
114 for (TraceMarkSlice slice : slices) {
115 durations.add(TimeUnit.MICROSECONDS.toNanos(slice.getDurationInMicroseconds()));
116 }
117 });
118 }
119
120 private DummyBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
121 final DummyBlobData blobData = new DummyBlobData(mContext,
122 fileSizeInMb * 1024 * 1024 /* bytes */);
123 blobData.prepare();
124 return blobData;
125 }
126
127 private void commitBlob(DummyBlobData blobData) throws Exception {
128 final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
129 try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
130 blobData.writeToSession(session);
131 final CompletableFuture<Integer> callback = new CompletableFuture<>();
132 session.commit(mContext.getMainExecutor(), callback::complete);
133 // Ignore commit callback result.
134 callback.get();
135 }
136 }
137
138 private String runShellCommand(String cmd) {
139 try {
140 return UiDevice.getInstance(
141 InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
142 } catch (IOException e) {
143 throw new RuntimeException(e);
144 }
145 }
146}