• 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 */
15import { HeapDataInterface, ParseListener } from './HeapDataInterface.js';
16import { AllocationFunction, FileType } from './model/UiStruct.js';
17import { getTimeForLog } from './utils/Utils.js';
18import { HeapNode, FileStruct } from './model/DatabaseStruct.js';
19import {
20  queryHeapFile,
21  queryHeapInfo,
22  queryHeapNode,
23  queryHeapEdge,
24  queryHeapFunction,
25  queryHeapTraceNode,
26  queryHeapSample,
27  queryHeapString,
28} from '../trace/database/SqlLite.js';
29import { info } from '../log/Log.js';
30
31export class LoadDatabase {
32  private static loadDB: LoadDatabase;
33  private fileModule!: Array<FileStruct>;
34
35  static getInstance() {
36    if (!this.loadDB) {
37      this.loadDB = new LoadDatabase();
38    }
39    return this.loadDB;
40  }
41
42  private async loadFile(listener: ParseListener) {
43    this.fileModule = new Array<FileStruct>();
44    let result = await queryHeapFile();
45    listener.process('start loading file  ', 1);
46    for (let row of result) {
47      let fileStruct = new FileStruct();
48      fileStruct.id = row.id;
49      fileStruct.name = row.name;
50      fileStruct.startTs = row.startTs;
51      fileStruct.endTs = row.endTs;
52      fileStruct.pid = row.pid;
53      fileStruct.size = row.size;
54      if (fileStruct.name.startsWith('Snapshot')) {
55        fileStruct.type = FileType.SNAPSHOT;
56      } else {
57        fileStruct.type = FileType.TIMELINE;
58      }
59      info(`read ${fileStruct.name} from db  ${getTimeForLog()}`);
60      //fileStruct.profile.root_index = 0
61      await this.loadInfo(fileStruct);
62      await this.loadStrings(fileStruct);
63      await this.loadNode(fileStruct);
64      await this.loadEdge(fileStruct);
65      await this.loadTraceFunctionInfos(fileStruct);
66      await this.loadTraceTree(fileStruct);
67      await this.loadSamples(fileStruct);
68      let percent = Math.floor(50 / result.length) * (row.id + 1);
69      listener.process('loading file ' + fileStruct.name + ' from db ', percent);
70      info(`read ${fileStruct.name} from db Success  ${getTimeForLog()}`);
71      this.fileModule.push(fileStruct);
72    }
73    listener.process('Loading completed ', 50);
74    let dataParse = HeapDataInterface.getInstance();
75    dataParse.setPraseListener(listener);
76    dataParse.parseData(this.fileModule);
77  }
78
79  private async loadInfo(file: FileStruct) {
80    let result = await queryHeapInfo(file.id);
81    for (let row of result) {
82      if (row.key.includes('types')) continue;
83      switch (row.key) {
84        case 'node_count':
85          file.snapshotStruct.nodeCount = row.intValue;
86          break;
87        case 'edge_count':
88          file.snapshotStruct.edgeCount = row.intValue;
89          break;
90        case 'trace_function_count':
91          file.snapshotStruct.functionCount = row.intValue;
92          break;
93      }
94    }
95  }
96
97  private async loadNode(file: FileStruct) {
98    let result = await queryHeapNode(file.id);
99    let heapNodes = file.snapshotStruct.nodeMap;
100    let firstEdgeIndex = 0;
101    for (let row of result) {
102      let node = new HeapNode(
103        file.id,
104        row.nodeIndex,
105        row.type,
106        file.snapshotStruct.strings[row.nameIdx],
107        row.id,
108        row.selfSize,
109        row.edgeCount,
110        row.traceNodeId,
111        row.detachedness,
112        firstEdgeIndex
113      );
114      if (file.snapshotStruct.rootNodeId === -1) {
115        file.snapshotStruct.rootNodeId = row.id;
116      }
117      heapNodes.set(node.id, node);
118      firstEdgeIndex += row.edgeCount;
119    }
120  }
121
122  private async loadEdge(file: FileStruct) {
123    file.snapshotStruct.edges = await queryHeapEdge(file.id);
124  }
125
126  private async loadTraceFunctionInfos(file: FileStruct) {
127    file.snapshotStruct.functionInfos = await queryHeapFunction(file.id);
128  }
129
130  private async loadTraceTree(file: FileStruct) {
131    let result = await queryHeapTraceNode(file.id);
132    let heapTraceNode = file.snapshotStruct.traceNodes;
133    let strings = file.snapshotStruct.strings;
134    for (let row of result) {
135      let traceNode = new AllocationFunction(
136        row.id,
137        strings[row.name],
138        strings[row.scriptName],
139        row.scriptId,
140        row.line,
141        row.column,
142        row.count,
143        row.size,
144        row.liveCount,
145        row.liveSize,
146        false
147      );
148      traceNode.parentsId.push(row.parentId);
149      traceNode.functionIndex = row.functionInfoIndex;
150      traceNode.fileId = file.id;
151      heapTraceNode.push(traceNode);
152    }
153  }
154
155  private async loadSamples(file: FileStruct) {
156    file.snapshotStruct.samples = await queryHeapSample(file.id);
157  }
158
159  private async loadStrings(file: FileStruct) {
160    let result = await queryHeapString(file.id);
161    for (let data of result) {
162      file.snapshotStruct.strings.push(data.string);
163    }
164  }
165
166  async loadDatabase(listener: ParseListener) {
167    await this.loadFile(listener);
168  }
169}
170