diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/components/places/PlacesFrecencyRecalculator.sys.mjs | 83 |
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": |