mobile/android/base/tests/testBrowserProviderPerf.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

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

mercurial