| Index: tools/telemetry/telemetry/core/heap/chrome_js_heap_snapshot_parser.py
|
| diff --git a/tools/telemetry/telemetry/core/heap/chrome_js_heap_snapshot_parser.py b/tools/telemetry/telemetry/core/heap/chrome_js_heap_snapshot_parser.py
|
| deleted file mode 100644
|
| index 9706dad4b768c260aa69caa5d03fd51521300410..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/telemetry/core/heap/chrome_js_heap_snapshot_parser.py
|
| +++ /dev/null
|
| @@ -1,248 +0,0 @@
|
| -# Copyright 2013 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.
|
| -
|
| -import json
|
| -
|
| -from telemetry.core.heap import live_heap_object
|
| -from telemetry.core.heap import retaining_edge
|
| -
|
| -
|
| -class ChromeJsHeapSnapshotParser(object):
|
| - """ Parser for the heap snapshot.
|
| -
|
| - The heap snapshot JSON format is defined by HeapSnapshotJSONSerializer in V8.
|
| -
|
| - The snapshot contains a list of integers describing nodes (types, names, etc.)
|
| - and a list of integers describing edges (types, the node the edge points to,
|
| - etc.) and a string table. All strings are expressed as indices to the string
|
| - table.
|
| -
|
| - In addition, the snapshot contains meta information describing the data fields
|
| - for nodes and the data fields for edges.
|
| -
|
| - Attributes:
|
| - _node_dict: {int -> LiveHeapObject}, maps integer ids to LiveHeapObject
|
| - objects.
|
| - _node_list: [int], the raw node data of the heap snapshot.
|
| - _edge_list: [int], the raw edge data of the heap snapshot.
|
| - _node_types: [str], the possible node types in the heap snapshot.
|
| - _edge_types: [str], the possible edge types in the heap snapshot.
|
| - _node_fields: [str], the fields present in the heap snapshot for each node.
|
| - _edge_fields: [str], the fields present in the heap snapshot for each node.
|
| - _node_type_ix: int, index of the node type field.
|
| - _node_name_ix: int, index of the node name field.
|
| - _node_id_ix: int, index of the node id field.
|
| - _node_edge_count_ix: int, index of the node edge count field.
|
| - _node_field_count: int, number of node fields.
|
| - _edge_type_ix: int, index of the edge type field.
|
| - _edge_name_or_ix_ix: int, index of the "edge name or index" field.
|
| - _edge_to_node_ix: int, index of the "to node for an edge" field.
|
| - _edge_field_count: int, number of edge fields.
|
| - """
|
| -
|
| - def __init__(self, raw_data):
|
| - heap = json.loads(raw_data)
|
| - self._node_dict = {}
|
| -
|
| - # Read the snapshot components (nodes, edges, strings, metadata).
|
| - self._node_list = heap['nodes']
|
| - self._edge_list = heap['edges']
|
| - self._strings = heap['strings']
|
| -
|
| - self._node_types = heap['snapshot']['meta']['node_types'][0]
|
| - self._edge_types = heap['snapshot']['meta']['edge_types'][0]
|
| - node_fields = heap['snapshot']['meta']['node_fields']
|
| - edge_fields = heap['snapshot']['meta']['edge_fields']
|
| -
|
| - # Find the indices of the required node and edge fields based on the
|
| - # metadata.
|
| - self._node_type_ix = node_fields.index('type')
|
| - self._node_name_ix = node_fields.index('name')
|
| - self._node_id_ix = node_fields.index('id')
|
| - self._node_edge_count_ix = node_fields.index('edge_count')
|
| - self._node_field_count = len(node_fields)
|
| -
|
| - self._edge_type_ix = edge_fields.index('type')
|
| - self._edge_name_or_ix_ix = edge_fields.index('name_or_index')
|
| - self._edge_to_node_ix = edge_fields.index('to_node')
|
| - self._edge_field_count = len(edge_fields)
|
| -
|
| - self._ParseSnapshot()
|
| -
|
| - @staticmethod
|
| - def CanImport(raw_data):
|
| - heap = json.loads(raw_data)
|
| - if ('nodes' not in heap or 'edges' not in heap or 'strings' not in heap or
|
| - 'snapshot' not in heap or 'meta' not in heap['snapshot']):
|
| - return False
|
| - meta = heap['snapshot']['meta']
|
| - if ('node_types' not in meta or 'edge_types' not in meta or
|
| - 'node_fields' not in meta or 'edge_fields' not in meta):
|
| - return False
|
| - node_fields = meta['node_fields']
|
| - edge_fields = meta['edge_fields']
|
| - if ('type' not in node_fields or 'name' not in node_fields or
|
| - 'id' not in node_fields or 'edge_count' not in node_fields):
|
| - return False
|
| - if ('type' not in edge_fields or 'name_or_index' not in edge_fields or
|
| - 'to_node' not in edge_fields):
|
| - return False
|
| - return True
|
| -
|
| - def GetAllLiveHeapObjects(self):
|
| - return self._node_dict.values()
|
| -
|
| - @staticmethod
|
| - def LiveHeapObjectToJavaScript(heap_object):
|
| - return heap_object.name or str(heap_object)
|
| -
|
| - @staticmethod
|
| - def RetainingEdgeToJavaScript(edge):
|
| - if edge.type_string == 'property':
|
| - return '.' + edge.name_string
|
| - if edge.type_string == 'element':
|
| - return '[' + edge.name_string + ']'
|
| - return str(edge)
|
| -
|
| - def _ParseSnapshot(self):
|
| - """Parses the stored JSON snapshot data.
|
| -
|
| - Fills in self._node_dict with LiveHeapObject objects constructed based on
|
| - the heap snapshot. The LiveHeapObject objects contain the associated
|
| - RetainingEdge objects.
|
| - """
|
| - edge_start_ix = 0
|
| - for ix in xrange(0, len(self._node_list), self._node_field_count):
|
| - edge_start_ix = self._ReadNodeFromIndex(ix, edge_start_ix)
|
| -
|
| - # Add pointers to the endpoints to the edges, and associate the edges with
|
| - # the "to" nodes.
|
| - for node_id in self._node_dict:
|
| - n = self._node_dict[node_id]
|
| - for e in n.edges_from:
|
| - self._node_dict[e.to_object_id].AddEdgeTo(e)
|
| - e.SetFromObject(n)
|
| - e.SetToObject(self._node_dict[e.to_object_id])
|
| -
|
| - def _ReadNodeFromIndex(self, ix, edges_start):
|
| - """Reads the data for a node from the heap snapshot.
|
| -
|
| - If the index contains an interesting node, constructs a Node object and adds
|
| - it to self._node_dict.
|
| -
|
| - Args:
|
| - ix: int, index into the self._node_list array.
|
| - edges_start: int, the index of the edge array where the edges for the node
|
| - start.
|
| - Returns:
|
| - int, the edge start index for the next node.
|
| -
|
| - Raises:
|
| - Exception: The node list of the snapshot is malformed.
|
| - """
|
| - if ix + self._node_field_count > len(self._node_list):
|
| - raise Exception('Snapshot node list too short')
|
| -
|
| - type_ix = self._node_list[ix + self._node_type_ix]
|
| - type_string = self._node_types[int(type_ix)]
|
| -
|
| - # edges_end is noninclusive (the index of the first edge that is not part of
|
| - # this node).
|
| - edge_count = self._node_list[ix + self._node_edge_count_ix]
|
| - edges_end = edges_start + edge_count * self._edge_field_count
|
| -
|
| - if ChromeJsHeapSnapshotParser._IsNodeTypeUninteresting(type_string):
|
| - return edges_end
|
| -
|
| - name_ix = self._node_list[ix + self._node_name_ix]
|
| - node_id = self._node_list[ix + self._node_id_ix]
|
| -
|
| - def ConstructorName(type_string, node_name_ix):
|
| - if type_string == 'object':
|
| - return self._strings[int(node_name_ix)]
|
| - return '(%s)' % type_string
|
| -
|
| - ctor_name = ConstructorName(type_string, name_ix)
|
| - n = live_heap_object.LiveHeapObject(node_id, type_string, ctor_name)
|
| - if type_string == 'string':
|
| - n.string = self._strings[int(name_ix)]
|
| -
|
| - for edge_ix in xrange(edges_start, edges_end, self._edge_field_count):
|
| - edge = self._ReadEdgeFromIndex(node_id, edge_ix)
|
| - if edge:
|
| - # The edge will be associated with the other endpoint when all the data
|
| - # has been read.
|
| - n.AddEdgeFrom(edge)
|
| -
|
| - self._node_dict[node_id] = n
|
| - return edges_end
|
| -
|
| - @staticmethod
|
| - def _IsNodeTypeUninteresting(type_string):
|
| - """Helper function for filtering out nodes from the heap snapshot.
|
| -
|
| - Args:
|
| - type_string: str, type of the node.
|
| - Returns:
|
| - bool, True if the node is of an uninteresting type and shouldn't be
|
| - included in the heap snapshot analysis.
|
| - """
|
| - uninteresting_types = ('hidden', 'code', 'number', 'native', 'synthetic')
|
| - return type_string in uninteresting_types
|
| -
|
| - @staticmethod
|
| - def _IsEdgeTypeUninteresting(edge_type_string):
|
| - """Helper function for filtering out edges from the heap snapshot.
|
| -
|
| - Args:
|
| - edge_type_string: str, type of the edge.
|
| - Returns:
|
| - bool, True if the edge is of an uninteresting type and shouldn't be
|
| - included in the heap snapshot analysis.
|
| - """
|
| - uninteresting_types = ('weak', 'hidden', 'internal')
|
| - return edge_type_string in uninteresting_types
|
| -
|
| - def _ReadEdgeFromIndex(self, node_id, edge_ix):
|
| - """Reads the data for an edge from the heap snapshot.
|
| -
|
| - Args:
|
| - node_id: int, id of the node which is the starting point of the edge.
|
| - edge_ix: int, index into the self._edge_list array.
|
| - Returns:
|
| - Edge, if the index contains an interesting edge, otherwise None.
|
| - Raises:
|
| - Exception: The node list of the snapshot is malformed.
|
| - """
|
| - if edge_ix + self._edge_field_count > len(self._edge_list):
|
| - raise Exception('Snapshot edge list too short')
|
| -
|
| - edge_type_ix = self._edge_list[edge_ix + self._edge_type_ix]
|
| - edge_type_string = self._edge_types[int(edge_type_ix)]
|
| -
|
| - if ChromeJsHeapSnapshotParser._IsEdgeTypeUninteresting(edge_type_string):
|
| - return None
|
| -
|
| - child_name_or_ix = self._edge_list[edge_ix + self._edge_name_or_ix_ix]
|
| - child_node_ix = self._edge_list[edge_ix + self._edge_to_node_ix]
|
| -
|
| - # The child_node_ix is an index into the node list. Read the actual
|
| - # node information.
|
| - child_node_type_ix = self._node_list[child_node_ix + self._node_type_ix]
|
| - child_node_type_string = self._node_types[int(child_node_type_ix)]
|
| - child_node_id = self._node_list[child_node_ix + self._node_id_ix]
|
| -
|
| - if ChromeJsHeapSnapshotParser._IsNodeTypeUninteresting(
|
| - child_node_type_string):
|
| - return None
|
| -
|
| - child_name_string = ''
|
| - # For element nodes, the child has no name (only an index).
|
| - if (edge_type_string == 'element' or
|
| - int(child_name_or_ix) >= len(self._strings)):
|
| - child_name_string = str(child_name_or_ix)
|
| - else:
|
| - child_name_string = self._strings[int(child_name_or_ix)]
|
| - return retaining_edge.RetainingEdge(node_id, child_node_id,
|
| - edge_type_string, child_name_string)
|
|
|