diff options
Diffstat (limited to 'browser/components/sessionstore/StartupPerformance.jsm')
-rw-r--r-- | browser/components/sessionstore/StartupPerformance.jsm | 234 |
1 files changed, 0 insertions, 234 deletions
diff --git a/browser/components/sessionstore/StartupPerformance.jsm b/browser/components/sessionstore/StartupPerformance.jsm deleted file mode 100644 index d1b77a237..000000000 --- a/browser/components/sessionstore/StartupPerformance.jsm +++ /dev/null @@ -1,234 +0,0 @@ -/* 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/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = ["StartupPerformance"]; - -const { utils: Cu, classes: Cc, interfaces: Ci } = Components; - -Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); - -XPCOMUtils.defineLazyModuleGetter(this, "Services", - "resource://gre/modules/Services.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "console", - "resource://gre/modules/Console.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "setTimeout", - "resource://gre/modules/Timer.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "clearTimeout", - "resource://gre/modules/Timer.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); - -const COLLECT_RESULTS_AFTER_MS = 10000; - -const OBSERVED_TOPICS = ["sessionstore-restoring-on-startup", "sessionstore-initiating-manual-restore"]; - -this.StartupPerformance = { - /** - * Once we have finished restoring initial tabs, we broadcast on this topic. - */ - RESTORED_TOPIC: "sessionstore-finished-restoring-initial-tabs", - - // Instant at which we have started restoration (notification "sessionstore-restoring-on-startup") - _startTimeStamp: null, - - // Latest instant at which we have finished restoring a tab (DOM event "SSTabRestored") - _latestRestoredTimeStamp: null, - - // A promise resolved once we have finished restoring all the startup tabs. - _promiseFinished: null, - - // Function `resolve()` for `_promiseFinished`. - _resolveFinished: null, - - // A timer - _deadlineTimer: null, - - // `true` once the timer has fired - _hasFired: false, - - // `true` once we are restored - _isRestored: false, - - // Statistics on the session we need to restore. - _totalNumberOfEagerTabs: 0, - _totalNumberOfTabs: 0, - _totalNumberOfWindows: 0, - - init: function() { - for (let topic of OBSERVED_TOPICS) { - Services.obs.addObserver(this, topic, false); - } - }, - - /** - * Return the timestamp at which we finished restoring the latest tab. - * - * This information is not really interesting until we have finished restoring - * tabs. - */ - get latestRestoredTimeStamp() { - return this._latestRestoredTimeStamp; - }, - - /** - * `true` once we have finished restoring startup tabs. - */ - get isRestored() { - return this._isRestored; - }, - - // Called when restoration starts. - // Record the start timestamp, setup the timer and `this._promiseFinished`. - // Behavior is unspecified if there was already an ongoing measure. - _onRestorationStarts: function(isAutoRestore) { - this._latestRestoredTimeStamp = this._startTimeStamp = Date.now(); - this._totalNumberOfEagerTabs = 0; - this._totalNumberOfTabs = 0; - this._totalNumberOfWindows = 0; - - // While we may restore several sessions in a single run of the browser, - // that's a very unusual case, and not really worth measuring, so let's - // stop listening for further restorations. - - for (let topic of OBSERVED_TOPICS) { - Services.obs.removeObserver(this, topic); - } - - Services.obs.addObserver(this, "sessionstore-single-window-restored", false); - this._promiseFinished = new Promise(resolve => { - this._resolveFinished = resolve; - }); - this._promiseFinished.then(() => { - try { - this._isRestored = true; - Services.obs.notifyObservers(null, this.RESTORED_TOPIC, ""); - - if (this._latestRestoredTimeStamp == this._startTimeStamp) { - // Apparently, we haven't restored any tab. - return; - } - - // Once we are done restoring tabs, update Telemetry. - let histogramName = isAutoRestore ? - "FX_SESSION_RESTORE_AUTO_RESTORE_DURATION_UNTIL_EAGER_TABS_RESTORED_MS" : - "FX_SESSION_RESTORE_MANUAL_RESTORE_DURATION_UNTIL_EAGER_TABS_RESTORED_MS"; - let histogram = Services.telemetry.getHistogramById(histogramName); - let delta = this._latestRestoredTimeStamp - this._startTimeStamp; - histogram.add(delta); - - Services.telemetry.getHistogramById("FX_SESSION_RESTORE_NUMBER_OF_EAGER_TABS_RESTORED").add(this._totalNumberOfEagerTabs); - Services.telemetry.getHistogramById("FX_SESSION_RESTORE_NUMBER_OF_TABS_RESTORED").add(this._totalNumberOfTabs); - Services.telemetry.getHistogramById("FX_SESSION_RESTORE_NUMBER_OF_WINDOWS_RESTORED").add(this._totalNumberOfWindows); - - // Reset - this._startTimeStamp = null; - } catch (ex) { - console.error("StartupPerformance: error after resolving promise", ex); - } - }); - }, - - _startTimer: function() { - if (this._hasFired) { - return; - } - if (this._deadlineTimer) { - clearTimeout(this._deadlineTimer); - } - this._deadlineTimer = setTimeout(() => { - try { - this._resolveFinished(); - } catch (ex) { - console.error("StartupPerformance: Error in timeout handler", ex); - } finally { - // Clean up. - this._deadlineTimer = null; - this._hasFired = true; - this._resolveFinished = null; - Services.obs.removeObserver(this, "sessionstore-single-window-restored"); - } - }, COLLECT_RESULTS_AFTER_MS); - }, - - observe: function(subject, topic, details) { - try { - switch (topic) { - case "sessionstore-restoring-on-startup": - this._onRestorationStarts(true); - break; - case "sessionstore-initiating-manual-restore": - this._onRestorationStarts(false); - break; - case "sessionstore-single-window-restored": { - // Session Restore has just opened a window with (initially empty) tabs. - // Some of these tabs will be restored eagerly, while others will be - // restored on demand. The process becomes usable only when all windows - // have finished restored their eager tabs. - // - // While it would be possible to track the restoration of each tab - // from within SessionRestore to determine exactly when the process - // becomes usable, experience shows that this is too invasive. Rather, - // we employ the following heuristic: - // - we maintain a timer of `COLLECT_RESULTS_AFTER_MS` that we expect - // will be triggered only once all tabs have been restored; - // - whenever we restore a new window (hence a bunch of eager tabs), - // we postpone the timer to ensure that the new eager tabs have - // `COLLECT_RESULTS_AFTER_MS` to be restored; - // - whenever a tab is restored, we update - // `this._latestRestoredTimeStamp`; - // - after `COLLECT_RESULTS_AFTER_MS`, we collect the final version - // of `this._latestRestoredTimeStamp`, and use it to determine the - // entire duration of the collection. - // - // Note that this heuristic may be inaccurate if a user clicks - // immediately on a restore-on-demand tab before the end of - // `COLLECT_RESULTS_AFTER_MS`. We assume that this will not - // affect too much the results. - // - // Reset the delay, to give the tabs a little (more) time to restore. - this._startTimer(); - - this._totalNumberOfWindows += 1; - - // Observe the restoration of all tabs. We assume that all tabs of this - // window will have been restored before `COLLECT_RESULTS_AFTER_MS`. - // The last call to `observer` will let us determine how long it took - // to reach that point. - let win = subject; - - let observer = (event) => { - // We don't care about tab restorations that are due to - // a browser flipping from out-of-main-process to in-main-process - // or vice-versa. We only care about restorations that are due - // to the user switching to a lazily restored tab, or for tabs - // that are restoring eagerly. - if (!event.detail.isRemotenessUpdate) { - this._latestRestoredTimeStamp = Date.now(); - this._totalNumberOfEagerTabs += 1; - } - }; - win.gBrowser.tabContainer.addEventListener("SSTabRestored", observer); - this._totalNumberOfTabs += win.gBrowser.tabContainer.itemCount; - - // Once we have finished collecting the results, clean up the observers. - this._promiseFinished.then(() => { - if (!win.gBrowser.tabContainer) { - // May be undefined during shutdown and/or some tests. - return; - } - win.gBrowser.tabContainer.removeEventListener("SSTabRestored", observer); - }); - } - break; - default: - throw new Error(`Unexpected topic ${topic}`); - } - } catch (ex) { - console.error("StartupPerformance error", ex, ex.stack); - throw ex; - } - } -}; |