Bug 993084 - Delay initialization of telemetry experiments if there is no active experiment. r=bsmedberg

To sync experiment state with the addon manager, we need to start it early when there is a
active experiment.
However, initializing the telemetry experiments system too early can lead to performance
regressions, so we delay the initialization if we don't have an active experiment.
This commit is contained in:
Georg Fritzsche 2014-04-15 18:12:26 +02:00
parent 28cd4fa967
commit c63002da12
2 changed files with 63 additions and 11 deletions

View File

@ -58,6 +58,7 @@ const MIN_EXPERIMENT_ACTIVE_SECONDS = 60;
const PREF_BRANCH = "experiments.";
const PREF_ENABLED = "enabled"; // experiments.enabled
const PREF_ACTIVE_EXPERIMENT = "activeExperiment"; // whether we have an active experiment
const PREF_LOGGING = "logging";
const PREF_LOGGING_LEVEL = PREF_LOGGING + ".level"; // experiments.logging.level
const PREF_LOGGING_DUMP = PREF_LOGGING + ".dump"; // experiments.logging.dump
@ -975,6 +976,11 @@ Experiments.Experiments.prototype = {
let activeChanged = false;
let now = this._policy.now();
if (!activeExperiment) {
// Avoid this pref staying out of sync if there were e.g. crashes.
gPrefs.set(PREF_ACTIVE_EXPERIMENT, false);
}
if (activeExperiment) {
this._pendingUninstall = activeExperiment._addonId;
try {
@ -1484,6 +1490,7 @@ Experiments.ExperimentEntry.prototype = {
}
yield this._installAddon();
gPrefs.set(PREF_ACTIVE_EXPERIMENT, true);
}.bind(this));
},
@ -1604,6 +1611,8 @@ Experiments.ExperimentEntry.prototype = {
}
this._enabled = false;
gPrefs.set(PREF_ACTIVE_EXPERIMENT, false);
let deferred = Promise.defer();
let updateDates = () => {
let now = this._policy.now();
@ -1851,8 +1860,6 @@ ExperimentsProvider.prototype = Object.freeze({
],
postInit: function () {
this._experiments = Experiments.instance();
for (let o of this._OBSERVERS) {
Services.obs.addObserver(this, o, false);
}
@ -1881,6 +1888,14 @@ ExperimentsProvider.prototype = Object.freeze({
},
recordLastActiveExperiment: function () {
if (!gExperimentsEnabled) {
return;
}
if (!this._experiments) {
this._experiments = Experiments.instance();
}
let m = this.getMeasurement(ExperimentsLastActiveMeasurement1.prototype.name,
ExperimentsLastActiveMeasurement1.prototype.version);

View File

@ -8,29 +8,41 @@ const {interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Experiments",
"resource:///modules/experiments/Experiments.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "OS",
"resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
"resource://services-common/utils.js");
const PREF_EXPERIMENTS_ENABLED = "experiments.enabled";
const PREF_ACTIVE_EXPERIMENT = "experiments.activeExperiment"; // whether we have an active experiment
const PREF_HEALTHREPORT_ENABLED = "datareporting.healthreport.service.enabled";
const PREF_TELEMETRY_ENABLED = "toolkit.telemetry.enabled";
const DELAY_INIT_MS = 30 * 1000;
XPCOMUtils.defineLazyGetter(
this, "gPrefs", () => {
return new Preferences();
});
XPCOMUtils.defineLazyGetter(
this, "gExperimentsEnabled", () => {
try {
let prefs = Services.prefs;
return prefs.getBoolPref(PREF_EXPERIMENTS_ENABLED) &&
prefs.getBoolPref(PREF_TELEMETRY_ENABLED) &&
prefs.getBoolPref(PREF_HEALTHREPORT_ENABLED);
} catch (e) {
return false;
}
return gPrefs.get(PREF_EXPERIMENTS_ENABLED, false) &&
gPrefs.get(PREF_TELEMETRY_ENABLED, false) &&
gPrefs.get(PREF_HEALTHREPORT_ENABLED, false);
});
XPCOMUtils.defineLazyGetter(
this, "gActiveExperiment", () => {
return gPrefs.get(PREF_ACTIVE_EXPERIMENT);
});
function ExperimentsService() {
this._initialized = false;
this._delayedInitTimer = null;
}
ExperimentsService.prototype = {
@ -47,11 +59,36 @@ ExperimentsService.prototype = {
Experiments.instance().updateManifest();
},
_delayedInit: function () {
if (!this._initialized) {
this._initialized = true;
Experiments.instance(); // for side effects
}
},
observe: function (subject, topic, data) {
switch (topic) {
case "profile-after-change":
if (gExperimentsEnabled) {
Experiments.instance(); // for side effects
Services.obs.addObserver(this, "quit-application", false);
Services.obs.addObserver(this, "sessionstore-state-finalized", false);
if (gActiveExperiment) {
this._initialized = true;
Experiments.instance(); // for side effects
}
}
break;
case "sessionstore-state-finalized":
if (!this._initialized) {
CommonUtils.namedTimer(this._delayedInit, DELAY_INIT_MS, this, "_delayedInitTimer");
}
break;
case "quit-application":
Services.obs.removeObserver(this, "quit-application");
Services.obs.removeObserver(this, "sessionstore-state-finalized");
if (this._delayedInitTimer) {
this._delayedInitTimer.clear();
}
break;
}