Index: tracing/tracing/metrics/v8/utils.html |
diff --git a/tracing/tracing/metrics/v8/utils.html b/tracing/tracing/metrics/v8/utils.html |
index 1d561d0811f0fd5e6b89f9e159393dd270a65bed..f1ca8f23a6d1988cd32eab0b45d9c777a718b597 100644 |
--- a/tracing/tracing/metrics/v8/utils.html |
+++ b/tracing/tracing/metrics/v8/utils.html |
@@ -30,6 +30,9 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
var LOW_MEMORY_EVENT = 'V8.GCLowMemoryNotification'; |
+ var MAJOR_GC_EVENT = 'MajorGC'; |
+ var MINOR_GC_EVENT = 'MinorGC'; |
+ |
// Maps the top-level GC events in timeline to telemetry friendly names. |
var TOP_GC_EVENTS = { |
'V8.GCCompactor': 'v8-gc-full-mark-compactor', |
@@ -38,11 +41,12 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
'V8.GCIncrementalMarking': 'v8-gc-incremental-step', |
'V8.GCIncrementalMarkingFinalize': 'v8-gc-incremental-finalize', |
'V8.GCIncrementalMarkingStart': 'v8-gc-incremental-start', |
- 'V8.GCLowMemoryNotification': 'v8-gc-low-memory-mark-compactor', |
'V8.GCPhantomHandleProcessingCallback' : 'v8-gc-phantom-handle-callback', |
'V8.GCScavenger': 'v8-gc-scavenger' |
}; |
+ var LOW_MEMORY_MARK_COMPACTOR = 'v8-gc-low-memory-mark-compactor'; |
+ |
/** |
* Finds the first parent of the |event| for which the |predicate| holds. |
*/ |
@@ -84,9 +88,19 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
return event.title in TOP_GC_EVENTS; |
} |
+ function isForcedGarbageCollectionEvent(event) { |
+ return findParent(event, isLowMemoryEvent) !== null; |
+ } |
+ |
function isSubGarbageCollectionEvent(event) { |
+ // To reduce number of results, we return only the first level of GC |
+ // subevents. Some subevents are nested in MajorGC or MinorGC events, so |
+ // we have to check for it explicitly. |
return isGarbageCollectionEvent(event) && |
- !isTopGarbageCollectionEvent(event); |
+ event.parentSlice && |
+ (isTopGarbageCollectionEvent(event.parentSlice) || |
+ event.parentSlice.title === MAJOR_GC_EVENT || |
+ event.parentSlice.title === MINOR_GC_EVENT); |
} |
function topGarbageCollectionEventName(event) { |
@@ -94,7 +108,7 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
// Full mark compact events inside a low memory notification |
// are counted as low memory mark compacts. |
if (findParent(event, isLowMemoryEvent)) { |
- return TOP_GC_EVENTS[LOW_MEMORY_EVENT]; |
+ return LOW_MEMORY_MARK_COMPACTOR; |
} |
} |
return TOP_GC_EVENTS[event.title]; |
@@ -112,6 +126,29 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
} |
/** |
+ * Filters events using the |filterCallback|, then groups events by the user |
+ * the name computed using the |nameCallback|, and then invokes |
+ * the |processCallback| with the grouped events. |
+ * @param {Function} filterCallback Takes an event and returns a boolean. |
+ * @param {Function} nameCallback Takes event and returns a string. |
+ * @param {Function} processCallback Takes a name, and an array of events. |
+ */ |
+ function groupAndProcessEvents(model, filterCallback, |
+ nameCallback, processCallback) { |
+ // Map: name -> [events]. |
+ var nameToEvents = {}; |
+ for (var event of model.getDescendantEvents()) { |
+ if (!filterCallback(event)) continue; |
+ var name = nameCallback(event); |
+ nameToEvents[name] = nameToEvents[name] || []; |
+ nameToEvents[name].push(event); |
+ } |
+ tr.b.iterItems(nameToEvents, function(name, events) { |
+ processCallback(name, events); |
+ }); |
+ } |
+ |
+ /** |
* Given a list of intervals, returns a new list with all overalapping |
* intervals merged into a single interval. |
*/ |
@@ -238,19 +275,39 @@ tr.exportTo('tr.metrics.v8.utils', function() { |
return mu; |
} |
+ function hasV8Stats(globalMemoryDump) { |
+ var v8stats = undefined; |
+ globalMemoryDump.iterateContainerDumps(function(dump) { |
+ v8stats = v8stats || dump.getMemoryAllocatorDumpByFullName('v8'); |
+ }); |
+ return !!v8stats; |
+ } |
+ |
+ function rangeForMemoryDumps(model) { |
+ var startOfFirstDumpWithV8 = |
+ model.globalMemoryDumps.filter(hasV8Stats).reduce( |
+ (start, dump) => Math.min(start, dump.start), Infinity); |
+ if (startOfFirstDumpWithV8 === Infinity) |
+ return new tr.b.Range(); // Empty range. |
+ return tr.b.Range.fromExplicitRange(startOfFirstDumpWithV8, Infinity); |
+ } |
+ |
return { |
findParent: findParent, |
+ groupAndProcessEvents: groupAndProcessEvents, |
+ isForcedGarbageCollectionEvent: isForcedGarbageCollectionEvent, |
+ isGarbageCollectionEvent: isGarbageCollectionEvent, |
isIdleTask: isIdleTask, |
isLowMemoryEvent: isLowMemoryEvent, |
- isV8ExecuteEvent: isV8ExecuteEvent, |
- isTopV8ExecuteEvent: isTopV8ExecuteEvent, |
- isGarbageCollectionEvent: isGarbageCollectionEvent, |
- isTopGarbageCollectionEvent: isTopGarbageCollectionEvent, |
isSubGarbageCollectionEvent: isSubGarbageCollectionEvent, |
- topGarbageCollectionEventName: topGarbageCollectionEventName, |
+ isTopGarbageCollectionEvent: isTopGarbageCollectionEvent, |
+ isTopV8ExecuteEvent: isTopV8ExecuteEvent, |
+ isV8ExecuteEvent: isV8ExecuteEvent, |
+ mutatorUtilization: mutatorUtilization, |
subGarbageCollectionEventName: subGarbageCollectionEventName, |
- unionOfIntervals: unionOfIntervals, |
- mutatorUtilization: mutatorUtilization |
+ topGarbageCollectionEventName: topGarbageCollectionEventName, |
+ rangeForMemoryDumps: rangeForMemoryDumps, |
+ unionOfIntervals: unionOfIntervals |
}; |
}); |
</script> |