| 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>
|
|
|