summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs83
1 files changed, 77 insertions, 6 deletions
diff --git a/toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs b/toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs
index 7c52c508ee..a1df8cac89 100644
--- a/toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs
+++ b/toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs
@@ -59,12 +59,31 @@ XPCOMUtils.defineLazyPreferenceGetter(
90
);
+// This pref stores whether recalculation should be faster.
+// It is set when we detect that a lot of changes happened recently, and it
+// will survive restarts. Once there's nothing left to recalculate, we unset
+// the pref and return to the normal recalculation rate.
+// Note this getter transforms the boolean pref value into an integer
+// acceleration rate.
+const PREF_ACCELERATE_RECALCULATION = "places.frecency.accelerateRecalculation";
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "accelerationRate",
+ PREF_ACCELERATE_RECALCULATION,
+ false,
+ null,
+ accelerate => (accelerate ? 2 : 1)
+);
+
// Time between deferred task executions.
const DEFERRED_TASK_INTERVAL_MS = 2 * 60000;
// Maximum time to wait for an idle before the task is executed anyway.
const DEFERRED_TASK_MAX_IDLE_WAIT_MS = 5 * 60000;
// Number of entries to update at once.
const DEFAULT_CHUNK_SIZE = 50;
+// Threshold used to evaluate whether the number of Places events from the last
+// recalculation is high enough to deserve a recalculation rate increase.
+const ACCELERATION_EVENTS_THRESHOLD = 250;
export class PlacesFrecencyRecalculator {
classID = Components.ID("1141fd31-4c1a-48eb-8f1a-2f05fad94085");
@@ -104,11 +123,8 @@ export class PlacesFrecencyRecalculator {
return;
}
- this.#task = new lazy.DeferredTask(
- this.#taskFn.bind(this),
- DEFERRED_TASK_INTERVAL_MS,
- DEFERRED_TASK_MAX_IDLE_WAIT_MS
- );
+ this.#createOrUpdateTask();
+
lazy.AsyncShutdown.profileChangeTeardown.addBlocker(
"PlacesFrecencyRecalculator: shutdown",
() => this.#finalize()
@@ -133,6 +149,22 @@ export class PlacesFrecencyRecalculator {
this.maybeStartFrecencyRecalculation();
}
+ #createOrUpdateTask() {
+ let wasArmed = this.#task?.isArmed;
+ if (this.#task) {
+ this.#task.disarm();
+ this.#task.finalize().catch(console.error);
+ }
+ this.#task = new lazy.DeferredTask(
+ this.#taskFn.bind(this),
+ DEFERRED_TASK_INTERVAL_MS / lazy.accelerationRate,
+ DEFERRED_TASK_MAX_IDLE_WAIT_MS / lazy.accelerationRate
+ );
+ if (wasArmed) {
+ this.#task.arm();
+ }
+ }
+
async #taskFn() {
if (this.#task.isFinalized) {
return;
@@ -161,6 +193,40 @@ export class PlacesFrecencyRecalculator {
this.#task.finalize().catch(console.error);
}
+ #lastEventsCount = 0;
+
+ /**
+ * Evaluates whether recalculation speed should be increased, and eventually
+ * accelerates.
+ * @returns {boolean} whether the recalculation rate is increased.
+ */
+ maybeUpdateRecalculationSpeed() {
+ if (lazy.accelerationRate > 1) {
+ return true;
+ }
+ // We mostly care about additions to cover the common case of importing
+ // bookmarks or history. We may care about removals, but in most cases they
+ // reduce the number of entries to recalculate.
+ let eventsCount =
+ PlacesObservers.counts.get("page-visited") +
+ PlacesObservers.counts.get("bookmark-added");
+ let accelerate =
+ eventsCount - this.#lastEventsCount > ACCELERATION_EVENTS_THRESHOLD;
+ if (accelerate) {
+ Services.prefs.setBoolPref(PREF_ACCELERATE_RECALCULATION, true);
+ this.#createOrUpdateTask();
+ }
+ this.#lastEventsCount = eventsCount;
+ return accelerate;
+ }
+
+ #resetRecalculationSpeed() {
+ if (lazy.accelerationRate > 1) {
+ Services.prefs.clearUserPref(PREF_ACCELERATE_RECALCULATION);
+ this.#createOrUpdateTask();
+ }
+ }
+
/**
* Updates a chunk of outdated frecency values. If there's more frecency
* values to update at the end of the process, it may rearm the task.
@@ -169,6 +235,8 @@ export class PlacesFrecencyRecalculator {
* @resolves {boolean} Whether any entry was recalculated.
*/
async recalculateSomeFrecencies({ chunkSize = DEFAULT_CHUNK_SIZE } = {}) {
+ // In case of acceleration we don't bump up the chunkSize to avoid issues
+ // with slow disk systems.
lazy.logger.trace(
`Recalculate ${chunkSize >= 0 ? chunkSize : "infinite"} frecency values`
);
@@ -182,7 +250,7 @@ export class PlacesFrecencyRecalculator {
WHERE id IN (
SELECT id FROM moz_places
WHERE recalc_frecency = 1
- ORDER BY frecency DESC
+ ORDER BY frecency DESC, visit_count DESC
LIMIT ${chunkSize}
)
RETURNING id`
@@ -212,8 +280,10 @@ export class PlacesFrecencyRecalculator {
if (chunkSize > 0 && shouldRestartRecalculation) {
// There's more entries to recalculate, rearm the task.
+ this.maybeUpdateRecalculationSpeed();
this.#task.arm();
} else {
+ this.#resetRecalculationSpeed();
// There's nothing left to recalculate, wait for the next change.
lazy.PlacesUtils.history.shouldStartFrecencyRecalculation = false;
this.#task.disarm();
@@ -360,6 +430,7 @@ export class PlacesFrecencyRecalculator {
return;
case "frecency-recalculation-needed":
lazy.logger.trace("Frecency recalculation requested");
+ this.maybeUpdateRecalculationSpeed();
this.maybeStartFrecencyRecalculation();
return;
case "test-execute-taskFn":