Bug 1159506 - Make GC events use TimeStamp. r=terrence
authorTom Tromey <tromey@mozilla.com>
Wed, 17 Jun 2015 15:14:00 -0400
changeset 280312 35091aff4234a3972cbc3b1cbe0de5f239f84cdf
parent 280311 df3415259fd58919248853d8f374838e338605fe
child 280313 53f268e9ab04ce53aa611444ccb038293a27aa1e
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1159506
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1159506 - Make GC events use TimeStamp. r=terrence
js/public/GCAPI.h
js/src/gc/Statistics.cpp
js/src/gc/Statistics.h
js/src/vm/Debugger.cpp
toolkit/devtools/shared/timeline.js
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -280,18 +280,18 @@ class GarbageCollectionEvent
     // Reference to a nullable, non-owned, statically allocated C string. If the
     // collection was forced to be non-incremental, this is a short reason of
     // why the GC could not perform an incremental collection.
     const char* nonincrementalReason;
 
     // Represents a single slice of a possibly multi-slice incremental garbage
     // collection.
     struct Collection {
-        int64_t startTimestamp;
-        int64_t endTimestamp;
+        double startTimestamp;
+        double endTimestamp;
     };
 
     // The set of garbage collection slices that made up this GC cycle.
     mozilla::Vector<Collection> collections;
 
     GarbageCollectionEvent(const GarbageCollectionEvent& rhs) = delete;
     GarbageCollectionEvent& operator=(const GarbageCollectionEvent& rhs) = delete;
 
--- a/js/src/gc/Statistics.cpp
+++ b/js/src/gc/Statistics.cpp
@@ -926,17 +926,17 @@ Statistics::beginSlice(const ZoneGCStats
                        SliceBudget budget, JS::gcreason::Reason reason)
 {
     this->zoneStats = zoneStats;
 
     bool first = !runtime->gc.isIncrementalGCInProgress();
     if (first)
         beginGC(gckind);
 
-    SliceData data(budget, reason, PRMJ_Now(), GetPageFaultCount());
+    SliceData data(budget, reason, PRMJ_Now(), JS_GetCurrentEmbedderTime(), GetPageFaultCount());
     if (!slices.append(data)) {
         // OOM testing fails if we CrashAtUnhandlableOOM here.
         aborted = true;
         return;
     }
 
     runtime->addTelemetry(JS_TELEMETRY_GC_REASON, reason);
 
@@ -949,16 +949,17 @@ Statistics::beginSlice(const ZoneGCStats
     }
 }
 
 void
 Statistics::endSlice()
 {
     if (!aborted) {
         slices.back().end = PRMJ_Now();
+        slices.back().endTimestamp = JS_GetCurrentEmbedderTime();
         slices.back().endFaults = GetPageFaultCount();
 
         int64_t sliceTime = slices.back().end - slices.back().start;
         runtime->addTelemetry(JS_TELEMETRY_GC_SLICE_MS, t(sliceTime));
         runtime->addTelemetry(JS_TELEMETRY_GC_RESET, !!slices.back().resetReason);
 
         if (slices.back().budget.isTimeBudget()) {
             int64_t budget = slices.back().budget.timeBudget.budget;
--- a/js/src/gc/Statistics.h
+++ b/js/src/gc/Statistics.h
@@ -206,29 +206,32 @@ struct Statistics
         if (phaseNestingDepth == 1)
             return phaseNesting[0] == PHASE_MUTATOR ? PHASE_NONE : phaseNesting[0];
         return phaseNesting[phaseNestingDepth - 1];
     }
 
     static const size_t MAX_NESTING = 20;
 
     struct SliceData {
-        SliceData(SliceBudget budget, JS::gcreason::Reason reason, int64_t start, size_t startFaults)
+        SliceData(SliceBudget budget, JS::gcreason::Reason reason, int64_t start,
+                  double startTimestamp, size_t startFaults)
           : budget(budget), reason(reason),
             resetReason(nullptr),
-            start(start), startFaults(startFaults)
+            start(start), startTimestamp(startTimestamp),
+            startFaults(startFaults)
         {
             for (auto i : mozilla::MakeRange(NumTimingArrays))
                 mozilla::PodArrayZero(phaseTimes[i]);
         }
 
         SliceBudget budget;
         JS::gcreason::Reason reason;
         const char* resetReason;
         int64_t start, end;
+        double startTimestamp, endTimestamp;
         size_t startFaults, endFaults;
         PhaseTimeTable phaseTimes;
 
         int64_t duration() const { return end - start; }
     };
 
     typedef Vector<SliceData, 8, SystemAllocPolicy> SliceDataVector;
     typedef SliceDataVector::ConstRange SliceRange;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8051,18 +8051,18 @@ GarbageCollectionEvent::Create(JSRuntime
             // same.
             data->reason = gcstats::ExplainReason(range.front().reason);
             MOZ_ASSERT(data->reason);
         }
 
         if (!data->collections.growBy(1))
             return nullptr;
 
-        data->collections.back().startTimestamp = range.front().start;
-        data->collections.back().endTimestamp = range.front().end;
+        data->collections.back().startTimestamp = range.front().startTimestamp;
+        data->collections.back().endTimestamp = range.front().endTimestamp;
     }
 
 
     return data;
 }
 
 static bool
 DefineStringProperty(JSContext* cx, HandleObject obj, PropertyName* propName, const char* strVal)
--- a/toolkit/devtools/shared/timeline.js
+++ b/toolkit/devtools/shared/timeline.js
@@ -177,19 +177,16 @@ let Timeline = exports.Timeline = Class(
    *         will be created regardless (to hook into GC events), but this determines
    *         whether or not a `memory` event gets fired.
    * @option {boolean} withTicks
    *         Boolean indicating whether a `ticks` event is fired and a FramerateActor
    *         is created.
    */
   start: Task.async(function *({ withMemory, withTicks }) {
     let startTime = this._startTime = this.docShells[0].now();
-    // Store the start time from unix epoch so we can normalize
-    // markers from the memory actor
-    this._unixStartTime = Date.now();
 
     if (this._isRecording) {
       return startTime;
     }
 
     this._isRecording = true;
     this._stackFrames = new StackFrameCache();
     this._stackFrames.initFrames();
@@ -261,25 +258,22 @@ let Timeline = exports.Timeline = Class(
    * why there was a GC, and may contain a `nonincrementalReason` when SpiderMonkey could
    * not incrementally collect garbage.
    */
   _onGarbageCollection: function ({ collections, reason, nonincrementalReason }) {
     if (!this._isRecording || !this.docShells.length) {
       return;
     }
 
-    // Normalize the start time to docshell start time, and convert it
-    // to microseconds.
-    let startTime = (this._unixStartTime - this._startTime) * 1000;
     let endTime = this.docShells[0].now();
 
     events.emit(this, "markers", collections.map(({ startTimestamp: start, endTimestamp: end }) => {
       return {
         name: "GarbageCollection",
         causeName: reason,
         nonincrementalReason: nonincrementalReason,
         // Both timestamps are in microseconds -- convert to milliseconds to match other markers
-        start: (start - startTime) / 1000,
-        end: (end - startTime) / 1000
+        start: start,
+        end: end
       };
     }), endTime);
   },
 });