Chromium Code Reviews| Index: tracing/tracing/extras/importer/heap_dump_trace_event_importer.html |
| diff --git a/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html b/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html |
| index 80e01000d73e8745da44fedb9f101b49430b62da..4c8e934ed155e34fbf72ef804097e324cbfe7738 100644 |
| --- a/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html |
| +++ b/tracing/tracing/extras/importer/heap_dump_trace_event_importer.html |
| @@ -1,6 +1,7 @@ |
| <!DOCTYPE html> |
| + |
| <!-- |
| -Copyright 2016 The Chromium Authors. All rights reserved. |
| +Copyright 2017 The Chromium Authors. All rights reserved. |
|
Primiano Tucci (use gerrit)
2017/03/22 15:53:52
I think the rule is to never update years for exis
fmeawad
2017/03/23 20:43:57
The original file was moved to legacy_, so in prac
|
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| @@ -16,169 +17,72 @@ found in the LICENSE file. |
| tr.exportTo('tr.e.importer', function() { |
| /** |
| * @constructor |
| - * @param {!tr.model.Model} model The model we are currently building. |
| - * @param {!tr.model.ProcessMemoryDump} processMemoryDump |
| - * The parent memory dump for this heap dump. |
| - * @param {!Map|undefined} processObjectTypeNameMap |
| - * A map from raw heap dump 'type' ids to human-readable names. |
| - * @param {!string} idPrefix Process-specific prefix to prepend to a stack |
| - * trace id before looking it up in the model. |
| - * @param {!string} dumpId |
| - * Raw heap dump id, used only for nice error messages. |
| */ |
| function HeapDumpTraceEventImporter( |
| - model, processMemoryDump, processObjectTypeNameMap, idPrefix, dumpId) { |
| - this.model_ = model; |
| - this.processObjectTypeNameMap_ = processObjectTypeNameMap; |
| - this.idPrefix_ = idPrefix; |
| - this.processMemoryDump_ = processMemoryDump; |
| - this.pid_ = this.processMemoryDump_.process.pid; |
| - this.dumpId_ = dumpId; |
| + heapProfileEventExpander, |
| + stackFrames, |
| + processMemoryDump, |
| + idPrefix, |
| + model) { |
| + this.expander = heapProfileEventExpander; |
| + this.stackFrames = stackFrames; |
| + this.processMemoryDump = processMemoryDump; |
| + this.idPrefix = idPrefix; |
| + this.model = model; |
| } |
| HeapDumpTraceEventImporter.prototype = { |
| - /** |
| - * Parse rawHeapDump and add entries to heapDump. |
| - * |
| - * @param {!{!entries:(!Array<!Object>|undefined)}} rawHeapDump |
| - * The data we're going to parse. |
| - * @param {!string} allocatorName e.g. malloc. |
| - * @return {!tr.model.HeapDump} on success or undefined on an error. |
| - */ |
| - parseRawHeapDump: function(rawHeapDump, allocatorName) { |
| - var model = this.model_; |
| - var processMemoryDump = this.processMemoryDump_; |
| - var heapDump = new tr.model.HeapDump(processMemoryDump, allocatorName); |
| - var entries = rawHeapDump.entries; |
| - if (entries === undefined || entries.length === 0) { |
| - this.model_.importWarning({ |
| - type: 'memory_dump_parse_error', |
| - message: 'No heap entries in a ' + allocatorName + |
| - ' heap dump for PID=' + this.pid_ + |
| - ' and dump ID=' + this.dumpId_ + '.' |
| - }); |
| + getLeafStackFrame: function(stackFrameId) { |
| + // Root. |
| + if (stackFrameId === '') return undefined; |
| + let parentId = this.idPrefix + stackFrameId; |
| + let id = parentId + ':self'; |
| - return undefined; |
| + // In the new format all values are 'self' values, |
| + // we distingiush these from the totals in the UI via |
| + // artificial '<self>' stack frames. |
| + if (!this.stackFrames[id]) { |
| + let parentStackFrame = this.stackFrames[parentId]; |
| + let stackFrame = new tr.model.StackFrame( |
| + parentStackFrame, id, '<self>', |
| + undefined /* colorId */); |
| + this.model.addStackFrame(stackFrame); |
| } |
| + return this.stackFrames[id]; |
| + }, |
| - // The old format always starts with a {size: <total>} entry. |
| - // See https://goo.gl/WYStil |
| - // TODO(petrcermak): Remove support for the old format once the new |
| - // format has been around long enough. |
| - var isOldFormat = entries[0].bt === undefined; |
| - if (!isOldFormat && this.processObjectTypeNameMap_ === undefined) { |
| - // Mapping from object type IDs to names must be provided in the new |
| - // format. |
| - return undefined; |
| + parseEntry: function(entry, heapDump) { |
| + let size = entry.size; |
| + let count = entry.count; |
| + let leafStackFrame = this.getLeafStackFrame(entry.node.id); |
| + let objectTypeName = entry.type.name; |
| + let valuesAreSelf = true; |
| + if (objectTypeName === undefined) { |
| + this.model_.importWarning({ |
| + type: 'memory_dump_parse_error', |
| + message: 'Missing object type name (ID ' + typeId + ')', |
| + }); |
| } |
| + heapDump.addEntry( |
| + leafStackFrame, objectTypeName, size, count, valuesAreSelf); |
| + }, |
| - for (var i = 0; i < entries.length; i++) { |
| - var entry = entries[i]; |
| - var leafStackFrameIndex = entry.bt; |
| - var leafStackFrame; |
| - |
| - // There are two possible mappings from leaf stack frame indices |
| - // (provided in the trace) to the corresponding stack frames |
| - // depending on the format. |
| - if (isOldFormat) { |
| - // Old format: |
| - // Undefined index -> / (root) |
| - // Defined index for /A/B -> /A/B/<self> |
| - if (leafStackFrameIndex === undefined) { |
| - leafStackFrame = undefined; /* root */ |
| - } else { |
| - // Get the leaf stack frame corresponding to the provided index. |
| - var leafStackFrameId = this.idPrefix_ + leafStackFrameIndex; |
| - if (leafStackFrameIndex === '') { |
| - leafStackFrame = undefined; /* root */ |
| - } else { |
| - leafStackFrame = model.stackFrames[leafStackFrameId]; |
| - if (leafStackFrame === undefined) { |
| - this.model_.importWarning({ |
| - type: 'memory_dump_parse_error', |
| - message: 'Missing leaf stack frame (ID ' + |
| - leafStackFrameId + ') of heap entry ' + i + ' (size ' + |
| - size + ') in a ' + allocatorName + |
| - ' heap dump for PID=' + this.pid_ + '.' |
| - }); |
| - continue; |
| - } |
| - } |
| - |
| - // Inject an artificial <self> leaf stack frame. |
| - leafStackFrameId += ':self'; |
| - if (model.stackFrames[leafStackFrameId] !== undefined) { |
| - // The frame might already exist if there are multiple process |
| - // memory dumps (for the same process) in the trace. |
| - leafStackFrame = model.stackFrames[leafStackFrameId]; |
| - } else { |
| - leafStackFrame = new tr.model.StackFrame( |
| - leafStackFrame, leafStackFrameId, '<self>', |
| - undefined /* colorId */); |
| - model.addStackFrame(leafStackFrame); |
| - } |
| - } |
| - } else { |
| - // New format: |
| - // Undefined index -> (invalid value) |
| - // Defined index for /A/B -> /A/B |
| - if (leafStackFrameIndex === undefined) { |
| - this.model_.importWarning({ |
| - type: 'memory_dump_parse_error', |
| - message: 'Missing stack frame ID of heap entry ' + i + |
| - ' (size ' + size + ') in a ' + allocatorName + |
| - ' heap dump for PID=' + this.pid_ + '.' |
| - }); |
| - continue; |
| - } |
| - |
| - // Get the leaf stack frame corresponding to the provided index. |
| - var leafStackFrameId = this.idPrefix_ + leafStackFrameIndex; |
| - if (leafStackFrameIndex === '') { |
| - leafStackFrame = undefined; /* root */ |
| - } else { |
| - leafStackFrame = model.stackFrames[leafStackFrameId]; |
| - if (leafStackFrame === undefined) { |
| - this.model_.importWarning({ |
| - type: 'memory_dump_parse_error', |
| - message: 'Missing leaf stack frame (ID ' + leafStackFrameId + |
| - ') of heap entry ' + i + ' (size ' + size + ') in a ' + |
| - allocatorName + ' heap dump for PID=' + this.pid_ + '.' |
| - }); |
| - continue; |
| - } |
| - } |
| - } |
| - |
| - var objectTypeId = entry.type; |
| - var objectTypeName; |
| - if (objectTypeId === undefined) { |
| - objectTypeName = undefined; /* total over all types */ |
| - } else if (this.processObjectTypeNameMap_ === undefined) { |
| - // This can only happen when the old format is used. |
| - continue; |
| - } else { |
| - objectTypeName = this.processObjectTypeNameMap_[objectTypeId]; |
| - if (objectTypeName === undefined) { |
| - this.model_.importWarning({ |
| - type: 'memory_dump_parse_error', |
| - message: 'Missing object type name (ID ' + objectTypeId + |
| - ') of heap entry ' + i + ' (size ' + size + ') in a ' + |
| - allocatorName + ' heap dump for PID=' + this.pid_ + '.' |
| - }); |
| - continue; |
| - } |
| + parse: function() { |
| + let heapDumps = {}; |
| + let inflated = this.expander.inflated; |
| + for (let [allocatorName, entries] of Object.entries(inflated)) { |
| + let heapDump = |
| + new tr.model.HeapDump(this.processMemoryDump, allocatorName); |
| + for (let entry of entries) { |
| + this.parseEntry(entry, heapDump); |
| } |
| - |
| - var size = parseInt(entry.size, 16); |
| - var count = entry.count === undefined ? undefined : |
| - parseInt(entry.count, 16); |
| - heapDump.addEntry(leafStackFrame, objectTypeName, size, count); |
| + heapDump.isComplete = true; |
| + heapDumps[allocatorName] = heapDump; |
| } |
| - |
| - return heapDump; |
| + return heapDumps; |
| }, |
| + |
| }; |
| return { |