• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { AllocationFunction } from '../model/UiStruct';
17import { FileStruct, HeapTraceFunctionInfo } from '../model/DatabaseStruct';
18
19export class AllocationLogic {
20  private fileStruct: FileStruct;
21  private traceNodes: Array<AllocationFunction>;
22  private bottomUpList: Array<AllocationFunction>;
23
24  constructor(fileStruct: FileStruct) {
25    this.fileStruct = fileStruct;
26    this.bottomUpList = [];
27    this.traceNodes = this.fileStruct.snapshotStruct.traceNodes;
28    this.setBottomUpTree();
29  }
30
31  private setBottomUpTree(): void {
32    let keyMap = new Map<String, AllocationFunction>();
33    for (let node of this.traceNodes) {
34      if (node.parentsId.length > 1) {
35        node.hasParent = true;
36      } else if (node.parentsId.length === 0) {
37        node.hasParent = false;
38      } else {
39        if (node.parentsId[0] === -1) {
40          node.hasParent = false;
41        } else {
42          node.hasParent = true;
43        }
44      }
45      // combine node
46      if (keyMap.has(node.name + node.functionIndex)) {
47        let uniqueNode = keyMap.get(node.name + node.functionIndex);
48        if (!uniqueNode) {
49          continue;
50        }
51        uniqueNode.size += node.size;
52        uniqueNode.count += node.count;
53        uniqueNode.liveSize += node.liveSize;
54        uniqueNode.liveCount += node.liveCount;
55        uniqueNode.parentsId.push(...node.parentsId);
56        uniqueNode.combineId.add(uniqueNode.id);
57        uniqueNode.combineId.add(node.id);
58      } else {
59        keyMap.set(node.name + node.functionIndex, node);
60        node.combineId.add(node.id);
61        this.bottomUpList.push(node);
62      }
63    }
64    this.bottomUpList.sort(function (a, b) {
65      return b.size - a.size;
66    });
67  }
68
69  private getNodeById(id: number): AllocationFunction | null {
70    for (let func of this.bottomUpList) {
71      if (func.id === id) {
72        return func;
73      }
74    }
75    return null;
76  }
77
78  private getFunctionStack(node: AllocationFunction, functionList: Array<HeapTraceFunctionInfo>): void {
79    functionList.push(this.fileStruct.snapshotStruct.functionInfos[node.functionIndex]);
80    if (node.parentsId.length > 0) {
81      for (let parentId of node.parentsId) {
82        let parentNode = this.getNodeById(parentId);
83        if (parentNode) {
84          this.getFunctionStack(parentNode, functionList);
85        }
86      }
87    }
88  }
89
90  /**
91   * get Bottom Up FUnction List
92   * @returns bottomUpList
93   */
94  public getFunctionList(): Array<AllocationFunction> {
95    return this.bottomUpList;
96  }
97
98  /**
99   * set node parents node
100   * node has multi parent because bottom up combine multi node
101   * @param node selected node
102   */
103  public getParent(node: AllocationFunction): void {
104    if (node.hasParent) {
105      if (node.parentsId.length > 1) {
106        for (let childrenId of node.parentsId) {
107          let children = this.traceNodes[childrenId - 1].clone();
108          children.size = node.size;
109          children.count = node.count;
110          children.liveSize = node.liveSize;
111          children.liveCount = node.liveCount;
112          node.parents.push(children);
113        }
114      } else if ((node.parentsId.length = 1)) {
115        let childrenId = node.parentsId[0];
116        if (!node.parents) {
117          node.parents = [];
118        }
119        let children = this.traceNodes[childrenId - 1].clone();
120        children.size = node.size;
121        children.count = node.count;
122        children.liveSize = node.liveSize;
123        children.liveCount = node.liveCount;
124        node.parents.push(children);
125        this.getParent(children);
126      } else {
127        // no need to do anything
128      }
129    }
130  }
131
132  /**
133   * get use bottom up method combine's node ids
134   * @param allocationNodeId node id
135   * @returns node combine id
136   */
137  public getFunctionNodeIds(allocationNodeId: number): Array<number> {
138    let node = this.getNodeById(allocationNodeId);
139    if (node) {
140      return Array.from(node.combineId);
141    } else {
142      return [];
143    }
144  }
145
146  /**
147   * get full stack for node
148   * @param allocationNodeId node.traceNodeId
149   * @returns stack list
150   */
151  public getNodeStack(allocationNodeId: number): Array<HeapTraceFunctionInfo> {
152    let currentNode = this.getNodeById(allocationNodeId);
153    let functionList: HeapTraceFunctionInfo[] = [];
154    if (currentNode) {
155      this.getFunctionStack(currentNode, functionList);
156    }
157    return functionList;
158  }
159}
160