• 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
16export class ChartStruct {
17    depth: number = 0;
18    symbol: string = '';
19    size: number = 0;
20    count: number = 0;
21    dur:number = 0;
22    parent: ChartStruct | undefined;
23    children: Array<ChartStruct> = [];
24}
25
26export class Msg{
27    tag:string = "";
28    index:number = 0;
29    data:Array<any> = [];
30}
31
32export class MerageBean extends ChartStruct{
33    #parentNode: MerageBean | undefined = undefined
34    #total = 0
35    currentTreeParentNode: MerageBean | undefined = undefined;
36    id: string = "";
37    parentId: string = "";
38    symbolName: string = "";
39    symbol: string = ""
40    libName: string = ""
41    path: string = ""
42    self: string = "0s"
43    weight: string = ""
44    weightPercent: string = ""
45    selfDur: number = 0;
46    dur: number = 0;
47    pid: number = 0;
48    canCharge:boolean = true
49    isStore = 0;
50    isSelected: boolean = false;
51    searchShow: boolean = true;
52    children: MerageBean[] = []
53    initChildren: MerageBean[] = []
54    type:number = 0
55    set parentNode(data: MerageBean | undefined) {
56        this.currentTreeParentNode = data;
57        this.#parentNode = data;
58    }
59
60    get parentNode() {
61        return this.#parentNode
62    }
63
64    set total(data: number) {
65        this.#total = data;
66        this.weight = `${getProbablyTime(this.dur)}`
67        this.weightPercent = `${(this.dur / data * 100).toFixed(1)}%`
68    }
69
70    get total() {
71        return this.#total;
72    }
73}
74
75class MerageBeanDataSplit{
76    systmeRuleName = "/system/"
77    numRuleName = "/max/min/"
78
79    //所有的操作都是针对整个树结构的 不区分特定的数据
80    splitTree(splitMapData:any,data: MerageBean[], name: string, isCharge: boolean, isSymbol: boolean,currentTreeList:any[],searchValue:string) {
81        data.forEach((process) => {
82            process.children = []
83            if (isCharge) {
84                this.recursionChargeInitTree(splitMapData,process, name, isSymbol)
85            } else {
86                this.recursionPruneInitTree(splitMapData,process, name, isSymbol)
87            }
88        })
89        this.resetAllNode(data,currentTreeList,searchValue)
90    }
91
92    recursionChargeInitTree(splitMapData:any,node: MerageBean, symbolName: string, isSymbol: boolean) {
93        if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) {
94            (splitMapData[symbolName] = splitMapData[symbolName] || []).push(node)
95            node.isStore++;
96        }
97        if (node.initChildren.length > 0) {
98            node.initChildren.forEach((child) => {
99                this.recursionChargeInitTree(splitMapData,child, symbolName, isSymbol)
100            })
101        }
102    }
103
104    //symbol lib charge
105    recursionChargeTree(node: MerageBean, symbolName: string, isSymbol: boolean) {
106        if ((isSymbol && node.symbolName == symbolName) || (!isSymbol && node.libName == symbolName)) {
107            node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1, ...node.children);
108            node.children.forEach((child) => {
109                child.currentTreeParentNode = node.currentTreeParentNode
110            })
111        }
112        if (node.children.length > 0) {
113            node.children.forEach((child) => {
114                this.recursionChargeTree(child, symbolName, isSymbol)
115            })
116        }
117    }
118
119    recursionPruneInitTree(splitMapData:any,node: MerageBean, symbolName: string, isSymbol: boolean) {
120        if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) {
121            (splitMapData[symbolName] = splitMapData[symbolName] || []).push(node)
122            node.isStore++;
123            this.pruneChildren(splitMapData,node, symbolName)
124        } else if (node.initChildren.length > 0) {
125            node.initChildren.forEach((child) => {
126                this.recursionPruneInitTree(splitMapData,child, symbolName, isSymbol)
127            })
128        }
129    }
130
131    //symbol lib prune
132    recursionPruneTree(node: MerageBean, symbolName: string, isSymbol: boolean) {
133        if (isSymbol && node.symbolName == symbolName || (!isSymbol && node.libName == symbolName)) {
134            node.currentTreeParentNode && node.currentTreeParentNode.children.splice(node.currentTreeParentNode.children.indexOf(node), 1);
135        } else {
136            node.children.forEach((child) => {
137                this.recursionPruneTree(child, symbolName, isSymbol)
138            })
139        }
140    }
141
142    recursionChargeByRule(splitMapData:any,node: MerageBean, ruleName: string, rule: (node: MerageBean) => boolean) {
143        if (node.initChildren.length > 0) {
144            node.initChildren.forEach((child) => {
145                if (rule(child)) {
146                    (splitMapData[ruleName] = splitMapData[ruleName] || []).push(child)
147                    child.isStore++;
148                }
149                this.recursionChargeByRule(splitMapData,child, ruleName, rule)
150            })
151        }
152    }
153
154    pruneChildren(splitMapData:any,node: MerageBean, symbolName: string) {
155        if (node.initChildren.length > 0) {
156            node.initChildren.forEach((child) => {
157                child.isStore++;
158                (splitMapData[symbolName] = splitMapData[symbolName] || []).push(child);
159                this.pruneChildren(splitMapData,child, symbolName)
160            })
161        }
162    }
163
164    hideSystemLibrary(allProcess:MerageBean[],splitMapData:any){
165        allProcess.forEach((item)=>{
166            item.children = []
167            this.recursionChargeByRule(splitMapData,item,this.systmeRuleName,(node)=>{
168                return node.path.startsWith(this.systmeRuleName)
169            })
170        })
171    }
172
173    hideNumMaxAndMin(allProcess:MerageBean[],splitMapData:any,startNum:number,endNum:string){
174        let max = endNum == "∞"?Number.POSITIVE_INFINITY :parseInt(endNum)
175        allProcess.forEach((item)=>{
176            item.children = []
177            this.recursionChargeByRule(splitMapData,item,this.numRuleName,(node)=>{
178                return node.count < startNum || node.count > max
179            })
180        })
181    }
182
183    resotreAllNode(splitMapData:any,symbols: string[]) {
184        symbols.forEach((symbol) => {
185            let list = splitMapData[symbol];
186            if (list != undefined) {
187                list.forEach((item: any) => {
188                    item.isStore--
189                })
190            }
191        })
192    }
193
194    resetAllNode(data: MerageBean[],currentTreeList:any[],searchValue:string) {
195        this.clearSearchNode(currentTreeList)
196        data.forEach((process) => {
197            process.searchShow = true
198        })
199        this.resetNewAllNode(data,currentTreeList)
200        if (searchValue != "") {
201            this.findSearchNode(data, searchValue, false)
202            this.resetNewAllNode(data,currentTreeList)
203        }
204    }
205
206    resetNewAllNode(data: MerageBean[],currentTreeList:any[]) {
207        data.forEach((process) => {
208            process.children = []
209        })
210        let values = currentTreeList.map((item: any) => {
211            item.children = []
212            return item
213        })
214        values.forEach((item: any) => {
215            if (item.parentNode != undefined) {
216                if (item.isStore == 0 && item.searchShow) {
217                    let parentNode = item.parentNode
218                    while (parentNode != undefined && !(parentNode.isStore == 0 && parentNode.searchShow)) {
219                        parentNode = parentNode.parentNode
220                    }
221                    if (parentNode) {
222                        item.currentTreeParentNode = parentNode
223                        parentNode.children.push(item)
224                    }
225                }
226            }
227        })
228    }
229
230    findSearchNode(data: MerageBean[], search: string, parentSearch: boolean) {
231        data.forEach((node) => {
232            if ((node.symbolName!=undefined&&node.symbolName.includes(search)) || parentSearch) {
233                node.searchShow = true
234                let parentNode = node.currentTreeParentNode
235                while (parentNode != undefined && !parentNode.searchShow) {
236                    parentNode.searchShow = true
237                    parentNode = parentNode.currentTreeParentNode
238                }
239            } else {
240                node.searchShow = false
241            }
242            if (node.children.length > 0) {
243                this.findSearchNode(node.children, search, node.searchShow)
244            }
245        })
246    }
247
248    clearSearchNode(currentTreeList:any[]) {
249        currentTreeList.forEach((node) => {
250            node.searchShow = true
251        })
252    }
253
254    splitAllProcess(allProcess:any[],splitMapData:any,list:any[]){
255        list.forEach((item:any)=>{
256            allProcess.forEach((process)=>{
257                if(item.select == "0"){
258                    this.recursionChargeInitTree(splitMapData,process, item.name, item.type == "symbol")
259                }else {
260                    this.recursionPruneInitTree(splitMapData,process, item.name, item.type == "symbol")
261                }
262            })
263            if(!item.checked){
264                this.resotreAllNode(splitMapData,[item.name])
265            }
266        })
267    }
268}
269
270export let merageBeanDataSplit = new MerageBeanDataSplit()
271
272export abstract class LogicHandler {
273    abstract  handle(data:any):void
274}
275
276let dec = new TextDecoder();
277
278export let setFileName = (path: string)=> {
279    let fileName = ""
280    if (path) {
281        let number = path.lastIndexOf("/");
282        if (number > 0) {
283            fileName = path.substring(number + 1)
284            return fileName
285        }
286    }
287    return path
288}
289
290let pagination = (page:number, pageSize:number, source:Array<any>)=>{
291    let offset = (page - 1) * pageSize;
292    return (offset + pageSize >= source.length) ? source.slice(offset, source.length) : source.slice(offset, offset + pageSize);
293}
294
295const PAGE_SIZE:number = 50_0000;
296export let postMessage = (id: any, action: string, results: Array<any>) => {
297    if(results.length > PAGE_SIZE){
298        let pageCount = Math.ceil( results.length / PAGE_SIZE)
299        for (let i = 0; i < pageCount; i++) {
300            let tag = "start";
301            if(i== 0){
302                tag = "start"
303            }else if(i == pageCount - 1){
304                tag = "end"
305            }else{
306                tag = "sending"
307            }
308            let msg = new Msg();
309            msg.tag = tag;
310            msg.index = i;
311            msg.data = pagination(i,PAGE_SIZE,results);
312            self.postMessage({id: id, action: action, isSending:msg.tag != "end",results: msg})
313        }
314    }else{
315        let msg = new Msg();
316        msg.tag = "end";
317        msg.index = 0;
318        msg.data = results;
319        self.postMessage({id: id, action: action,results: msg})
320    }
321}
322
323export let convertJSON = (arr:ArrayBuffer)=>{
324    if(arr instanceof ArrayBuffer) {
325        let str = dec.decode(arr);
326        let jsonArray = [];
327        str = str.substring(str.indexOf("\n") + 1);
328        if (!str) {
329        } else {
330            let parse = JSON.parse(str);
331            let columns = parse.columns;
332            let values = parse.values;
333            for (let i = 0; i < values.length; i++) {
334                let obj: any = {}
335                for (let j = 0; j < columns.length; j++) {
336                    obj[columns[j]] = values[i][j]
337                }
338                jsonArray.push(obj)
339            }
340        }
341        return jsonArray;
342    } else {
343        return arr;
344    }
345}
346
347export let getByteWithUnit = (bytes: number) : string => {
348    if (bytes < 0) {
349        return "-" + getByteWithUnit(Math.abs(bytes))
350    }
351    let currentBytes = bytes
352    let kb1 = 1 << 10;
353    let mb1 = 1 << 10 << 10;
354    let gb1 = 1 << 10 << 10 << 10; // 1 gb
355    let res = ""
356    if (currentBytes > gb1) {
357        res += (currentBytes / gb1).toFixed(2) + " Gb";
358    } else if (currentBytes > mb1) {
359        res += (currentBytes / mb1).toFixed(2) + " Mb";
360    } else if (currentBytes > kb1) {
361        res += (currentBytes / kb1).toFixed(2) + " Kb";
362    } else {
363        res += Math.round(currentBytes) + " byte";
364    }
365    return res
366}
367
368export let  getTimeString = (ns: number): string =>{
369    let currentNs = ns
370    let hour1 = 3600_000_000_000
371    let minute1 = 60_000_000_000
372    let second1 = 1_000_000_000;
373    let millisecond1 = 1_000_000;
374    let microsecond1 = 1_000;
375    let res = "";
376    if (currentNs >= hour1) {
377        res += Math.floor(currentNs / hour1) + "h ";
378        currentNs = currentNs - Math.floor(currentNs / hour1) * hour1
379    }
380    if (currentNs >= minute1) {
381        res += Math.floor(currentNs / minute1) + "m ";
382        currentNs = currentNs - Math.floor(ns / minute1) * minute1
383    }
384    if (currentNs >= second1) {
385        res += Math.floor(currentNs / second1) + "s ";
386        currentNs = currentNs - Math.floor(currentNs / second1) * second1
387    }
388    if (currentNs >= millisecond1) {
389        res += Math.floor(currentNs / millisecond1) + "ms ";
390        currentNs = currentNs - Math.floor(currentNs / millisecond1) * millisecond1
391    }
392    if (currentNs >= microsecond1) {
393        res += Math.floor(currentNs / microsecond1) + "μs ";
394        currentNs = currentNs - Math.floor(currentNs / microsecond1) * microsecond1
395    }
396    if (currentNs > 0) {
397        res += currentNs + "ns ";
398    }
399    if (res == "") {
400        res = ns + "";
401    }
402    return res
403}
404
405export function getProbablyTime(ns: number): string {
406    let currentNs = ns
407    let hour1 = 3600_000_000_000
408    let minute1 = 60_000_000_000
409    let second1 = 1_000_000_000;
410    let millisecond1 = 1_000_000;
411    let microsecond1 = 1_000;
412    let res = "";
413    if (currentNs >= hour1) {
414        res += (currentNs / hour1).toFixed(2) + "h ";
415    }else if (currentNs >= minute1) {
416        res += (currentNs / minute1).toFixed(2) + "m ";
417    }else if (currentNs >= second1) {
418        res += (currentNs / second1).toFixed(2) + "s ";
419    }else if (currentNs >= millisecond1) {
420        res += (currentNs / millisecond1).toFixed(2) + "ms ";
421    }else if (currentNs >= microsecond1) {
422        res += (currentNs / microsecond1).toFixed(2) + "μs ";
423    }else if (currentNs > 0) {
424        res += currentNs + "ns ";
425    }else if (res == "") {
426        res = ns + "";
427    }
428    return res
429}
430
431export function timeMsFormat2p(ns: number) {
432    let currentNs = ns
433    let hour1 = 3600_000
434    let minute1 = 60_000
435    let second1 = 1_000; // 1 second
436    let res = ""
437    if (currentNs >= hour1) {
438        res += Math.floor(currentNs / hour1).toFixed(2) + "h"
439        return res
440    }
441    if (currentNs >= minute1) {
442        res += Math.floor(currentNs / minute1).toFixed(2) + "min"
443        return res
444    }
445    if (currentNs >= second1) {
446        res += Math.floor(currentNs / second1).toFixed(2) + "s"
447        return res
448    }
449    if (currentNs > 0) {
450        res += currentNs.toFixed(2) + "ms";
451        return res
452    }
453    if (res == "") {
454        res = "0s";
455    }
456    return res
457}