BearND has uploaded a new change for review.
https://gerrit.wikimedia.org/r/232681
Change subject: Hygiene: Add page load performance test
......................................................................
Hygiene: Add page load performance test
We can't improve what we don't measure.
I'm adding some performance tests to see how long loading a few pages
on testwiki takes. It's good to have those tests added before we significantly
change the page load code further.
For serious testing increase the NUM_RUNS to a higher value.
Also to compare apples to apples it's imperative to test on the same devices,
ideally with the same network condition.
(Ok, the latter is not really exactly controlled. But as long as we're talking
about a stable broadband connection it should be good enough.
The alternative would be mocking responses from a Mock MediaWiki server
and injecting code to use that instead of the real servers.)
Introduced a callback for page load completion which is currently only
used for this performance test but could be used for other things in the future.
Renamed another test to make it clearer that it's testing SectionFetchTask
directly.
Bug: T109246
Change-Id: Ie5f8494da952cfdaa753a5e4e7a9f826599a1409
---
R app/src/androidTest/java/org/wikipedia/test/SectionsFetchTaskTests.java
A app/src/androidTest/java/org/wikipedia/test/perf/MeasurementController.java
A app/src/androidTest/java/org/wikipedia/test/perf/PageLoadPerformanceTests.java
M app/src/main/java/org/wikipedia/page/PageFragment.java
A app/src/main/java/org/wikipedia/page/PageLoadCallbacks.java
5 files changed, 211 insertions(+), 2 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/apps/android/wikipedia
refs/changes/81/232681/1
diff --git
a/app/src/androidTest/java/org/wikipedia/test/PageFetchTaskTests.java
b/app/src/androidTest/java/org/wikipedia/test/SectionsFetchTaskTests.java
similarity index 94%
rename from app/src/androidTest/java/org/wikipedia/test/PageFetchTaskTests.java
rename to
app/src/androidTest/java/org/wikipedia/test/SectionsFetchTaskTests.java
index 717dfa0..504cbe8 100644
--- a/app/src/androidTest/java/org/wikipedia/test/PageFetchTaskTests.java
+++ b/app/src/androidTest/java/org/wikipedia/test/SectionsFetchTaskTests.java
@@ -13,10 +13,10 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-public class PageFetchTaskTests extends
ActivityUnitTestCase<TestDummyActivity> {
+public class SectionsFetchTaskTests extends
ActivityUnitTestCase<TestDummyActivity> {
private static final int TASK_COMPLETION_TIMEOUT = 20000;
- public PageFetchTaskTests() {
+ public SectionsFetchTaskTests() {
super(TestDummyActivity.class);
}
diff --git
a/app/src/androidTest/java/org/wikipedia/test/perf/MeasurementController.java
b/app/src/androidTest/java/org/wikipedia/test/perf/MeasurementController.java
new file mode 100644
index 0000000..5806e6d
--- /dev/null
+++
b/app/src/androidTest/java/org/wikipedia/test/perf/MeasurementController.java
@@ -0,0 +1,89 @@
+package org.wikipedia.test.perf;
+
+import org.wikipedia.util.log.L;
+
+import android.support.v4.util.ArrayMap;
+
+import java.util.ArrayList;
+
+/**
+ * A simple performance test measurement collection mechanism for Android.
+ */
+public final class MeasurementController {
+ private static final ArrayMap<String, MeasurementSeries> seriesMap = new
ArrayMap<>();
+
+ public static void start(String key) {
+ MeasurementSeries measurementSeries = seriesMap.get(key);
+ if (measurementSeries == null) {
+ measurementSeries = new MeasurementSeries();
+ seriesMap.put(key, measurementSeries);
+ }
+ if (measurementSeries.currentStart > 0) {
+ L.w("Overwriting currentStart of " +
measurementSeries.currentStart);
+ }
+ L.v("Start(" + key + ")");
+ measurementSeries.currentStart = System.nanoTime();
+ }
+
+ public static void stop(String key) {
+ MeasurementSeries measurementSeries = seriesMap.get(key);
+ if (measurementSeries == null) {
+ throw new IllegalStateException("Stop called without start");
+ }
+
+ long duration = System.nanoTime() - measurementSeries.currentStart;
+ measurementSeries.currentStart = 0L;
+ measurementSeries.measurements.add(duration);
+
+ L.v("Duration(" + key + ") = " +
MeasurementSeries.nanoToMillisString(duration));
+ }
+
+ public static void analyzeAll() {
+ L.i("---");
+ for (String key : seriesMap.keySet()) {
+ analyze(key);
+ }
+ L.i("---");
+ }
+
+ private static void analyze(String key) {
+ L.i(key + ": " + seriesMap.get(key).analyze());
+ }
+
+ /**
+ * One series of similar tests which can be aggregated
+ */
+ public static class MeasurementSeries {
+ ArrayList<Long> measurements = new ArrayList<>();
+ long currentStart = 0L;
+
+ public String analyze() {
+ long min = Long.MAX_VALUE;
+ long max = Long.MIN_VALUE;
+ long sum = 0L;
+
+ for (long current : measurements) {
+ if (current < min) {
+ min = current;
+ }
+ if (current > max) {
+ max = current;
+ }
+ sum += current;
+ }
+
+ String res = nanoToMillisString(sum / measurements.size());
+ if (measurements.size() > 1) {
+ res += "(n: " + measurements.size()
+ + "; min: " + nanoToMillisString(min)
+ + "; max: " + nanoToMillisString(max)
+ + ")";
+ }
+ return res;
+ }
+
+ static String nanoToMillisString(long value) {
+ return (value / 1000000) + "ms";
+ }
+ }
+}
diff --git
a/app/src/androidTest/java/org/wikipedia/test/perf/PageLoadPerformanceTests.java
b/app/src/androidTest/java/org/wikipedia/test/perf/PageLoadPerformanceTests.java
new file mode 100644
index 0000000..a1e242e
--- /dev/null
+++
b/app/src/androidTest/java/org/wikipedia/test/perf/PageLoadPerformanceTests.java
@@ -0,0 +1,99 @@
+package org.wikipedia.test.perf;
+
+import org.wikipedia.R;
+import org.wikipedia.Site;
+import org.wikipedia.history.HistoryEntry;
+import org.wikipedia.page.PageActivity;
+import org.wikipedia.page.PageFragment;
+import org.wikipedia.page.PageLoadCallbacks;
+import org.wikipedia.page.PageTitle;
+
+import android.support.v4.app.Fragment;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test performance of page loading. Update the NUM_RUNS for better
statistical significance.
+ */
+@LargeTest
+public class PageLoadPerformanceTests extends
ActivityInstrumentationTestCase2<PageActivity> {
+ private static final int TASK_COMPLETION_TIMEOUT=30000;
+ private static final Site SITE = new Site("test.wikipedia.org");
+ private static final int NUM_RUNS = 1; //50;
+ private PageActivity activity;
+ private CountDownLatch completionLatch;
+ private PageFragment fragment;
+ private String titleString;
+
+ public PageLoadPerformanceTests() {
+ super(PageActivity.class);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ activity = getActivity();
+ }
+
+ public void testLoadPage() throws Throwable {
+ titleString = "Test_page_for_app_testing/Section1";
+ for (int i = 0; i < NUM_RUNS; i++) {
+ loadPageUi();
+ }
+
+ titleString = "A_long_page";
+ for (int i = 0; i < NUM_RUNS; i++) {
+ loadPageUi();
+ }
+
+ // also on testwiki, much longer than previous pages, has a lead image
+ titleString = "Barack_Obama";
+ for (int i = 0; i < NUM_RUNS; i++) {
+ loadPageUi();
+ }
+
+ Thread.sleep(100);
+ MeasurementController.analyzeAll();
+ }
+
+ private void loadPageUi() throws Throwable {
+ completionLatch = new CountDownLatch(1);
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ fragment = findPageFragment();
+ fragment.setPageLoadCallbacks(cb);
+
+ MeasurementController.start(titleString);
+ loadPage();
+ }
+ });
+ assertTrue(completionLatch.await(TASK_COMPLETION_TIMEOUT,
TimeUnit.MILLISECONDS));
+ }
+
+ private void loadPage() {
+ PageTitle pageTitle = new PageTitle(null, titleString, SITE);
+ fragment.displayNewPage(pageTitle,
+ new HistoryEntry(pageTitle, HistoryEntry.SOURCE_RANDOM),
+ false,
+ false);
+ }
+
+ private PageLoadCallbacks cb = new PageLoadCallbacks() {
+ @Override
+ public void onLoadComplete() {
+ completionLatch.countDown();
+ MeasurementController.stop(titleString);
+ }
+ };
+
+ private PageFragment findPageFragment() {
+ Fragment fragment = activity.getSupportFragmentManager()
+ .findFragmentById(R.id.content_fragment_container);
+ assertTrue(fragment instanceof PageFragment);
+ return (PageFragment) fragment;
+ }
+}
diff --git a/app/src/main/java/org/wikipedia/page/PageFragment.java
b/app/src/main/java/org/wikipedia/page/PageFragment.java
index 1d06c1b..ad39b70 100755
--- a/app/src/main/java/org/wikipedia/page/PageFragment.java
+++ b/app/src/main/java/org/wikipedia/page/PageFragment.java
@@ -169,6 +169,9 @@
}
};
+ @Nullable
+ private PageLoadCallbacks pageLoadCallbacks;
+
public ObservableWebView getWebView() {
return webView;
}
@@ -826,6 +829,10 @@
checkAndShowSelectTextOnboarding();
updateNavDrawerSelection();
+
+ if (pageLoadCallbacks != null) {
+ pageLoadCallbacks.onLoadComplete();
+ }
}
public PageTitle adjustPageTitleFromMobileview(PageTitle title, JSONObject
mobileView)
@@ -1064,6 +1071,11 @@
return (PageActivity) getActivity();
}
+ // Mainly for testing (for now)
+ public void setPageLoadCallbacks(PageLoadCallbacks pageLoadCallbacks) {
+ this.pageLoadCallbacks = pageLoadCallbacks;
+ }
+
private class LongPressHandler extends PageActivityLongPressHandler
implements PageLongPressHandler.WebViewContextMenuListener {
public LongPressHandler(@NonNull PageActivity activity) {
diff --git a/app/src/main/java/org/wikipedia/page/PageLoadCallbacks.java
b/app/src/main/java/org/wikipedia/page/PageLoadCallbacks.java
new file mode 100644
index 0000000..af440eb
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/page/PageLoadCallbacks.java
@@ -0,0 +1,9 @@
+package org.wikipedia.page;
+
+/**
+ * Callback methods for page load state feedback
+ */
+public interface PageLoadCallbacks {
+ /** Called when page has finished loading */
+ void onLoadComplete();
+}
--
To view, visit https://gerrit.wikimedia.org/r/232681
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie5f8494da952cfdaa753a5e4e7a9f826599a1409
Gerrit-PatchSet: 1
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: BearND <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits