SimpleperfListener: Map symbols to easy to read keys
Also divide any reported event count by test iterations.
Bug: 230039226
Test: atest SimpleperfListenerTest
Change-Id: I7f0d5a6fe716b933de95d438dd68104d59c2be5c
diff --git a/libraries/collectors-helper/simpleperf/src/com/android/helpers/SimpleperfHelper.java b/libraries/collectors-helper/simpleperf/src/com/android/helpers/SimpleperfHelper.java
index e6a6f30..5f62982 100644
--- a/libraries/collectors-helper/simpleperf/src/com/android/helpers/SimpleperfHelper.java
+++ b/libraries/collectors-helper/simpleperf/src/com/android/helpers/SimpleperfHelper.java
@@ -180,8 +180,8 @@
public Map<String /*event-process-symbol*/, String /*eventCount*/> getSimpleperfReport(
String path,
Map.Entry<String, String> processToPid,
- String[] symbols,
- String metricsPrefix) {
+ Map<String, String> symbols,
+ int testIterations) {
try {
String reportCommand =
String.format(
@@ -190,7 +190,7 @@
path, processToPid.getValue(), SIMPLEPERF_REPORT_TMP_FILE_PATH);
Log.i(LOG_TAG, String.format("Report command: %s", reportCommand));
mUiDevice.executeShellCommand(reportCommand);
- return getMetrics(processToPid.getKey(), symbols, metricsPrefix);
+ return getMetrics(processToPid.getKey(), symbols, testIterations);
} catch (IOException e) {
Log.e(LOG_TAG, "Could not generate report: " + e.getMessage());
}
@@ -202,10 +202,10 @@
*
* @param process Individually extracted processes recorded in binary record file.
* @param symbols Symbols to report events from the processes recorded.
- * @param metricsPrefix
* @return Map containing recorded event counts from symbols within process
*/
- private Map<String, String> getMetrics(String process, String[] symbols, String metricsPrefix) {
+ private Map<String, String> getMetrics(
+ String process, Map<String, String> symbols, int testIterations) {
Map<String, String> results = new HashMap<>();
try {
String eventName = "";
@@ -220,8 +220,9 @@
if (splitLine[0].equals("Event")) {
eventName = splitLine[1].split(" ")[0];
} else if (splitLine[0].equals("Event count")) {
- String key = String.join("-", metricsPrefix, process, eventName);
- results.put(key, splitLine[1]);
+ String key = String.join("-", process, eventName);
+ long count = Long.parseLong(splitLine[1]) / testIterations;
+ results.put(key, String.valueOf(count));
}
}
// Parsing lines for specific symbols in report to store with event count to results
@@ -234,7 +235,7 @@
if (matchedSymbol == null) {
continue;
}
- String key = String.join("-", metricsPrefix, process, matchedSymbol, eventName);
+ String key = String.join("-", process, matchedSymbol, eventName);
if (results.containsKey(key + "-percentage")) {
// We are searching for symbols with partial matches so only include the
// first hit if we get multiple matches.
@@ -245,7 +246,8 @@
String percentage = splitLine[0].substring(0, splitLine[0].length() - 1);
results.put(key + "-percentage", percentage);
String eventCount = splitLine[2].trim();
- results.put(key + "-eventCount", eventCount);
+ long count = Long.parseLong(eventCount) / testIterations;
+ results.put(key + "-count", String.valueOf(count));
}
}
} catch (Exception e) {
@@ -254,10 +256,10 @@
return results;
}
- private static String getMatchingSymbol(String[] symbols, String parsedSymbol) {
- for (String candidate : symbols) {
+ private static String getMatchingSymbol(Map<String, String> symbols, String parsedSymbol) {
+ for (String candidate : symbols.keySet()) {
if (parsedSymbol.contains(candidate)) {
- return candidate;
+ return symbols.get(candidate);
}
}
return null;
diff --git a/libraries/device-collectors/src/main/java/android/device/collectors/SimpleperfListener.java b/libraries/device-collectors/src/main/java/android/device/collectors/SimpleperfListener.java
index a53d68f..1cbc8a0 100644
--- a/libraries/device-collectors/src/main/java/android/device/collectors/SimpleperfListener.java
+++ b/libraries/device-collectors/src/main/java/android/device/collectors/SimpleperfListener.java
@@ -66,10 +66,15 @@
public static final String EVENTS = "events_to_record";
// Argument to determine if report is generated after recording.
public static final String REPORT = "report";
- // Arguments to report event count for specific symbols separated by semicolons and spaces are
- // ignored.
- // Ex. "android::Parcel::writeInt32(int);android::SurfaceFlinger::commit(long, long, long)"
+ // Report events per symbol. Symbols are separated by the key to identify the symbol and the
+ // substring used to search for the symbol.
+ // Ex. "writeInt32;android::Parcel::writeInt32(;commit;android::SurfaceFlinger::commit("
+ // symbols matching the substring "android::Parcel::writeInt32(" will be reported as
+ // "writeInt32" and
+ // symbols matching "android::SurfaceFlinger::commit(" will be reported as "commit"
public static final String REPORT_SYMBOLS = "symbols_to_report";
+ // Test iterations used to divide any reported event counts.
+ public static final String TEST_ITERATIONS = "test_iterations";
// Simpleperf samples collected during the test will be saved under this root folder.
private String mTestOutputRoot;
@@ -83,7 +88,8 @@
private String mArguments;
private Map<String, String> mProcessToPid = new HashMap<>();
private boolean mReport;
- private String[] mReportSymbols;
+ private Map<String, String> mSymbolToMetricKey = new HashMap<>();
+ private int mTestIterations;
private SimpleperfHelper mSimpleperfHelper = new SimpleperfHelper();
@@ -134,7 +140,10 @@
mReport = "true".equals(args.getString(REPORT));
// Symbols to look for when reporting events for processes.
- mReportSymbols = args.getString(REPORT_SYMBOLS, "").trim().split("\\s*;\\s*");
+ String[] symbolAndMetricKey = args.getString(REPORT_SYMBOLS, "").trim().split("\\s*;\\s*");
+ for (int i = 0; i < symbolAndMetricKey.length - 1; i += 2) {
+ mSymbolToMetricKey.put(symbolAndMetricKey[i + 1], symbolAndMetricKey[i]);
+ }
// Appending recording argument for recording specified events if given.
if (!events.isEmpty()) {
@@ -149,6 +158,9 @@
mArguments += " -p " + String.join(",", mProcessToPid.values());
}
+ mTestIterations = Integer.parseInt(args.getString(TEST_ITERATIONS, "1"));
+ Log.i(getTag(), "onTestRunStart arguments mTestIterations=" + mTestIterations);
+
if (!mIsCollectPerRun) {
return;
}
@@ -215,7 +227,7 @@
mTestIdInvocationCount.get(getTestFileName(description))));
stopSimpleperf(path, testData);
if (mReport) {
- getSimpleperfReport(path, testData, description.getMethodName());
+ getSimpleperfReport(path, testData);
}
}
}
@@ -240,7 +252,7 @@
String.format("%s%s.data", SIMPLEPERF_PREFIX, uniqueId));
stopSimpleperf(path, runData);
if (mReport) {
- getSimpleperfReport(path, runData, uniqueId);
+ getSimpleperfReport(path, runData);
}
}
@@ -268,11 +280,11 @@
* @param path Path to read binary record from.
* @param data DataRecord to store metrics parsed from report
*/
- private void getSimpleperfReport(Path path, DataRecord data, String metricsPrefix) {
+ private void getSimpleperfReport(Path path, DataRecord data) {
for (Map.Entry<String, String> entry : mProcessToPid.entrySet()) {
Map<String, String> metricPerProcess =
mSimpleperfHelper.getSimpleperfReport(
- path.toString(), entry, mReportSymbols, metricsPrefix);
+ path.toString(), entry, mSymbolToMetricKey, mTestIterations);
Log.i(getTag(), "Simpleperf Metrics report collected. " + metricPerProcess);
for (Map.Entry<String /*event-process-symbol*/, String /*eventCount*/> metric :
metricPerProcess.entrySet()) {
diff --git a/libraries/device-collectors/src/test/java/android/device/collectors/SimpleperfListenerTest.java b/libraries/device-collectors/src/test/java/android/device/collectors/SimpleperfListenerTest.java
index 5db60f3..7cd4263 100644
--- a/libraries/device-collectors/src/test/java/android/device/collectors/SimpleperfListenerTest.java
+++ b/libraries/device-collectors/src/test/java/android/device/collectors/SimpleperfListenerTest.java
@@ -17,6 +17,7 @@
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -130,36 +131,31 @@
}
private void testSampleReport() {
- Map.Entry<String, String>[] processes =
- new Map.Entry[] {
- Map.entry("surfaceflinger", "680"), Map.entry("system_server", "1696")
- };
+ Map<String, String> processes =
+ Map.of(
+ "surfaceflinger", "680",
+ "system_server", "1696");
Map<String /*key*/, String /*eventCount*/> metrics = new ArrayMap<>();
- for (Map.Entry<String, String> process : processes) {
+ for (Map.Entry<String, String> process : processes.entrySet()) {
metrics.putAll(
mSimpleperfHelper.getSimpleperfReport(
"/data/local/tmp/simpleperf/testdata/simpleperf_record_sample.data",
process,
- new String[] {
- "android::Parcel::writeInt32(int)",
- "android::SurfaceFlinger::commit(long, long, long)",
- "android::SurfaceFlinger::composite("
- },
- "metricsPrefix"));
+ Map.of(
+ "android::Parcel::writeInt32(int)",
+ "writeInt32",
+ "android::SurfaceFlinger::commit(long, long, long)",
+ "commit",
+ "android::SurfaceFlinger::composite(",
+ "composite"),
+ 10));
}
- // cherrypick a few metrics to test
- assertEquals(metrics.get("metricsPrefix-surfaceflinger-instructions"), "1107121607");
- assertEquals(
- metrics.get(
- "metricsPrefix-surfaceflinger-android::SurfaceFlinger::composite("
- + "-cpu-cycles-eventCount"),
- "20433426");
- assertEquals(
- metrics.get(
- "metricsPrefix-surfaceflinger-android::Parcel::writeInt32(int)-instructions-percentage"),
- "0.74");
- assertEquals(metrics.get("metricsPrefix-system_server-cpu-cycles"), "9080947163");
+ // cherry-pick a few metrics to test
+ assertEquals(metrics.get("surfaceflinger-instructions"), "110712160");
+ assertEquals(metrics.get("surfaceflinger-composite-cpu-cycles-count"), "2043342");
+ assertEquals(metrics.get("surfaceflinger-writeInt32-instructions-percentage"), "0.74");
+ assertEquals(metrics.get("system_server-cpu-cycles"), "908094716");
}
/*
@@ -351,7 +347,7 @@
mListener.onTestRunEnd(mListener.createDataRecord(), new Result());
verify(mSimpleperfHelperVisibleUidevice, times(1)).stopCollecting(anyString());
verify(mSimpleperfHelperVisibleUidevice, times(2))
- .getSimpleperfReport(anyString(), any(), any(), any());
+ .getSimpleperfReport(anyString(), any(), any(), anyInt());
testSampleReport();
}
@@ -367,8 +363,8 @@
b.putString(SimpleperfListener.REPORT, "true");
b.putString(
SimpleperfListener.REPORT_SYMBOLS,
- "android::Parcel::writeInt32(int); android::SurfaceFlinger::commit(long, long,"
- + " long); android::SurfaceFlinger::composite(long, long)");
+ "writeInt32;android::Parcel::writeInt32(int);commit;android::SurfaceFlinger::commit(long,"
+ + " long, long);composite;android::SurfaceFlinger::composite(long, long)");
b.putString(SimpleperfListener.EVENTS, "instructions,cpu-cycles");
mListener = initListener(b, mSimpleperfHelperVisibleUidevice);
doReturn("680").when(mUiDevice).executeShellCommand(eq("pidof surfaceflinger"));
@@ -386,7 +382,7 @@
mListener.onTestEnd(mListener.createDataRecord(), mTest3Desc);
verify(mSimpleperfHelperVisibleUidevice, times(1)).stopCollecting(anyString());
verify(mSimpleperfHelperVisibleUidevice, times(2))
- .getSimpleperfReport(anyString(), any(), any(), any());
+ .getSimpleperfReport(anyString(), any(), any(), anyInt());
testSampleReport();
}