Bug 854606 - Use more SQLite transactions; r=rnewman, a=bajaj
authorGregory Szorc <gps@mozilla.com>
Tue, 26 Mar 2013 13:02:33 -0700
changeset 128725 a084be9582247c3e493288f2daae879827de202e
parent 128724 0488055e9f9ff56d760a10bd4552fd34b0f82b05
child 128726 d132b29c48cc1598ed5f287eeeb78586fc116d39
push id3568
push usergszorc@mozilla.com
push dateThu, 28 Mar 2013 22:57:01 +0000
treeherdermozilla-aurora@a084be958224 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman, bajaj
bugs854606
milestone21.0a2
Bug 854606 - Use more SQLite transactions; r=rnewman, a=bajaj
services/healthreport/providers.jsm
services/metrics/dataprovider.jsm
services/metrics/storage.jsm
--- a/services/healthreport/providers.jsm
+++ b/services/healthreport/providers.jsm
@@ -275,19 +275,17 @@ AppInfoProvider.prototype = Object.freez
     this._log.info("Recording new platform build ID: " + build);
     let m = this.getMeasurement("versions", 2);
     m.addDailyDiscreteText("platformBuildID", build);
     return this.setState("lastPlatformBuildID", build);
   },
 
 
   collectConstantData: function () {
-    return this.enqueueStorageOperation(function collect() {
-      return Task.spawn(this._populateConstants.bind(this));
-    }.bind(this));
+    return this.storage.enqueueTransaction(this._populateConstants.bind(this));
   },
 
   _populateConstants: function () {
     let m = this.getMeasurement(AppInfoMeasurement.prototype.name,
                                 AppInfoMeasurement.prototype.version);
 
     let ai;
     try {
@@ -420,19 +418,17 @@ SysInfoProvider.prototype = Object.freez
     device: "device",
     hardware: "hardware",
     name: "name",
     version: "version",
     arch: "architecture",
   },
 
   collectConstantData: function () {
-    return this.enqueueStorageOperation(function collection() {
-      return Task.spawn(this._populateConstants.bind(this));
-    }.bind(this));
+    return this.storage.enqueueTransaction(this._populateConstants.bind(this));
   },
 
   _populateConstants: function () {
     let m = this.getMeasurement(SysInfoMeasurement.prototype.name,
                                 SysInfoMeasurement.prototype.version);
 
     let si = Cc["@mozilla.org/system-info;1"]
                .getService(Ci.nsIPropertyBag2);
@@ -874,17 +870,17 @@ CrashesProvider.prototype = Object.freez
 
   name: "org.mozilla.crashes",
 
   measurementTypes: [DailyCrashesMeasurement],
 
   pullOnly: true,
 
   collectConstantData: function () {
-    return Task.spawn(this._populateCrashCounts.bind(this));
+    return this.storage.enqueueTransaction(this._populateCrashCounts.bind(this));
   },
 
   _populateCrashCounts: function () {
     let now = new Date();
     let service = new CrashDirectoryService();
 
     let pending = yield service.getPendingFiles();
     let submitted = yield service.getSubmittedFiles();
--- a/services/metrics/dataprovider.jsm
+++ b/services/metrics/dataprovider.jsm
@@ -177,22 +177,38 @@ Measurement.prototype = Object.freeze({
     if (!entry) {
       throw new Error("Unknown field: " + name);
     }
 
     return entry[1];
   },
 
   _configureStorage: function () {
-    return Task.spawn(function configureFields() {
-      for (let [name, info] in Iterator(this.fields)) {
-        this._log.debug("Registering field: " + name + " " + info.type);
+    let missing = [];
+    for (let [name, info] in Iterator(this.fields)) {
+      if (this.storage.hasFieldFromMeasurement(this.id, name)) {
+        this._fields[name] =
+          [this.storage.fieldIDFromMeasurement(this.id, name), info.type];
+        continue;
+      }
+
+      missing.push([name, info.type]);
+    }
 
-        let id = yield this.storage.registerField(this.id, name, info.type);
-        this._fields[name] = [id, info.type];
+    if (!missing.length) {
+      return CommonUtils.laterTickResolvingPromise();
+    }
+
+    // We only perform a transaction if we have work to do (to avoid
+    // extra SQLite overhead).
+    return this.storage.enqueueTransaction(function registerFields() {
+      for (let [name, type] of missing) {
+        this._log.debug("Registering field: " + name + " " + type);
+        let id = yield this.storage.registerField(this.id, name, type);
+        this._fields[name] = [id, type];
       }
     }.bind(this));
   },
 
   //---------------------------------------------------------------------------
   // Data Recording Functions
   //
   // Functions in this section are used to record new values against this
--- a/services/metrics/storage.jsm
+++ b/services/metrics/storage.jsm
@@ -1175,29 +1175,39 @@ MetricsStorageSqliteBackend.prototype = 
         let id = row.getResultByName("id");
         let name = row.getResultByName("name");
 
         self._typesByID.set(id, name);
         self._typesByName.set(name, id);
       });
 
       // 3. Populate built-in types with database.
+      let missingTypes = [];
       for (let type of self._BUILTIN_TYPES) {
         type = self[type];
         if (self._typesByName.has(type)) {
           continue;
         }
 
-        let params = {name: type};
-        yield self._connection.executeCached(SQL.addType, params);
-        let rows = yield self._connection.executeCached(SQL.getTypeID, params);
-        let id = rows[0].getResultByIndex(0);
+        missingTypes.push(type);
+      }
 
-        self._typesByID.set(id, type);
-        self._typesByName.set(type, id);
+      // Don't perform DB transaction unless there is work to do.
+      if (missingTypes.length) {
+        yield self._connection.executeTransaction(function populateBuiltinTypes() {
+          for (let type of missingTypes) {
+            let params = {name: type};
+            yield self._connection.executeCached(SQL.addType, params);
+            let rows = yield self._connection.executeCached(SQL.getTypeID, params);
+            let id = rows[0].getResultByIndex(0);
+
+            self._typesByID.set(id, type);
+            self._typesByName.set(type, id);
+          }
+        });
       }
 
       // 4. Obtain measurement info.
       yield self._connection.execute(SQL.getMeasurements, null, function onRow(row) {
         let providerID = row.getResultByName("provider_id");
         let providerName = row.getResultByName("provider_name");
         let measurementID = row.getResultByName("measurement_id");
         let measurementName = row.getResultByName("measurement_name");