| 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 e11e40313f0e369e517640e1ed1fb1862d6b7e64..e22671b6359bbcba0bdecc47e9f52d107b2a1feb 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,6 @@
|
| <!DOCTYPE html>
|
| <!--
|
| -Copyright 2016 The Chromium Authors. All rights reserved.
|
| +Copyright 2017 The Chromium Authors. All rights reserved.
|
| Use of this source code is governed by a BSD-style license that can be
|
| found in the LICENSE file.
|
| -->
|
| @@ -16,169 +16,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;
|
| + heapProfileExpander,
|
| + stackFrames,
|
| + processMemoryDump,
|
| + idPrefix,
|
| + model) {
|
| + this.expander = heapProfileExpander;
|
| + 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(rawHeapDump, allocatorName) {
|
| - const model = this.model_;
|
| - const processMemoryDump = this.processMemoryDump_;
|
| - const heapDump = new tr.model.HeapDump(processMemoryDump, allocatorName);
|
|
|
| - const 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(stackFrameId) {
|
| + // Root.
|
| + if (stackFrameId === '') return undefined;
|
| + const parentId = this.idPrefix + stackFrameId;
|
| + const 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]) {
|
| + const parentStackFrame = this.stackFrames[parentId];
|
| + const 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.
|
| - const 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(entry, heapDump) {
|
| + const size = entry.size;
|
| + const count = entry.count;
|
| + const leafStackFrame = this.getLeafStackFrame(entry.node.id);
|
| + const objectTypeName = entry.type.name;
|
| + const valuesAreTotals = false;
|
| + if (objectTypeName === undefined) {
|
| + this.model_.importWarning({
|
| + type: 'memory_dump_parse_error',
|
| + message: 'Missing object type name (ID ' + typeId + ')',
|
| + });
|
| }
|
| + heapDump.addEntry(
|
| + leafStackFrame, objectTypeName, size, count, valuesAreTotals);
|
| + },
|
|
|
| - for (let i = 0; i < entries.length; i++) {
|
| - const entry = entries[i];
|
| - const size = parseInt(entry.size, 16);
|
| - const leafStackFrameIndex = entry.bt;
|
| - let 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.
|
| - let 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.
|
| - const 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;
|
| - }
|
| - }
|
| - }
|
| -
|
| - const objectTypeId = entry.type;
|
| - let 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() {
|
| + const heapDumps = {};
|
| + const inflated = this.expander.inflated;
|
| + for (const [allocatorName, entries] of Object.entries(inflated)) {
|
| + const heapDump =
|
| + new tr.model.HeapDump(this.processMemoryDump, allocatorName);
|
| + for (const entry of entries) {
|
| + this.parseEntry(entry, heapDump);
|
| }
|
| -
|
| - const 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 {
|
|
|