mobile/android/base/tests/testBrowserProviderPerf.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko.tests;
michael@0 6
michael@0 7 import java.io.File;
michael@0 8 import java.util.Random;
michael@0 9 import java.util.UUID;
michael@0 10
michael@0 11 import org.mozilla.gecko.db.BrowserContract;
michael@0 12 import org.mozilla.gecko.db.BrowserProvider;
michael@0 13 import org.mozilla.gecko.db.LocalBrowserDB;
michael@0 14 import org.mozilla.gecko.util.FileUtils;
michael@0 15
michael@0 16 import android.content.ContentProvider;
michael@0 17 import android.content.ContentProviderClient;
michael@0 18 import android.content.ContentResolver;
michael@0 19 import android.content.ContentValues;
michael@0 20 import android.database.Cursor;
michael@0 21 import android.database.sqlite.SQLiteDatabase;
michael@0 22 import android.net.Uri;
michael@0 23 import android.os.SystemClock;
michael@0 24 import android.util.Log;
michael@0 25
michael@0 26 /**
michael@0 27 * This test is meant to exercise the performance of Fennec's history and
michael@0 28 * bookmarks content provider.
michael@0 29 *
michael@0 30 * It does not extend ContentProviderTest because that class is unable to
michael@0 31 * accurately assess the performance of the ContentProvider -- it's a second
michael@0 32 * instance of a class that's only supposed to exist once, wrapped in a bunch of
michael@0 33 * junk.
michael@0 34 *
michael@0 35 * Instead, we directly use the existing ContentProvider, accessing a new
michael@0 36 * profile directory that we initialize via BrowserDB.
michael@0 37 */
michael@0 38 public class testBrowserProviderPerf extends BaseRobocopTest {
michael@0 39 private final int NUMBER_OF_BASIC_HISTORY_URLS = 10000;
michael@0 40 private final int NUMBER_OF_BASIC_BOOKMARK_URLS = 500;
michael@0 41 private final int NUMBER_OF_COMBINED_URLS = 500;
michael@0 42
michael@0 43 private final int NUMBER_OF_KNOWN_URLS = 200;
michael@0 44 private final int BATCH_SIZE = 500;
michael@0 45
michael@0 46 // Include spaces in prefix to test performance querying with
michael@0 47 // multiple constraint words.
michael@0 48 private final String KNOWN_PREFIX = "my mozilla test ";
michael@0 49
michael@0 50 private Random mGenerator;
michael@0 51
michael@0 52 private final String MOBILE_FOLDER_GUID = "mobile";
michael@0 53 private long mMobileFolderId;
michael@0 54 private ContentResolver mResolver;
michael@0 55 private String mProfile;
michael@0 56 private Uri mHistoryURI;
michael@0 57 private Uri mBookmarksURI;
michael@0 58 private Uri mFaviconsURI;
michael@0 59
michael@0 60 @Override
michael@0 61 protected Type getTestType() {
michael@0 62 return Type.TALOS;
michael@0 63 }
michael@0 64
michael@0 65 private void loadMobileFolderId() throws Exception {
michael@0 66 Cursor c = mResolver.query(mBookmarksURI, null,
michael@0 67 BrowserContract.Bookmarks.GUID + " = ?",
michael@0 68 new String[] { MOBILE_FOLDER_GUID },
michael@0 69 null);
michael@0 70 c.moveToFirst();
michael@0 71 mMobileFolderId = c.getLong(c.getColumnIndex(BrowserContract.Bookmarks._ID));
michael@0 72
michael@0 73 c.close();
michael@0 74 }
michael@0 75
michael@0 76 private ContentValues createBookmarkEntry(String title, String url, long parentId,
michael@0 77 int type, int position, String tags, String description, String keyword) throws Exception {
michael@0 78 ContentValues bookmark = new ContentValues();
michael@0 79
michael@0 80 bookmark.put(BrowserContract.Bookmarks.TITLE, title);
michael@0 81 bookmark.put(BrowserContract.Bookmarks.URL, url);
michael@0 82 bookmark.put(BrowserContract.Bookmarks.PARENT, parentId);
michael@0 83 bookmark.put(BrowserContract.Bookmarks.TYPE, type);
michael@0 84 bookmark.put(BrowserContract.Bookmarks.POSITION, position);
michael@0 85 bookmark.put(BrowserContract.Bookmarks.TAGS, tags);
michael@0 86 bookmark.put(BrowserContract.Bookmarks.DESCRIPTION, description);
michael@0 87 bookmark.put(BrowserContract.Bookmarks.KEYWORD, keyword);
michael@0 88
michael@0 89 return bookmark;
michael@0 90 }
michael@0 91
michael@0 92 private ContentValues createBookmarkEntryWithUrl(String url) throws Exception {
michael@0 93 return createBookmarkEntry(url, url, mMobileFolderId,
michael@0 94 BrowserContract.Bookmarks.TYPE_BOOKMARK, 0, "tags", "description", "keyword");
michael@0 95 }
michael@0 96
michael@0 97 private ContentValues createRandomBookmarkEntry() throws Exception {
michael@0 98 return createRandomBookmarkEntry("");
michael@0 99 }
michael@0 100
michael@0 101 private ContentValues createRandomBookmarkEntry(String knownPrefix) throws Exception {
michael@0 102 String randomStr = createRandomUrl(knownPrefix);
michael@0 103 return createBookmarkEntryWithUrl(randomStr);
michael@0 104 }
michael@0 105
michael@0 106 private ContentValues createHistoryEntry(String title, String url, int visits,
michael@0 107 long lastVisited) throws Exception {
michael@0 108 ContentValues historyEntry = new ContentValues();
michael@0 109
michael@0 110 historyEntry.put(BrowserContract.History.TITLE, title);
michael@0 111 historyEntry.put(BrowserContract.History.URL, url);
michael@0 112 historyEntry.put(BrowserContract.History.VISITS, visits);
michael@0 113 historyEntry.put(BrowserContract.History.DATE_LAST_VISITED, lastVisited);
michael@0 114
michael@0 115 return historyEntry;
michael@0 116 }
michael@0 117
michael@0 118 private ContentValues createHistoryEntryWithUrl(String url) throws Exception {
michael@0 119 int visits = mGenerator.nextInt(500);
michael@0 120 return createHistoryEntry(url, url, visits,
michael@0 121 System.currentTimeMillis());
michael@0 122 }
michael@0 123
michael@0 124 private ContentValues createRandomHistoryEntry() throws Exception {
michael@0 125 return createRandomHistoryEntry("");
michael@0 126 }
michael@0 127
michael@0 128 private ContentValues createRandomHistoryEntry(String knownPrefix) throws Exception {
michael@0 129 String randomStr = createRandomUrl(knownPrefix);
michael@0 130 return createHistoryEntryWithUrl(randomStr);
michael@0 131 }
michael@0 132
michael@0 133 private ContentValues createFaviconEntryWithUrl(String url) throws Exception {
michael@0 134 ContentValues faviconEntry = new ContentValues();
michael@0 135
michael@0 136 faviconEntry.put(BrowserContract.Favicons.URL, url + "/favicon.ico");
michael@0 137 faviconEntry.put(BrowserContract.Favicons.PAGE_URL, url);
michael@0 138 faviconEntry.put(BrowserContract.Favicons.DATA, url.getBytes("UTF8"));
michael@0 139
michael@0 140 return faviconEntry;
michael@0 141 }
michael@0 142
michael@0 143 private String createRandomUrl(String knownPrefix) throws Exception {
michael@0 144 return knownPrefix + UUID.randomUUID().toString();
michael@0 145 }
michael@0 146
michael@0 147 private void addTonsOfUrls() throws Exception {
michael@0 148 // Create some random bookmark entries.
michael@0 149 ContentValues[] bookmarkEntries = new ContentValues[BATCH_SIZE];
michael@0 150
michael@0 151 for (int i = 0; i < NUMBER_OF_BASIC_BOOKMARK_URLS / BATCH_SIZE; i++) {
michael@0 152 bookmarkEntries = new ContentValues[BATCH_SIZE];
michael@0 153
michael@0 154 for (int j = 0; j < BATCH_SIZE; j++) {
michael@0 155 bookmarkEntries[j] = createRandomBookmarkEntry();
michael@0 156 }
michael@0 157
michael@0 158 mResolver.bulkInsert(mBookmarksURI, bookmarkEntries);
michael@0 159 }
michael@0 160
michael@0 161 // Create some random history entries.
michael@0 162 ContentValues[] historyEntries = new ContentValues[BATCH_SIZE];
michael@0 163 ContentValues[] faviconEntries = new ContentValues[BATCH_SIZE];
michael@0 164
michael@0 165 for (int i = 0; i < NUMBER_OF_BASIC_HISTORY_URLS / BATCH_SIZE; i++) {
michael@0 166 historyEntries = new ContentValues[BATCH_SIZE];
michael@0 167 faviconEntries = new ContentValues[BATCH_SIZE];
michael@0 168
michael@0 169 for (int j = 0; j < BATCH_SIZE; j++) {
michael@0 170 historyEntries[j] = createRandomHistoryEntry();
michael@0 171 faviconEntries[j] = createFaviconEntryWithUrl(historyEntries[j].getAsString(BrowserContract.History.URL));
michael@0 172 }
michael@0 173
michael@0 174 mResolver.bulkInsert(mHistoryURI, historyEntries);
michael@0 175 mResolver.bulkInsert(mFaviconsURI, faviconEntries);
michael@0 176 }
michael@0 177
michael@0 178
michael@0 179 // Create random bookmark/history entries with the same URL.
michael@0 180 for (int i = 0; i < NUMBER_OF_COMBINED_URLS / BATCH_SIZE; i++) {
michael@0 181 bookmarkEntries = new ContentValues[BATCH_SIZE];
michael@0 182 historyEntries = new ContentValues[BATCH_SIZE];
michael@0 183
michael@0 184 for (int j = 0; j < BATCH_SIZE; j++) {
michael@0 185 String url = createRandomUrl("");
michael@0 186 bookmarkEntries[j] = createBookmarkEntryWithUrl(url);
michael@0 187 historyEntries[j] = createHistoryEntryWithUrl(url);
michael@0 188 faviconEntries[j] = createFaviconEntryWithUrl(url);
michael@0 189 }
michael@0 190
michael@0 191 mResolver.bulkInsert(mBookmarksURI, bookmarkEntries);
michael@0 192 mResolver.bulkInsert(mHistoryURI, historyEntries);
michael@0 193 mResolver.bulkInsert(mFaviconsURI, faviconEntries);
michael@0 194 }
michael@0 195
michael@0 196 // Create some history entries with a known prefix.
michael@0 197 historyEntries = new ContentValues[NUMBER_OF_KNOWN_URLS];
michael@0 198 faviconEntries = new ContentValues[NUMBER_OF_KNOWN_URLS];
michael@0 199 for (int i = 0; i < NUMBER_OF_KNOWN_URLS; i++) {
michael@0 200 historyEntries[i] = createRandomHistoryEntry(KNOWN_PREFIX);
michael@0 201 faviconEntries[i] = createFaviconEntryWithUrl(historyEntries[i].getAsString(BrowserContract.History.URL));
michael@0 202 }
michael@0 203
michael@0 204 mResolver.bulkInsert(mHistoryURI, historyEntries);
michael@0 205 mResolver.bulkInsert(mFaviconsURI, faviconEntries);
michael@0 206 }
michael@0 207
michael@0 208 @Override
michael@0 209 public void setUp() throws Exception {
michael@0 210 super.setUp();
michael@0 211
michael@0 212 mProfile = "prof" + System.currentTimeMillis();
michael@0 213
michael@0 214 mHistoryURI = prepUri(BrowserContract.History.CONTENT_URI);
michael@0 215 mBookmarksURI = prepUri(BrowserContract.Bookmarks.CONTENT_URI);
michael@0 216 mFaviconsURI = prepUri(BrowserContract.Favicons.CONTENT_URI);
michael@0 217
michael@0 218 mResolver = getActivity().getApplicationContext().getContentResolver();
michael@0 219
michael@0 220 mGenerator = new Random(19580427);
michael@0 221 }
michael@0 222
michael@0 223 @Override
michael@0 224 public void tearDown() {
michael@0 225 final ContentProviderClient client = mResolver.acquireContentProviderClient(mBookmarksURI);
michael@0 226 try {
michael@0 227 final ContentProvider cp = client.getLocalContentProvider();
michael@0 228 final BrowserProvider bp = ((BrowserProvider) cp);
michael@0 229
michael@0 230 // This will be the DB we were just testing.
michael@0 231 final SQLiteDatabase db = bp.getWritableDatabaseForTesting(mBookmarksURI);
michael@0 232 try {
michael@0 233 db.close();
michael@0 234 } catch (Throwable e) {
michael@0 235 // Nothing we can do.
michael@0 236 }
michael@0 237 } finally {
michael@0 238 try {
michael@0 239 client.release();
michael@0 240 } catch (Throwable e) {
michael@0 241 // Still go ahead and try to delete the profile.
michael@0 242 }
michael@0 243
michael@0 244 try {
michael@0 245 FileUtils.delTree(new File(mProfile), null, true);
michael@0 246 } catch (Exception e) {
michael@0 247 Log.w("GeckoTest", "Unable to delete profile " + mProfile, e);
michael@0 248 }
michael@0 249 }
michael@0 250 }
michael@0 251
michael@0 252 public Uri prepUri(Uri uri) {
michael@0 253 return uri.buildUpon()
michael@0 254 .appendQueryParameter(BrowserContract.PARAM_PROFILE, mProfile)
michael@0 255 .appendQueryParameter(BrowserContract.PARAM_IS_SYNC, "1") // So we don't trigger a sync.
michael@0 256 .build();
michael@0 257 }
michael@0 258
michael@0 259 /**
michael@0 260 * This method:
michael@0 261 *
michael@0 262 * * Adds a bunch of test data via the ContentProvider API.
michael@0 263 * * Runs a single query against that test data via BrowserDB.
michael@0 264 * * Reports timing for Talos.
michael@0 265 */
michael@0 266 public void testBrowserProviderQueryPerf() throws Exception {
michael@0 267 // We add at least this many results.
michael@0 268 final int limit = 100;
michael@0 269
michael@0 270 // Make sure we're querying the right profile.
michael@0 271 final LocalBrowserDB db = new LocalBrowserDB(mProfile);
michael@0 272
michael@0 273 final Cursor before = db.filter(mResolver, KNOWN_PREFIX, limit);
michael@0 274 try {
michael@0 275 mAsserter.is(before.getCount(), 0, "Starts empty");
michael@0 276 } finally {
michael@0 277 before.close();
michael@0 278 }
michael@0 279
michael@0 280 // Add data.
michael@0 281 loadMobileFolderId();
michael@0 282 addTonsOfUrls();
michael@0 283
michael@0 284 // Wait for a little while after inserting data. We do this because
michael@0 285 // this test launches about:home, and Top Sites watches for DB changes.
michael@0 286 // We don't have a good way for it to only watch changes related to
michael@0 287 // its current profile, nor is it convenient for us to launch a different
michael@0 288 // activity that doesn't depend on the DB.
michael@0 289 // We can fix this by:
michael@0 290 // * Adjusting the provider interface to allow a "don't notify" param.
michael@0 291 // * Adjusting the interface schema to include the profile in the path,
michael@0 292 // and only observe the correct path.
michael@0 293 // * Launching a different activity.
michael@0 294 Thread.sleep(5000);
michael@0 295
michael@0 296 // Time the query.
michael@0 297 final long start = SystemClock.uptimeMillis();
michael@0 298 final Cursor c = db.filter(mResolver, KNOWN_PREFIX, limit);
michael@0 299
michael@0 300 try {
michael@0 301 final int count = c.getCount();
michael@0 302 final long end = SystemClock.uptimeMillis();
michael@0 303
michael@0 304 mAsserter.is(count, limit, "Retrieved results");
michael@0 305 mAsserter.dumpLog("Results: " + count);
michael@0 306 mAsserter.dumpLog("__start_report" + Long.toString(end - start) + "__end_report");
michael@0 307 mAsserter.dumpLog("__startTimestamp" + Long.toString(end - start) + "__endTimestamp");
michael@0 308 } finally {
michael@0 309 c.close();
michael@0 310 }
michael@0 311 }
michael@0 312 }

mercurial