• 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.js';
17import { FileStruct, HeapTraceFunctionInfo } from '../model/DatabaseStruct.js';
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() {
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) continue;
49        uniqueNode.size += node.size;
50        uniqueNode.count += node.count;
51        uniqueNode.liveSize += node.liveSize;
52        uniqueNode.liveCount += node.liveCount;
53        uniqueNode.parentsId.push(...node.parentsId);
54        uniqueNode.combineId.add(uniqueNode.id);
55        uniqueNode.combineId.add(node.id);
56      } else {
57        keyMap.set(node.name + node.functionIndex, node);
58        node.combineId.add(node.id);
59        this.bottomUpList.push(node);
60      }
61    }
62    this.bottomUpList.sort(function (a, b) {
63      return b.size - a.size;
64    });
65  }
66
67  private getNodeById(id: number): AllocationFunction | null {
68    for (let func of this.bottomUpList) {
69      if (func.id == id) {
70        return func;
71      }
72    }
73    return null;
74  }
75
76  private getFunctionStack(node: AllocationFunction, functionList: Array<HeapTraceFunctionInfo>) {
77    functionList.push(this.fileStruct.snapshotStruct.functionInfos[node.functionIndex]);
78    if (node.parentsId.length > 0) {
79      for (let parentId of node.parentsId) {
80        let parentNode = this.getNodeById(parentId);
81        if (parentNode) {
82          this.getFunctionStack(parentNode, functionList);
83        }
84      }
85    }
86  }
87
88  /**
89   * get Bottom Up FUnction List
90   * @returns bottomUpList
91   */
92  public getFunctionList(): Array<AllocationFunction> {
93    return this.bottomUpList;
94  }
95
96  /**
97   * set node parents node
98   * node has multi parent because bottom up combine multi node
99   * @param node selected node
100   */
101  public getParent(node: AllocationFunction) {
102    if (node.hasParent) {
103      if (node.parentsId.length > 1) {
104        for (let childrenId of node.parentsId) {
105          let children = this.traceNodes[childrenId - 1].clone();
106          children.size = node.size;
107          children.count = node.count;
108          children.liveSize = node.liveSize;
109          children.liveCount = node.liveCount;
110          node.parents.push(children);
111        }
112      } else if ((node.parentsId.length = 1)) {
113        let childrenId = node.parentsId[0];
114        if (!node.parents) node.parents = new Array<AllocationFunction>();
115        let children = this.traceNodes[childrenId - 1].clone();
116        children.size = node.size;
117        children.count = node.count;
118        children.liveSize = node.liveSize;
119        children.liveCount = node.liveCount;
120        node.parents.push(children);
121        this.getParent(children);
122      } else {
123        // no need to do anything
124      }
125    }
126  }
127
128  /**
129   * get use bottom up method combine's node ids
130   * @param allocationNodeId node id
131   * @returns node combine id
132   */
133  public getFunctionNodeIds(allocationNodeId: number): Array<number> {
134    let node = this.getNodeById(allocationNodeId);
135    if (node) {
136      return Array.from(node.combineId);
137    } else {
138      return [];
139    }
140  }
141
142  /**
143   * get full stack for node
144   * @param allocationNodeId node.traceNodeId
145   * @returns stack list
146   */
147  public getNodeStack(allocationNodeId: number): Array<HeapTraceFunctionInfo> {
148    let currentNode = this.getNodeById(allocationNodeId);
149    let functionList = new Array<HeapTraceFunctionInfo>();
150    if (currentNode) {
151      this.getFunctionStack(currentNode, functionList);
152    }
153    return functionList;
154  }
155}
156