github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/convert/flamebearersToTree.ts (about) 1 import type { Profile } from '@pyroscope/models/src'; 2 3 export interface TreeNode { 4 name: string; 5 key: string; 6 self: number[]; 7 total: number[]; 8 offset?: number; 9 children: TreeNode[]; 10 } 11 12 export function flamebearersToTree( 13 f1: Profile['flamebearer'], 14 f2?: Profile['flamebearer'] 15 ): TreeNode { 16 const globalLookup: { [key: string]: TreeNode } = {}; 17 const treeSpecificLookup: { [key: string]: TreeNode } = {}; 18 let root: TreeNode = { 19 name: 'total', 20 children: [], 21 self: [], 22 total: [], 23 key: '/total', 24 }; 25 26 (f2 ? [f1, f2] : [f1]).forEach((f, fi) => { 27 for (let i = 0; i < f.levels.length; i += 1) { 28 for (let j = 0; j < f.levels[i].length; j += 4) { 29 const treeSpecificKey: string = [fi, i, j].join('/'); 30 const name: string = f.names[f.levels[i][j + 3]]; 31 const offset: number = f.levels[i][j + 0]; 32 const total: number = f.levels[i][j + 1]; 33 const self: number = f.levels[i][j + 2]; 34 let parentGlobalKey = ''; 35 // searching for parent node 36 if (i !== 0) { 37 const pi = i - 1; 38 const parentLevel = f.levels[pi]; 39 for (let k = 0; k < parentLevel.length; k += 4) { 40 const parentOffset = parentLevel[k + 0]; 41 const total = parentLevel[k + 1]; 42 if (offset >= parentOffset && offset < parentOffset + total) { 43 const parentTreeSpecificKey = [fi, pi, k].join('/'); 44 const parentObj = treeSpecificLookup[parentTreeSpecificKey]; 45 parentGlobalKey = parentObj.key; 46 break; 47 } 48 } 49 } 50 51 const globalKey = [parentGlobalKey || '', name].join('/'); 52 const isNewObject = !globalLookup[globalKey]; 53 globalLookup[globalKey] ||= { 54 name, 55 children: [], 56 self: [], 57 total: [], 58 key: globalKey, 59 } as TreeNode; 60 const obj: TreeNode = globalLookup[globalKey]; 61 obj.total[fi] ||= 0; 62 obj.total[fi] += total; 63 obj.self[fi] ||= 0; 64 obj.self[fi] += self; 65 treeSpecificLookup[treeSpecificKey] = obj; 66 67 if (parentGlobalKey && isNewObject) { 68 globalLookup[parentGlobalKey].children.push(obj); 69 } 70 if (i === 0) { 71 root = obj; 72 } 73 } 74 } 75 }); 76 77 return root; 78 }