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