зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1369604: Use HighlightCandidateCursorIndices to cache. r=liuche
This reduces the calls to `getColumnIndexOrThrow` to 9 (from 1.6k) and HighlightsRanking.extractFeatures goes from 77.1% inclusive CPU time -> 40.8%, 14.6k ms -> 7.1k ms. MozReview-Commit-ID: L6HqvBK5I4i --HG-- extra : rebase_source : f67c5ed207a4684edc4a3e7779dabd59c7f98608
This commit is contained in:
Родитель
a764197b83
Коммит
9c75c2a05e
|
@ -6,8 +6,7 @@
|
|||
package org.mozilla.gecko.activitystream;
|
||||
|
||||
import android.database.Cursor;
|
||||
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.activitystream.ranking.HighlightCandidateCursorIndices;
|
||||
|
||||
/**
|
||||
* Various util methods and constants that are shared by different parts of Activity Stream.
|
||||
|
@ -18,12 +17,12 @@ public class Utils {
|
|||
BOOKMARKED
|
||||
}
|
||||
|
||||
public static HighlightSource highlightSource(final Cursor cursor) {
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.BOOKMARK_ID))) {
|
||||
public static HighlightSource highlightSource(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices) {
|
||||
if (-1 != cursor.getLong(cursorIndices.bookmarkIDColumnIndex)) {
|
||||
return HighlightSource.BOOKMARKED;
|
||||
}
|
||||
|
||||
if (-1 != cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.HISTORY_ID))) {
|
||||
if (-1 != cursor.getLong(cursorIndices.historyIDColumnIndex)) {
|
||||
return HighlightSource.VISITED;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,8 @@ package org.mozilla.gecko.activitystream.homepanel.model;
|
|||
import android.database.Cursor;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import org.mozilla.gecko.activitystream.Utils;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.activitystream.ranking.HighlightCandidateCursorIndices;
|
||||
|
||||
public class Highlight implements Item {
|
||||
private final String title;
|
||||
|
@ -25,19 +24,19 @@ public class Highlight implements Item {
|
|||
private @Nullable Boolean isPinned;
|
||||
private @Nullable Boolean isBookmarked;
|
||||
|
||||
public static Highlight fromCursor(Cursor cursor) {
|
||||
return new Highlight(cursor);
|
||||
public static Highlight fromCursor(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices) {
|
||||
return new Highlight(cursor, cursorIndices);
|
||||
}
|
||||
|
||||
private Highlight(Cursor cursor) {
|
||||
title = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.History.TITLE));
|
||||
url = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Combined.URL));
|
||||
source = Utils.highlightSource(cursor);
|
||||
time = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.DATE));
|
||||
private Highlight(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices) {
|
||||
title = cursor.getString(cursorIndices.titleColumnIndex);
|
||||
url = cursor.getString(cursorIndices.urlColumnIndex);
|
||||
source = Utils.highlightSource(cursor, cursorIndices);
|
||||
time = cursor.getLong(cursorIndices.highlightsDateColumnIndex);
|
||||
|
||||
historyId = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.HISTORY_ID));
|
||||
historyId = cursor.getLong(cursorIndices.historyIDColumnIndex);
|
||||
|
||||
metadata = Metadata.fromCursor(cursor);
|
||||
metadata = Metadata.fromCursor(cursor, cursorIndices);
|
||||
|
||||
updateState();
|
||||
}
|
||||
|
|
|
@ -8,17 +8,15 @@ package org.mozilla.gecko.activitystream.homepanel.model;
|
|||
import android.database.Cursor;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.activitystream.ranking.HighlightCandidateCursorIndices;
|
||||
|
||||
public class Metadata {
|
||||
private static final String LOGTAG = "GeckoMetadata";
|
||||
|
||||
public static Metadata fromCursor(Cursor cursor) {
|
||||
return new Metadata(
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.METADATA)));
|
||||
public static Metadata fromCursor(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices) {
|
||||
return new Metadata(cursor.getString(cursorIndices.metadataColumnIndex));
|
||||
}
|
||||
|
||||
private String provider;
|
||||
|
|
|
@ -12,7 +12,6 @@ import android.support.annotation.StringDef;
|
|||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import org.mozilla.gecko.activitystream.ranking.RankingUtils.Func1;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.activitystream.homepanel.model.Highlight;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -44,11 +43,12 @@ import java.util.Map;
|
|||
private String host;
|
||||
private double score;
|
||||
|
||||
public static HighlightCandidate fromCursor(Cursor cursor) throws InvalidHighlightCandidateException {
|
||||
public static HighlightCandidate fromCursor(final Cursor cursor, final HighlightCandidateCursorIndices cursorIndices)
|
||||
throws InvalidHighlightCandidateException {
|
||||
final HighlightCandidate candidate = new HighlightCandidate();
|
||||
|
||||
extractHighlight(candidate, cursor);
|
||||
extractFeatures(candidate, cursor);
|
||||
extractHighlight(candidate, cursor, cursorIndices);
|
||||
extractFeatures(candidate, cursor, cursorIndices);
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
@ -56,22 +56,24 @@ import java.util.Map;
|
|||
/**
|
||||
* Extract highlight object from cursor.
|
||||
*/
|
||||
private static void extractHighlight(HighlightCandidate candidate, Cursor cursor) {
|
||||
candidate.highlight = Highlight.fromCursor(cursor);
|
||||
private static void extractHighlight(final HighlightCandidate candidate, final Cursor cursor,
|
||||
final HighlightCandidateCursorIndices cursorIndices) {
|
||||
candidate.highlight = Highlight.fromCursor(cursor, cursorIndices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract and assign features that will be used for ranking.
|
||||
*/
|
||||
private static void extractFeatures(HighlightCandidate candidate, Cursor cursor) throws InvalidHighlightCandidateException {
|
||||
private static void extractFeatures(final HighlightCandidate candidate, final Cursor cursor,
|
||||
final HighlightCandidateCursorIndices cursorIndices) throws InvalidHighlightCandidateException {
|
||||
candidate.features.put(
|
||||
FEATURE_AGE_IN_DAYS,
|
||||
(System.currentTimeMillis() - cursor.getDouble(cursor.getColumnIndexOrThrow(BrowserContract.History.DATE_LAST_VISITED)))
|
||||
(System.currentTimeMillis() - cursor.getDouble(cursorIndices.historyDateLastVisitedColumnIndex))
|
||||
/ (1000 * 3600 * 24));
|
||||
|
||||
candidate.features.put(
|
||||
FEATURE_VISITS_COUNT,
|
||||
cursor.getDouble(cursor.getColumnIndexOrThrow(BrowserContract.History.VISITS)));
|
||||
cursor.getDouble(cursorIndices.visitsColumnIndex));
|
||||
|
||||
// Until we can determine those numbers we assume this domain has only been visited once
|
||||
// and the cursor returned all database entries.
|
||||
|
@ -108,15 +110,14 @@ import java.util.Map;
|
|||
// to the real creation date, or the earliest one mentioned in the clients constellation.
|
||||
// We are sourcing highlights from the recent visited history - so in order to
|
||||
// show up this bookmark need to have been visited recently too.
|
||||
final int bookmarkDateColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Bookmarks.DATE_CREATED);
|
||||
if (cursor.isNull(bookmarkDateColumnIndex)) {
|
||||
if (cursor.isNull(cursorIndices.bookmarkDateCreatedColumnIndex)) {
|
||||
candidate.features.put(
|
||||
FEATURE_BOOKMARK_AGE_IN_MILLISECONDS,
|
||||
0d);
|
||||
} else {
|
||||
candidate.features.put(
|
||||
FEATURE_BOOKMARK_AGE_IN_MILLISECONDS,
|
||||
Math.max(1, System.currentTimeMillis() - cursor.getDouble(bookmarkDateColumnIndex)));
|
||||
Math.max(1, System.currentTimeMillis() - cursor.getDouble(cursorIndices.bookmarkDateCreatedColumnIndex)));
|
||||
}
|
||||
|
||||
candidate.features.put(
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.activitystream.ranking;
|
||||
|
||||
import android.database.Cursor;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
|
||||
/**
|
||||
* A cache of the column indices of the given Cursor.
|
||||
*
|
||||
* We use this for performance reasons: {@link Cursor#getColumnIndexOrThrow(String)} will do a HashMap look-up and
|
||||
* String comparison each time it's called, which gets expensive while iterating through HighlightCandidate results
|
||||
* (currently a maximum of 500 items), so we cache the values.
|
||||
*/
|
||||
public class HighlightCandidateCursorIndices {
|
||||
|
||||
public final int titleColumnIndex;
|
||||
public final int urlColumnIndex;
|
||||
public final int visitsColumnIndex;
|
||||
public final int metadataColumnIndex;
|
||||
|
||||
public final int highlightsDateColumnIndex;
|
||||
public final int bookmarkDateCreatedColumnIndex;
|
||||
public final int historyDateLastVisitedColumnIndex;
|
||||
|
||||
public final int historyIDColumnIndex;
|
||||
public final int bookmarkIDColumnIndex;
|
||||
|
||||
HighlightCandidateCursorIndices(final Cursor cursor) {
|
||||
titleColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.History.TITLE);
|
||||
urlColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Combined.URL);
|
||||
visitsColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.History.VISITS);
|
||||
metadataColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Highlights.METADATA);
|
||||
|
||||
highlightsDateColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Highlights.DATE);
|
||||
bookmarkDateCreatedColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Bookmarks.DATE_CREATED);
|
||||
historyDateLastVisitedColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.History.DATE_LAST_VISITED);
|
||||
|
||||
historyIDColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Highlights.HISTORY_ID);
|
||||
bookmarkIDColumnIndex = cursor.getColumnIndexOrThrow(BrowserContract.Highlights.BOOKMARK_ID);
|
||||
}
|
||||
}
|
|
@ -7,8 +7,8 @@ package org.mozilla.gecko.activitystream.ranking;
|
|||
|
||||
import android.database.Cursor;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.Log;
|
||||
|
||||
import android.util.Log;
|
||||
import org.mozilla.gecko.activitystream.homepanel.model.Highlight;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -96,12 +96,14 @@ public class HighlightsRanking {
|
|||
* Extract features for every candidate. The heavy lifting is done in
|
||||
* HighlightCandidate.fromCursor().
|
||||
*/
|
||||
@VisibleForTesting static List<HighlightCandidate> extractFeatures(Cursor cursor) {
|
||||
@VisibleForTesting static List<HighlightCandidate> extractFeatures(final Cursor cursor) {
|
||||
// Cache column indices for performance: see class Javadoc for more info.
|
||||
final HighlightCandidateCursorIndices cursorIndices = new HighlightCandidateCursorIndices(cursor);
|
||||
return looselyMapCursor(cursor, new Func1<Cursor, HighlightCandidate>() {
|
||||
@Override
|
||||
public HighlightCandidate call(Cursor cursor) {
|
||||
try {
|
||||
return HighlightCandidate.fromCursor(cursor);
|
||||
return HighlightCandidate.fromCursor(cursor, cursorIndices);
|
||||
} catch (HighlightCandidate.InvalidHighlightCandidateException e) {
|
||||
Log.w(LOG_TAG, "Skipping invalid highlight item", e);
|
||||
return null;
|
||||
|
|
|
@ -525,6 +525,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
|
|||
'activitystream/homepanel/topsites/TopSitesPageAdapter.java',
|
||||
'activitystream/homepanel/topsites/TopSitesPagerAdapter.java',
|
||||
'activitystream/ranking/HighlightCandidate.java',
|
||||
'activitystream/ranking/HighlightCandidateCursorIndices.java',
|
||||
'activitystream/ranking/HighlightsRanking.java',
|
||||
'activitystream/ranking/RankingUtils.java',
|
||||
'activitystream/Utils.java',
|
||||
|
|
Загрузка…
Ссылка в новой задаче