Merge "AppLaunch: Update to support iorap compilations on go/perfmaster"

This commit is contained in:
Treehugger Robot
2020-03-17 23:00:56 +00:00
committed by Gerrit Code Review

View File

@@ -71,6 +71,7 @@ public class AppLaunch extends InstrumentationTestCase {
// with the app launch
private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
private static final String KEY_APPS = "apps";
private static final String KEY_IORAP_TRIAL_LAUNCH = "iorap_trial_launch";
private static final String KEY_TRIAL_LAUNCH = "trial_launch";
private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
private static final String KEY_LAUNCH_ORDER = "launch_order";
@@ -98,6 +99,9 @@ public class AppLaunch extends InstrumentationTestCase {
private static final int BEFORE_KILL_APP_SLEEP_TIMEOUT = 1000; // 1s before killing
private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 3000; // 3s between launching apps
private static final int PROFILE_SAVE_SLEEP_TIMEOUT = 1000; // Allow 1s for the profile to save
private static final int IORAP_TRACE_DURATION_TIMEOUT = 7000; // Allow 7s for trace to complete.
private static final int IORAP_TRIAL_LAUNCH_ITERATIONS = 3; // min 3 launches to merge traces.
private static final int IORAP_COMPILE_CMD_TIMEOUT = 600; // in seconds: 10 minutes
private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
private static final String LAUNCH_FILE = "applaunch.txt";
private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
@@ -106,6 +110,9 @@ public class AppLaunch extends InstrumentationTestCase {
private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
private static final String IORAP_TRIAL_LAUNCH = "IORAP_TRIAL_LAUNCH";
private static final String IORAP_TRIAL_LAUNCH_FIRST = "IORAP_TRIAL_LAUNCH_FIRST";
private static final String IORAP_TRIAL_LAUNCH_LAST = "IORAP_TRIAL_LAUNCH_LAST";
private static final String DELIMITER = ",";
private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
private static final String APP_LAUNCH_CMD = "am start -W -n";
@@ -119,6 +126,10 @@ public class AppLaunch extends InstrumentationTestCase {
private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
private static final String IORAP_COMPILE_CMD = "cmd jobscheduler run -f android 283673059";
private static final String IORAP_MAINTENANCE_CMD =
"iorap.cmd.maintenance --purge-package %s /data/misc/iorapd/sqlite.db";
private static final String IORAP_DUMPSYS_CMD = "dumpsys iorapd";
private static final String SPEED_PROFILE_FILTER = "speed-profile";
private static final String VERIFY_FILTER = "verify";
private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
@@ -138,6 +149,7 @@ public class AppLaunch extends InstrumentationTestCase {
private Bundle mResult = new Bundle();
private Set<String> mRequiredAccounts;
private boolean mTrialLaunch = false;
private boolean mIorapTrialLaunch = false;
private BufferedWriter mBufferedWriter = null;
private boolean mSimplePerfAppOnly = false;
private String[] mCompilerFilters = null;
@@ -145,6 +157,13 @@ public class AppLaunch extends InstrumentationTestCase {
private boolean mCycleCleanUp = false;
private boolean mTraceAll = false;
private boolean mIterationCycle = false;
enum IorapStatus {
UNDEFINED,
ENABLED,
DISABLED
}
private IorapStatus mIorapStatus = IorapStatus.UNDEFINED;
private long mCycleTime = 0;
private StringBuilder mCycleTimes = new StringBuilder();
@@ -243,7 +262,10 @@ public class AppLaunch extends InstrumentationTestCase {
setLaunchOrder();
for (LaunchOrder launch : mLaunchOrderList) {
dropCache();
toggleIorapStatus(launch.getIorapEnabled());
dropCache(/*override*/false);
Log.v(TAG, "Launch reason: " + launch.getLaunchReason());
// App launch times for trial launch will not be used for final
// launch time calculations.
@@ -289,6 +311,43 @@ public class AppLaunch extends InstrumentationTestCase {
compileApp(launch.getCompilerFilter(), appPkgName));
}
}
else if (launch.getLaunchReason().startsWith(IORAP_TRIAL_LAUNCH)) {
mIterationCycle = false;
// In the "applaunch.txt" file, iorap-trial launches is referenced using
// "IORAP_TRIAL_LAUNCH" or "IORAP_TRIAL_LAUNCH_LAST"
Intent startIntent = mNameToIntent.get(launch.getApp());
if (startIntent == null) {
Log.w(TAG, "App does not exist: " + launch.getApp());
mResult.putString(mNameToResultKey.get(launch.getApp()),
"App does not exist");
continue;
}
String appPkgName = startIntent.getComponent().getPackageName();
if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_FIRST)) {
// delete any iorap-traces associated with this package.
purgeIorapPackage(appPkgName);
}
dropCache(/*override*/true); // iorap-trial runs must have drop cache.
AppLaunchResult launchResult =
startApp(launch.getApp(), launch.getLaunchReason());
if (launchResult.mLaunchTime < 0) {
addLaunchResult(launch, new AppLaunchResult());
// simply pass the app if launch isn't successful
// error should have already been logged by startApp
continue;
}
// wait for slightly more than 5s (iorapd.perfetto.trace_duration_ms) for the trace buffers to complete.
sleep(IORAP_TRACE_DURATION_TIMEOUT);
if (launch.getLaunchReason().equals(IORAP_TRIAL_LAUNCH_LAST)) {
// run the iorap job scheduler and wait for iorap to compile fully.
assertTrue(String.format("Not able to iorap-compile the app : %s", appPkgName),
compileAppForIorap(appPkgName));
}
}
// App launch times used for final calculation
else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
@@ -437,6 +496,74 @@ public class AppLaunch extends InstrumentationTestCase {
}
}
/**
* Compile the app package using compilerFilter and return true or false
* based on status of the compilation command.
*/
private boolean compileAppForIorap(String appPkgName) throws IOException {
getInstrumentation().getUiAutomation().
executeShellCommand(IORAP_COMPILE_CMD);
for (int i = 0; i < IORAP_COMPILE_CMD_TIMEOUT; ++i) {
IorapCompilationStatus status = waitForIorapCompiled(appPkgName);
if (status == IorapCompilationStatus.COMPLETE) {
return true;
} else if (status == IorapCompilationStatus.INSUFFICIENT_TRACES) {
return false;
} // else INCOMPLETE. keep asking iorapd if it's done yet.
sleep(1000);
}
return false;
}
enum IorapCompilationStatus {
INCOMPLETE,
COMPLETE,
INSUFFICIENT_TRACES,
}
private IorapCompilationStatus waitForIorapCompiled(String appPkgName) throws IOException {
try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
executeShellCommand(IORAP_DUMPSYS_CMD);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
new FileInputStream(result.getFileDescriptor())))) {
String line;
String prevLine = "";
while ((line = bufferedReader.readLine()) != null) {
// Match the indented VersionedComponentName string.
// " com.google.android.deskclock/com.android.deskclock.DeskClock@62000712"
// Note: spaces are meaningful here.
if (prevLine.contains(" " + appPkgName) && prevLine.contains("@")) {
// pre-requisite:
// Compiled Status: Raw traces pending compilation (3)
if (line.contains("Compiled Status: Usable compiled trace")) {
return IorapCompilationStatus.COMPLETE;
} else if (line.contains("Compiled Status: ") &&
line.contains("more traces for compilation")) {
// Compiled Status: Need 1 more traces for compilation
// No amount of waiting will help here because there were
// insufficient traces made.
return IorapCompilationStatus.INSUFFICIENT_TRACES;
}
}
prevLine = line;
}
return IorapCompilationStatus.INCOMPLETE;
}
}
private String makeReasonForIorapTrialLaunch(int launchCount) {
String reason = IORAP_TRIAL_LAUNCH;
if (launchCount == 0) {
reason = IORAP_TRIAL_LAUNCH_FIRST;
}
if (launchCount == IORAP_TRIAL_LAUNCH_ITERATIONS - 1) {
reason = IORAP_TRIAL_LAUNCH_LAST;
}
return reason;
}
/**
* If launch order is "cyclic" then apps will be launched one after the
* other for each iteration count.
@@ -448,20 +575,31 @@ public class AppLaunch extends InstrumentationTestCase {
for (String compilerFilter : mCompilerFilters) {
if (mTrialLaunch) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
}
}
if (mIorapTrialLaunch) {
for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
for (String app : mNameToResultKey.keySet()) {
String reason = makeReasonForIorapTrialLaunch(launchCount);
mLaunchOrderList.add(
new LaunchOrder(app, compilerFilter,
reason,
/*iorapEnabled*/true));
}
}
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
String.format(LAUNCH_ITERATION, launchCount)));
String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
for (String app : mNameToResultKey.keySet()) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
String.format(TRACE_ITERATION, traceCount)));
String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -470,16 +608,25 @@ public class AppLaunch extends InstrumentationTestCase {
for (String compilerFilter : mCompilerFilters) {
for (String app : mNameToResultKey.keySet()) {
if (mTrialLaunch) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH, /*iorapEnabled*/false));
}
if (mIorapTrialLaunch) {
for (int launchCount = 0; launchCount < IORAP_TRIAL_LAUNCH_ITERATIONS; ++launchCount) {
String reason = makeReasonForIorapTrialLaunch(launchCount);
mLaunchOrderList.add(
new LaunchOrder(app, compilerFilter,
reason,
/*iorapEnabled*/true));
}
}
for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
String.format(LAUNCH_ITERATION, launchCount)));
String.format(LAUNCH_ITERATION, launchCount), mIorapTrialLaunch));
}
if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
String.format(TRACE_ITERATION, traceCount)));
String.format(TRACE_ITERATION, traceCount), mIorapTrialLaunch));
}
}
}
@@ -489,14 +636,92 @@ public class AppLaunch extends InstrumentationTestCase {
}
}
private void dropCache() {
if (mDropCache) {
private void dropCache(boolean override) {
if (mDropCache || override) {
assertNotNull("Issue in dropping the cache",
getInstrumentation().getUiAutomation()
.executeShellCommand(DROP_CACHE_SCRIPT));
}
}
// [[ $(adb shell whoami) == "root" ]]
private boolean checkIfRoot() throws IOException {
String total = "";
try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
executeShellCommand("whoami");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
new FileInputStream(result.getFileDescriptor())))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
total = total + line;
}
}
return total.contains("root");
}
// Delete all db rows and files associated with a package in iorapd.
// Effectively deletes any raw or compiled trace files, unoptimizing the package in iorap.
private void purgeIorapPackage(String packageName) {
try {
if (!checkIfRoot()) {
throw new AssertionError("must be root to toggle iorapd; try adb root?");
}
} catch (IOException e) {
throw new AssertionError(e);
}
getInstrumentation().getUiAutomation()
.executeShellCommand("stop iorapd");
sleep(100); // give iorapd enough time to stop.
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format(IORAP_MAINTENANCE_CMD, packageName));
Log.v(TAG, "Executed: " + String.format(IORAP_MAINTENANCE_CMD, packageName));
getInstrumentation().getUiAutomation()
.executeShellCommand("start iorapd");
sleep(2000); // give iorapd enough time to start up.
}
/**
* Toggle iorapd-based readahead and trace-collection.
* If iorapd is already enabled and enable is true, does nothing.
* If iorapd is already disabled and enable is false, does nothing.
*/
private void toggleIorapStatus(boolean enable) {
boolean currentlyEnabled = false;
Log.v(TAG, "toggleIorapStatus " + Boolean.toString(enable));
// Do nothing if we are already enabled or disabled.
if (mIorapStatus == IorapStatus.ENABLED && enable) {
return;
} else if (mIorapStatus == IorapStatus.DISABLED && !enable) {
return;
}
try {
if (!checkIfRoot()) {
throw new AssertionError("must be root to toggle iorapd; try adb root?");
}
} catch (IOException e) {
throw new AssertionError(e);
}
getInstrumentation().getUiAutomation()
.executeShellCommand("stop iorapd");
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.perfetto.enable %b", enable));
getInstrumentation().getUiAutomation()
.executeShellCommand(String.format("setprop iorapd.readahead.enable %b", enable));
getInstrumentation().getUiAutomation()
.executeShellCommand("start iorapd");
sleep(2000); // give enough time for iorapd to start back up.
if (enable) {
mIorapStatus = IorapStatus.ENABLED;
} else {
mIorapStatus = IorapStatus.DISABLED;
}
}
private void parseArgs(Bundle args) {
mNameToResultKey = new LinkedHashMap<String, String>();
mNameToLaunchTime = new HashMap<>();
@@ -560,6 +785,8 @@ public class AppLaunch extends InstrumentationTestCase {
mCycleCleanUp = Boolean.parseBoolean(args.getString(KEY_CYCLE_CLEAN));
mTraceAll = Boolean.parseBoolean(args.getString(KEY_TRACE_ALL));
mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
mIorapTrialLaunch = mIorapTrialLaunch ||
Boolean.parseBoolean(args.getString(KEY_IORAP_TRIAL_LAUNCH));
if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
@@ -738,11 +965,13 @@ public class AppLaunch extends InstrumentationTestCase {
private String mApp;
private String mCompilerFilter;
private String mLaunchReason;
private boolean mIorapEnabled;
LaunchOrder(String app, String compilerFilter, String launchReason){
LaunchOrder(String app, String compilerFilter, String launchReason, boolean iorapEnabled) {
mApp = app;
mCompilerFilter = compilerFilter;
mLaunchReason = launchReason;
mIorapEnabled = iorapEnabled;
}
public String getApp() {
@@ -764,6 +993,14 @@ public class AppLaunch extends InstrumentationTestCase {
public void setLaunchReason(String launchReason) {
mLaunchReason = launchReason;
}
public void setIorapEnabled(boolean iorapEnabled) {
mIorapEnabled = iorapEnabled;
}
public boolean getIorapEnabled() {
return mIorapEnabled;
}
}
private class AppLaunchResult {