Bug 848136 - Part 2: Checkpoint WAL after data collection; r=rnewman, a=bajaj
authorGregory Szorc <gps@mozilla.com>
Tue, 26 Mar 2013 14:28:22 -0700
changeset 128724 0488055e9f9ff56d760a10bd4552fd34b0f82b05
parent 128723 b28fcc0c943f03cb91f5203eab618f7806dd2f46
child 128725 a084be9582247c3e493288f2daae879827de202e
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
bugs848136
milestone21.0a2
Bug 848136 - Part 2: Checkpoint WAL after data collection; r=rnewman, a=bajaj
services/healthreport/healthreporter.jsm
services/metrics/storage.jsm
toolkit/components/telemetry/Histograms.json
--- a/services/healthreport/healthreporter.jsm
+++ b/services/healthreport/healthreporter.jsm
@@ -47,16 +47,17 @@ const TELEMETRY_GENERATE_PAYLOAD = "HEAL
 const TELEMETRY_JSON_PAYLOAD_SERIALIZE = "HEALTHREPORT_JSON_PAYLOAD_SERIALIZE_MS";
 const TELEMETRY_PAYLOAD_SIZE = "HEALTHREPORT_PAYLOAD_UNCOMPRESSED_BYTES";
 const TELEMETRY_SAVE_LAST_PAYLOAD = "HEALTHREPORT_SAVE_LAST_PAYLOAD_MS";
 const TELEMETRY_UPLOAD = "HEALTHREPORT_UPLOAD_MS";
 const TELEMETRY_SHUTDOWN_DELAY = "HEALTHREPORT_SHUTDOWN_DELAY_MS";
 const TELEMETRY_COLLECT_CONSTANT = "HEALTHREPORT_COLLECT_CONSTANT_DATA_MS";
 const TELEMETRY_COLLECT_DAILY = "HEALTHREPORT_COLLECT_DAILY_MS";
 const TELEMETRY_SHUTDOWN = "HEALTHREPORT_SHUTDOWN_MS";
+const TELEMETRY_COLLECT_CHECKPOINT = "HEALTHREPORT_POST_COLLECT_CHECKPOINT_MS";
 
 /**
  * This is the abstract base class of `HealthReporter`. It exists so that
  * we can sanely divide work on platforms where control of Firefox Health
  * Report is outside of Gecko (e.g., Android).
  */
 function AbstractHealthReporter(branch, policy, sessionRecorder) {
   if (!branch.endsWith(".")) {
@@ -528,16 +529,28 @@ AbstractHealthReporter.prototype = Objec
           TelemetryStopwatch.finish(TELEMETRY_COLLECT_DAILY, this);
         } catch (ex) {
           TelemetryStopwatch.cancel(TELEMETRY_COLLECT_DAILY, this);
           this._log.warn("Error collecting daily data from providers: " +
                          CommonUtils.exceptionStr(ex));
         }
       }
 
+      // Flush gathered data to disk. This will incur an fsync. But, if
+      // there is ever a time we want to persist data to disk, it's
+      // after a massive collection.
+      try {
+        TelemetryStopwatch.start(TELEMETRY_COLLECT_CHECKPOINT, this);
+        yield this._storage.checkpoint();
+        TelemetryStopwatch.finish(TELEMETRY_COLLECT_CHECKPOINT, this);
+      } catch (ex) {
+        TelemetryStopwatch.cancel(TELEMETRY_COLLECT_CHECKPOINT, this);
+        throw ex;
+      }
+
       throw new Task.Result();
     }.bind(this));
   },
 
   /**
    * Helper function to perform data collection and obtain the JSON payload.
    *
    * If you are looking for an up-to-date snapshot of FHR data that pulls in
--- a/services/metrics/storage.jsm
+++ b/services/metrics/storage.jsm
@@ -1265,16 +1265,29 @@ MetricsStorageSqliteBackend.prototype = 
     let self = this;
     return this.enqueueOperation(function doCompact() {
       self._connection.discardCachedStatements();
       return self._connection.shrinkMemory();
     });
   },
 
   /**
+   * Checkpoint writes requiring flush to disk.
+   *
+   * This is called to persist queued and non-flushed writes to disk.
+   * It will force an fsync, so it is expensive and should be used
+   * sparingly.
+   */
+  checkpoint: function () {
+    return this.enqueueOperation(function checkpoint() {
+      return this._connection.execute("PRAGMA wal_checkpoint");
+    }.bind(this));
+  },
+
+  /**
    * Ensure a field ID matches a specified type.
    *
    * This is called internally as part of adding values to ensure that
    * the type of a field matches the operation being performed.
    */
   _ensureFieldType: function (id, type) {
     let info = this._fieldsByID.get(id);
 
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2917,16 +2917,22 @@
     "description": "Time (ms) it takes FHR to collect daily data."
   },
   "HEALTHREPORT_SHUTDOWN_MS": {
     "kind": "exponential",
     "high": "20000",
     "n_buckets": 15,
     "description": "Time (ms) it takes FHR to shut down."
   },
+  "HEALTHREPORT_POST_COLLECT_CHECKPOINT_MS": {
+    "kind": "exponential",
+    "high": "20000",
+    "n_buckets": 15,
+    "description": "Time (ms) for a WAL checkpoint after collecting all measurements."
+  },
   "POPUP_NOTIFICATION_MAINACTION_TRIGGERED_MS": {
     "kind": "linear",
     "low": 25,
     "high": "80 * 25",
     "n_buckets": "80 + 1",
     "description": "The time (in milliseconds) after showing a PopupNotification that the mainAction was first triggered"
   }
 }