diff --git a/ide/server/main.go b/ide/server/main.go index 4f2aebf2c24f62e1a653a2ee806cc9d011d3a5d2..a8c8af502028336cbb57c40c521222e6cb850932 100644 --- a/ide/server/main.go +++ b/ide/server/main.go @@ -42,6 +42,7 @@ import ( "strconv" "strings" "time" + "flag" ) const HttpPort = 9000 @@ -112,7 +113,16 @@ func genSSL() { keyOut.Close() } func main() { - checkPort(HttpPort) + port := HttpPort + isOpen := 1 + flag.IntVar(&port, "p", HttpPort, "The port number used") + flag.IntVar(&isOpen, "o", 1 , "Whether to immediately open the website in your browser; 1 is true; 0 is false") + flag.Parse() + if isOpen < 0 || isOpen > 1 { + fmt.Println("Error: -o must be 0 or 1") + return + } + checkPort(port) genSSL() exPath = getCurrentAbPath() fmt.Println(exPath) @@ -137,23 +147,25 @@ func main() { mux.Handle("/application/", http.StripPrefix("/application/", cors(fs, version))) go func() { ser := &http.Server{ - Addr: fmt.Sprintf(":%d", HttpPort), + Addr: fmt.Sprintf(":%d", port), Handler: mux, } - log.Println(fmt.Sprintf("HTTPS[%d]服务启动", HttpPort)) + log.Println(fmt.Sprintf("HTTPS[%d]服务启动", port)) err := ser.ListenAndServeTLS("cert/certFile.pem", "cert/keyFile.key") CheckErr(err) }() go func() { ser := &http.Server{ - Addr: fmt.Sprintf(":%d", HttpPort+1), + Addr: fmt.Sprintf(":%d", port+1), Handler: mux, } - log.Println(fmt.Sprintf("HTTP[%d]服务启动", HttpPort)) + log.Println(fmt.Sprintf("HTTP[%d]服务启动", port)) err := ser.ListenAndServe() CheckErr(err) }() - open(fmt.Sprintf("https://localhost:%d/application", HttpPort)) + if (isOpen == 1){ + open(fmt.Sprintf("https://localhost:%d/application", port)) + } }() select {} } diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index f5c3b9157c35cfade89094144976d9f1e76e40aa..441a731163d90e6eb5878232735b0ff449725114 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -799,6 +799,8 @@ export class LitTable extends HTMLElement { this.meauseRowElement = undefined; this.tbodyElement!.innerHTML = ''; this.treeElement!.innerHTML = ''; + this.treeElement && (this.treeElement!.style.transform = `translateY(0px)`); + this.tbodyElement && (this.tbodyElement!.style.transform = `translateY(0px)`); this.currentRecycleList = []; this.currentTreeDivList = []; } diff --git a/ide/src/js-heap/LoadDatabase.ts b/ide/src/js-heap/LoadDatabase.ts index cbad93232e1e31116f19f377980cff99a35d3ec1..5b730c0b303340576d8ffd89db5655eaa993f65b 100644 --- a/ide/src/js-heap/LoadDatabase.ts +++ b/ide/src/js-heap/LoadDatabase.ts @@ -54,7 +54,6 @@ export class LoadDatabase { fileStruct.type = FileType.TIMELINE; } info(`read ${fileStruct.name} from db ${getTimeForLog()}`); - //fileStruct.profile.root_index = 0 await this.loadInfo(fileStruct); await this.loadStrings(fileStruct); await this.loadNode(fileStruct); diff --git a/ide/src/js-heap/logic/HeapLoader.ts b/ide/src/js-heap/logic/HeapLoader.ts index 920d6e2e3398153a707f71b233a994f68d21d468..80ebeac8206b3a2e876f896718df773d020c9258 100644 --- a/ide/src/js-heap/logic/HeapLoader.ts +++ b/ide/src/js-heap/logic/HeapLoader.ts @@ -213,36 +213,79 @@ export class HeapLoader { this.markPageOwnedNodes(); } - private buildOrderIdxAndDominateTree(): Uint32Array { - let stackNodes = new Uint32Array(this.nodeCount); // node index - let stackCurrentEdge = new Uint32Array(this.nodeCount); // edge index - let orderIdx2NodeIdx = new Uint32Array(this.nodeCount); - let nodeIdx2OrderIdx = new Uint32Array(this.nodeCount); - let visited = new Uint8Array(this.nodeCount); - let postOrderIdx = 0; + private buildOrderIdxOrphans( + postOrderIdx: number, + visited: Uint8Array, + nodeIdx2OrderIdx: Uint32Array, + orderIdx2NodeIdx: Uint32Array + ): void { + if (postOrderIdx !== this.nodeCount) { + // Remove root from the result (last node in the array) and put it at the bottom of the stack so that it is + // visited after all orphan nodes and their subgraphs. + --postOrderIdx; + for (let i = 0; i < this.nodeCount; i++) { + if (visited[i]) { + continue; + } + // Fix it by giving the node a postorder index anyway. + nodeIdx2OrderIdx[i] = postOrderIdx; + orderIdx2NodeIdx[postOrderIdx++] = i; + } + nodeIdx2OrderIdx[this.rootNode!.nodeIndex] = postOrderIdx; + orderIdx2NodeIdx[postOrderIdx++] = this.rootNode!.nodeIndex; + } + } + + private buildOrderIdxRootNode(stackNodes: Uint32Array, stackCurrentEdge: Uint32Array, visited: Uint8Array): number { let stack = 0; stackNodes[0] = this.rootNode!.nodeIndex; - visited[this.rootNode!.nodeIndex] = 1; + stackCurrentEdge[0] = this.nodes[this.rootNode!.nodeIndex + 1].firstEdgeIndex; + for (let node of this.nodes) { + if (visited[node.nodeIndex] || !this.hasOnlyWeakRetainers(node)) { + continue; + } + stackNodes[++stack] = node.nodeIndex; + stackCurrentEdge[stack] = node.firstEdgeIndex; + visited[node.nodeIndex] = 1; + } + return stack; + } + private buildOrderIdxInit() { + const state = { + stackNodes: new Uint32Array(this.nodeCount), + stackCurrentEdge: new Uint32Array(this.nodeCount), + orderIdx2NodeIdx: new Uint32Array(this.nodeCount), + nodeIdx2OrderIdx: new Uint32Array(this.nodeCount), + visited: new Uint8Array(this.nodeCount), + }; + state.stackNodes[0] = this.rootNode!.nodeIndex; + state.visited[this.rootNode!.nodeIndex] = 1; + return state; + } + private buildOrderIdxAndDominateTree(): Uint32Array { + const params = this.buildOrderIdxInit(); let iteration = 0; + let postOrderIdx = 0; + let stack = 0; while (true) { ++iteration; while (stack >= 0 && stack < this.nodeCount) { - let nodeIndex = stackNodes[stack]; + let nodeIndex = params.stackNodes[stack]; let node = this.nodes[nodeIndex]; if (!node) { continue; } - let edgeIndex = stackCurrentEdge[stack]; + let edgeIndex = params.stackCurrentEdge[stack]; let edgeEnd = node.firstEdgeIndex + node.edgeCount; if (edgeIndex < edgeEnd) { - stackCurrentEdge[stack] += 1; + params.stackCurrentEdge[stack] += 1; let edge = this.edges[edgeIndex]; if (!this.isEssentialEdge(edge, node.id)) { continue; } let childNode = this.nodeMap.get(edge.toNodeId); - if (!childNode || visited[childNode!.nodeIndex]) { + if (!childNode || params.visited[childNode!.nodeIndex]) { continue; } //Skip the edges from non-page-object nodes to page-object nodes @@ -251,12 +294,12 @@ export class HeapLoader { continue; } ++stack; - stackNodes[stack] = childNode.nodeIndex; - stackCurrentEdge[stack] = childNode.firstEdgeIndex; - visited[childNode.nodeIndex] = 1; + params.stackNodes[stack] = childNode.nodeIndex; + params.stackCurrentEdge[stack] = childNode.firstEdgeIndex; + params.visited[childNode.nodeIndex] = 1; } else { - nodeIdx2OrderIdx[node.nodeIndex] = postOrderIdx; - orderIdx2NodeIdx[postOrderIdx++] = node.nodeIndex; + params.nodeIdx2OrderIdx[node.nodeIndex] = postOrderIdx; + params.orderIdx2NodeIdx[postOrderIdx++] = node.nodeIndex; --stack; } } @@ -267,38 +310,79 @@ export class HeapLoader { // Remove root from the result (last node in the array) and put it at the bottom of the stack so that it is // visited after all orphan nodes and their subgraphs. --postOrderIdx; - stack = 0; - stackNodes[0] = this.rootNode!.nodeIndex; - stackCurrentEdge[0] = this.nodes[this.rootNode!.nodeIndex + 1].firstEdgeIndex; - for (let node of this.nodes) { - if (visited[node.nodeIndex] || !this.hasOnlyWeakRetainers(node)) { - continue; - } - stackNodes[++stack] = node.nodeIndex; - stackCurrentEdge[stack] = node.firstEdgeIndex; - visited[node.nodeIndex] = 1; - } + stack = this.buildOrderIdxRootNode(params.stackNodes, params.stackCurrentEdge, params.visited); } // If we already processed all orphan nodes that have only weak retainers and still have some orphans... - if (postOrderIdx !== this.nodeCount) { - // Remove root from the result (last node in the array) and put it at the bottom of the stack so that it is - // visited after all orphan nodes and their subgraphs. - --postOrderIdx; - for (let i = 0; i < this.nodeCount; i++) { - if (visited[i]) { - continue; - } - // Fix it by giving the node a postorder index anyway. - nodeIdx2OrderIdx[i] = postOrderIdx; - orderIdx2NodeIdx[postOrderIdx++] = i; + this.buildOrderIdxOrphans(postOrderIdx, params.visited, params.nodeIdx2OrderIdx, params.orderIdx2NodeIdx); + this.buildDominatorTree(params.orderIdx2NodeIdx, params.nodeIdx2OrderIdx); + return params.orderIdx2NodeIdx; + } + + private affectedNode(affected: Uint8Array, nodeIdx2OrderIdx: Uint32Array): void { + // 标记root节点的子节点为affected. + for (let edge of this.rootNode!.edges) { + if (!this.isEssentialEdge(edge, this.rootNode!.id)) { + continue; + } + let childNode = this.nodeMap.get(edge.toNodeId); + if (childNode) { + affected[nodeIdx2OrderIdx[childNode.nodeIndex]] = 1; } - nodeIdx2OrderIdx[this.rootNode!.nodeIndex] = postOrderIdx; - orderIdx2NodeIdx[postOrderIdx++] = this.rootNode!.nodeIndex; } - this.buildDominatorTree(orderIdx2NodeIdx, nodeIdx2OrderIdx); - return orderIdx2NodeIdx; } + private buildDominatorTreeLogic( + nodeIdx: number, + rootOrderedIdx: number, + dominators: Uint32Array, + nodeIdx2OrderIdx: Uint32Array + ): number { + let node = this.nodes[nodeIdx]; + let nodeFlag = node.flag & PAGE_PROJECT; + let newDominatorIdx = this.nodeCount; + let retainerStart = this.firstRetainerIndex[nodeIdx]; + let retainerEnd = this.firstRetainerIndex[nodeIdx + 1]; + let orphanNode = true; + for (let idx = retainerStart; idx < retainerEnd; idx++) { + let retainerNodeIdx = this.retainingNodes[idx]; + let retainerEdgeIdx = this.retainingEdges[idx]; + let node = this.nodes[retainerNodeIdx]; + let edge = this.edges[retainerEdgeIdx]; + if (!this.isEssentialEdge(edge, node.id)) { + continue; + } + orphanNode = false; + let retainerNodeFlag = node.flag & PAGE_PROJECT; + if (retainerNodeIdx !== this.rootNode?.nodeIndex && nodeFlag && !retainerNodeFlag) { + continue; + } + let retainerOrderIdx = nodeIdx2OrderIdx[retainerNodeIdx]; + if (dominators[retainerOrderIdx] !== this.nodeCount) { + if (newDominatorIdx === this.nodeCount) { + newDominatorIdx = retainerOrderIdx; + } else { + while (retainerOrderIdx !== newDominatorIdx) { + while (retainerOrderIdx < newDominatorIdx) { + retainerOrderIdx = dominators[retainerOrderIdx]; + } + while (newDominatorIdx < retainerOrderIdx) { + newDominatorIdx = dominators[newDominatorIdx]; + } + } + } + // If idom has already reached the root, it doesn't make sense + // to check other retainers. + if (newDominatorIdx === rootOrderedIdx) { + break; + } + } + } + // Make root dominator of orphans. + if (orphanNode) { + newDominatorIdx = rootOrderedIdx; + } + return newDominatorIdx; + } // The algorithm is based on the article: // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm" // Softw. Pract. Exper. 4 (2001), pp. 1-10. @@ -312,15 +396,7 @@ export class HeapLoader { let affected = new Uint8Array(this.nodeCount); // 标记root节点的子节点为affected. - for (let edge of this.rootNode!.edges) { - if (!this.isEssentialEdge(edge, this.rootNode!.id)) { - continue; - } - let childNode = this.nodeMap.get(edge.toNodeId); - if (childNode) { - affected[nodeIdx2OrderIdx[childNode.nodeIndex]] = 1; - } - } + this.affectedNode(affected, nodeIdx2OrderIdx); let changed = true; let nodeIdx; @@ -337,50 +413,8 @@ export class HeapLoader { continue; } nodeIdx = orderIdx2NodeIdx[orderIdx]; - let node = this.nodes[nodeIdx]; - let nodeFlag = node.flag & PAGE_PROJECT; - let newDominatorIdx = this.nodeCount; - let retainerStart = this.firstRetainerIndex[nodeIdx]; - let retainerEnd = this.firstRetainerIndex[nodeIdx + 1]; - let orphanNode = true; - for (let idx = retainerStart; idx < retainerEnd; idx++) { - let retainerNodeIdx = this.retainingNodes[idx]; - let retainerEdgeIdx = this.retainingEdges[idx]; - let node = this.nodes[retainerNodeIdx]; - let edge = this.edges[retainerEdgeIdx]; - if (!this.isEssentialEdge(edge, node.id)) { - continue; - } - orphanNode = false; - let retainerNodeFlag = node.flag & PAGE_PROJECT; - if (retainerNodeIdx !== this.rootNode?.nodeIndex && nodeFlag && !retainerNodeFlag) { - continue; - } - let retainerOrderIdx = nodeIdx2OrderIdx[retainerNodeIdx]; - if (dominators[retainerOrderIdx] !== this.nodeCount) { - if (newDominatorIdx === this.nodeCount) { - newDominatorIdx = retainerOrderIdx; - } else { - while (retainerOrderIdx !== newDominatorIdx) { - while (retainerOrderIdx < newDominatorIdx) { - retainerOrderIdx = dominators[retainerOrderIdx]; - } - while (newDominatorIdx < retainerOrderIdx) { - newDominatorIdx = dominators[newDominatorIdx]; - } - } - } - // If idom has already reached the root, it doesn't make sense - // to check other retainers. - if (newDominatorIdx === rootOrderedIdx) { - break; - } - } - } - // Make root dominator of orphans. - if (orphanNode) { - newDominatorIdx = rootOrderedIdx; - } + const newDominatorIdx = this.buildDominatorTreeLogic(nodeIdx, rootOrderedIdx, dominators, nodeIdx2OrderIdx); + if (newDominatorIdx !== this.nodeCount && dominators[orderIdx] !== newDominatorIdx) { dominators[orderIdx] = newDominatorIdx; changed = true; @@ -687,20 +721,25 @@ export class HeapLoader { return true; } - private calClassDiff(targetClass: ConstructorItem, baseClass?: ConstructorItem) { - let diff = new ConstructorComparison(); + private initDiff(targetClass: ConstructorItem, baseClass?: ConstructorItem): ConstructorComparison { + const diff = new ConstructorComparison(); diff.type = ConstructorType.ComparisonType; diff.fileId = this.fileId; diff.targetFileId = targetClass.fileId; diff.nodeName = targetClass.nodeName; - let i = 0; - let j = 0; - let baseLen = baseClass ? baseClass.childCount : 0; - let targetLen = targetClass.childCount; targetClass.classChildren.sort((a, b) => a.id - b.id); if (baseClass) { baseClass.classChildren.sort((a, b) => a.id - b.id); } + return diff; + } + + private calClassDiff(targetClass: ConstructorItem, baseClass?: ConstructorItem) { + let i = 0; + let j = 0; + let baseLen = baseClass ? baseClass.childCount : 0; + let targetLen = targetClass.childCount; + const diff = this.initDiff(targetClass, baseClass); // The overlap between the base class and the target class while (i < targetLen && j < baseLen) { let baseNode = baseClass!.classChildren[j]; @@ -746,24 +785,53 @@ export class HeapLoader { return diff; } - public getClassesForSummary(minNodeId?: number, maxNodeId?: number): Map { - let hasFiler = typeof minNodeId === 'number' && typeof maxNodeId === 'number'; - function filter(nodeId: number): boolean { - if (hasFiler) { - if (hasFiler && nodeId >= minNodeId! && nodeId <= maxNodeId!) { - return true; - } else { - return false; + private calClassRetainedSize(hasFiler: boolean, classes: Map, filter: Function) { + // cal class retained size + let list = [this.rootNode]; + const sizes = [-1]; + const classesName = []; + let seenClassName = new Map(); + + while (list.length) { + let node = list.pop(); + if (!node) { + continue; + } + let nodeClassName = node.className(); + let seen = Boolean(seenClassName.get(nodeClassName)); + let dominatorFromIdx = this.firstDominatedNodesIdx[node.nodeIndex]; + let dominatorToIdx = this.firstDominatedNodesIdx[node.nodeIndex + 1]; + + if (!seen && (!hasFiler || filter(node.id)) && (node.selfSize || node.type === NodeType.NATIVE)) { + let classItem = classes.get(nodeClassName); + if (classItem) { + classItem.retainedSize += node.retainedSize; + if (dominatorFromIdx !== dominatorToIdx) { + seenClassName.set(nodeClassName, true); + sizes.push(list.length); + classesName.push(nodeClassName); + } } - } else { - return true; + } + + for (let idx = dominatorFromIdx; idx < dominatorToIdx; idx++) { + let nodeIdx = this.dominatedNodes[idx]; + let domNode = this.nodes[nodeIdx]; + list.push(domNode); + } + + while (sizes[sizes.length - 1] === list.length) { + sizes.pop(); + nodeClassName = classesName.pop() as string; + seenClassName.set(nodeClassName, false); } } - if (!hasFiler && this.allClasses) { - return this.allClasses; + if (!hasFiler) { + this.allClasses = classes; } - let classes = new Map(); - // combine node with className + } + + private combineNodeWithClassName(classes: Map, filter: Function) { for (let node of this.nodes) { if (!filter(node.id) || (node.selfSize === 0 && node.type !== NodeType.NATIVE)) { continue; @@ -809,50 +877,27 @@ export class HeapLoader { classItem.classChildren.push(nodeItem); } } + } - // cal class retained size - let list = [this.rootNode]; - const sizes = [-1]; - const classesName = []; - let seenClassName = new Map(); - - while (list.length) { - let node = list.pop(); - if (!node) { - continue; - } - let nodeClassName = node.className(); - let seen = Boolean(seenClassName.get(nodeClassName)); - let dominatorFromIdx = this.firstDominatedNodesIdx[node.nodeIndex]; - let dominatorToIdx = this.firstDominatedNodesIdx[node.nodeIndex + 1]; - - if (!seen && (!hasFiler || filter(node.id)) && (node.selfSize || node.type === NodeType.NATIVE)) { - let classItem = classes.get(nodeClassName); - if (classItem) { - classItem.retainedSize += node.retainedSize; - if (dominatorFromIdx !== dominatorToIdx) { - seenClassName.set(nodeClassName, true); - sizes.push(list.length); - classesName.push(nodeClassName); - } + public getClassesForSummary(minNodeId?: number, maxNodeId?: number): Map { + let hasFiler = typeof minNodeId === 'number' && typeof maxNodeId === 'number'; + function filter(nodeId: number): boolean { + if (hasFiler) { + if (hasFiler && nodeId >= minNodeId! && nodeId <= maxNodeId!) { + return true; + } else { + return false; } - } - - for (let idx = dominatorFromIdx; idx < dominatorToIdx; idx++) { - let nodeIdx = this.dominatedNodes[idx]; - let domNode = this.nodes[nodeIdx]; - list.push(domNode); - } - - while (sizes[sizes.length - 1] === list.length) { - sizes.pop(); - nodeClassName = classesName.pop() as string; - seenClassName.set(nodeClassName, false); + } else { + return true; } } - if (!hasFiler) { - this.allClasses = classes; + if (!hasFiler && this.allClasses) { + return this.allClasses; } + let classes = new Map(); + this.combineNodeWithClassName(classes, filter); + this.calClassRetainedSize(hasFiler, classes, filter); return classes; } @@ -956,6 +1001,27 @@ export class HeapLoader { findParents(clickNode, []); } + private combineRetains(node: HeapNode, item: ConstructorItem, retains: Array) { + for (let i = 0; i < node.retainsNodeIdx.length; i++) { + let retainsNode = this.nodes[node.retainsNodeIdx[i]]; + let retainEdge = this.edges[node.retainsEdgeIdx[i]]; + + if (retainEdge.type == EdgeType.WEAK) { + continue; + } + let retainsItem = HeapNodeToConstructorItem(retainsNode); + retainsItem.edgeName = retainEdge.nameOrIndex; + retainsItem.edgeType = retainEdge.type; + retainsItem.type = ConstructorType.RetainersType; + retainsItem.childCount = retainsNode.retainsNodeIdx.length; + retainsItem.hasNext = retainsNode.retainsNodeIdx.length > 0; + if (item!.type == ConstructorType.RetainersType) { + retainsItem.parent = item; + } + retains.push(retainsItem); + } + } + /** * get nodes which referenced this node * @param constructor current node @@ -971,24 +1037,7 @@ export class HeapLoader { let node = this.nodes[item.index]; let retains = new Array(); if (node && node.retainsEdgeIdx.length === node.retainsNodeIdx.length) { - for (let i = 0; i < node.retainsNodeIdx.length; i++) { - let retainsNode = this.nodes[node.retainsNodeIdx[i]]; - let retainEdge = this.edges[node.retainsEdgeIdx[i]]; - - if (retainEdge.type == EdgeType.WEAK) { - continue; - } - let retainsItem = HeapNodeToConstructorItem(retainsNode); - retainsItem.edgeName = retainEdge.nameOrIndex; - retainsItem.edgeType = retainEdge.type; - retainsItem.type = ConstructorType.RetainersType; - retainsItem.childCount = retainsNode.retainsNodeIdx.length; - retainsItem.hasNext = retainsNode.retainsNodeIdx.length > 0; - if (item!.type == ConstructorType.RetainersType) { - retainsItem.parent = item; - } - retains.push(retainsItem); - } + this.combineRetains(node, item, retains); } // Because the node with id 1 needs to be deleted, there is only one child and id 1 does not need to expand the symbol diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 5f2e17018c592787b924abfd2dd2676531fee840..d623c516073ca6d679a155fc5e54f7165a589d5a 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -61,7 +61,8 @@ import { Utils } from './component/trace/base/Utils'; import { applicationHtml, clearTraceFileCache, - findFreeSizeAlgorithm, getCurrentDataTime, + findFreeSizeAlgorithm, + getCurrentDataTime, indexedDataToBufferData, postLog, readTraceFileBuffer, @@ -90,20 +91,21 @@ export class SpApplication extends BaseElement { longTraceTypeMessageMap: | Map< - number, - Array<{ - fileType: string; - startIndex: number; - endIndex: number; - size: number; - }> - > + number, + Array<{ + fileType: string; + startIndex: number; + endIndex: number; + size: number; + }> + > | undefined | null; static skinChange: Function | null | undefined = null; static skinChange2: Function | null | undefined = null; skinChangeArray: Array = []; private rootEL: HTMLDivElement | undefined | null; + private headerDiv: HTMLDivElement | undefined | null; private spWelcomePage: SpWelcomePage | undefined | null; private spMetrics: SpMetrics | undefined | null; private spQuerySQL: SpQuerySQL | undefined | null; @@ -123,6 +125,7 @@ export class SpApplication extends BaseElement { private sidebarButton: HTMLDivElement | undefined | null; private chartFilter: TraceRowConfig | undefined | null; private cutTraceFile: HTMLImageElement | undefined | null; + private exportRecord: LitIcon | undefined | null; private longTracePage: HTMLDivElement | undefined | null; private customColor: CustomThemeColor | undefined | null; private filterConfig: LitIcon | undefined | null; @@ -142,6 +145,7 @@ export class SpApplication extends BaseElement { 189: true, }; private traceFileName: string | undefined; + private markJson: string | undefined; colorTransiton: any; static isLongTrace: boolean = false; fileTypeList: string[] = ['ebpf', 'arkts', 'hiperf']; @@ -255,6 +259,7 @@ export class SpApplication extends BaseElement { this.initPlugin(); this.querySql = true; this.rootEL = this.shadowRoot!.querySelector('.root'); + this.headerDiv = this.shadowRoot!.querySelector('.search-vessel'); this.spWelcomePage = this.shadowRoot!.querySelector('#sp-welcome') as SpWelcomePage; this.spMetrics = this.shadowRoot!.querySelector('#sp-metrics') as SpMetrics; // new SpMetrics(); this.spQuerySQL = this.shadowRoot!.querySelector('#sp-query-sql') as SpQuerySQL; // new SpQuerySQL(); @@ -274,6 +279,7 @@ export class SpApplication extends BaseElement { this.sidebarButton = this.shadowRoot?.querySelector('.sidebar-button'); this.chartFilter = this.shadowRoot?.querySelector('.chart-filter') as TraceRowConfig; this.cutTraceFile = this.shadowRoot?.querySelector('.cut-trace-file') as HTMLImageElement; + this.exportRecord = this.shadowRoot?.querySelector('.export-record') as LitIcon; this.longTracePage = this.shadowRoot!.querySelector('.long_trace_page') as HTMLDivElement; this.customColor = this.shadowRoot?.querySelector('.custom-color') as CustomThemeColor; this.filterConfig = this.shadowRoot?.querySelector('.filter-config') as LitIcon; @@ -281,27 +287,45 @@ export class SpApplication extends BaseElement { this.configClose = this.shadowRoot ?.querySelector('.chart-filter')! .shadowRoot?.querySelector('.config-close'); - // 关键路径标识 this.importConfigDiv = this.shadowRoot?.querySelector('#import-key-path'); this.closeKeyPath = this.shadowRoot?.querySelector('#close-key-path'); this.importFileBt = this.shadowRoot?.querySelector('#import-config'); this.initElementsAttr(); this.initEvents(); + this.initRecordEvents(); this.initCustomEvents(); this.initCustomColorHandler(); this.initImportConfigEvent(); this.initSlideMenuEvents(); - this.initMenus(); + this.mainMenu!.menus = [this.initNavigationMenu(), this.initSupportMenus()]; this.initGlobalEvents(); this.initDocumentListener(); + this.initElementsEnd(); + } + + private initElementsEnd(): void { let urlParams = new URL(window.location.href).searchParams; if (urlParams && urlParams.get('trace') && urlParams.get('link')) { this.openLineFileHandler(urlParams); + } else if (urlParams && urlParams.get('action')) { + this.helpClick(urlParams!); } else { this.openMenu(true); } } + private helpClick(urlParams: URLSearchParams) { + if (urlParams.get('action') === 'help') { + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'help_page', + action: 'help_doc', + }); + this.showContent(this.spHelp!); + } else if (urlParams.get('action')!.length > 4) { + this.showContent(this.spHelp!); + } + } + private initElementsAttr(): void { this.mainMenu!.setAttribute('main_menu', '1'); this.chartFilter!.setAttribute('mode', ''); @@ -325,6 +349,7 @@ export class SpApplication extends BaseElement { } private openLongTraceFile(ev: any, isRecordTrace: boolean = false) { + this.returnOriginalUrl(); this.wasm = true; this.openFileInit(); let detail = (ev as any).detail; @@ -521,6 +546,7 @@ export class SpApplication extends BaseElement { } private openTraceFile(ev: any, isClickHandle?: boolean) { + this.returnOriginalUrl(); this.removeAttribute('custom-color'); this.customColor!.setAttribute('hidden', ''); this.longTracePage!.style.display = 'none'; @@ -550,7 +576,7 @@ export class SpApplication extends BaseElement { this.wasm = true; this.handleWasmMode(ev, showFileName, (ev as any).size, fileName); } - } + }; } private openLineFileHandler(urlParams: URLSearchParams): void { @@ -711,117 +737,152 @@ export class SpApplication extends BaseElement { ); } - private initMenus(): void { - this.mainMenu!.menus = [ - { - collapsed: false, - title: 'Navigation', - second: false, - icon: '', - describe: 'Open or record a new trace', - children: [ - { - title: 'Open trace file', - icon: 'folder', - fileChoose: true, - fileHandler: (ev: InputEvent): void => { - this.openTraceFile(ev.detail as any); - }, - clickHandler: (hand: any) => { - this.openTraceFile(hand, true); - }, - }, - { - title: 'Open long trace file', - icon: 'folder', - fileChoose: true, - fileHandler: (ev: InputEvent): void => { - this.openLongTraceFile(ev); - }, - clickHandler: (hand: any): void => { - this.openLongTraceFile(hand, true); - }, - }, - { - title: 'Record new trace', - icon: 'copyhovered', - clickHandler: (item: MenuItem): void => { - this.spRecordTrace!.synchronizeDeviceList(); - this.spRecordTemplate!.record_template = false; - this.spRecordTrace!.refreshConfig(true); - this.showContent(this.spRecordTrace!); - }, - }, - { - title: 'Record template', - icon: 'copyhovered', - clickHandler: (item: MenuItem): void => { - this.spRecordTemplate!.refreshHint(); - this.spRecordTemplate!.record_template = true; - this.spRecordTemplate!.refreshConfig(false); - this.spRecordTemplate!.synchronizeDeviceList(); - this.showContent(this.spRecordTemplate!); - }, + private initNavigationMenu() { + return { + collapsed: false, + title: 'Navigation', + second: false, + icon: '', + describe: 'Open or record a new trace', + children: [ + { + title: 'Open trace file', + icon: 'folder', + fileChoose: true, + fileHandler: (ev: InputEvent): void => { + this.openTraceFile(ev.detail as any); }, - ], - }, - { - collapsed: false, - title: 'Support', - second: false, - icon: '', - describe: 'Support', - children: [ - { - title: 'Help Documents', - icon: 'smart-help', - clickHandler: (item: MenuItem): void => { - this.spHelp!.dark = this.dark; - this.search = false; - this.showContent(this.spHelp!); - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'help_page', - action: 'help_doc', - }); - }, + clickHandler: (hand: any) => { + this.openTraceFile(hand, true); }, - { - title: 'Flags', - icon: 'menu', - // fileModel: this.wasm ? 'wasm' : 'db', - clickHandler: (item: MenuItem): void => { - this.search = false; - this.showContent(this.spFlags!); - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'flags', - action: 'flags', - }); - }, + }, + { + title: 'Open long trace file', + icon: 'folder', + fileChoose: true, + fileHandler: (ev: InputEvent): void => { + this.openLongTraceFile(ev); }, - { - title: 'Keyboard Shortcuts', - icon: 'smart-help', - clickHandler: (item: MenuItem): void => { - document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; - SpSystemTrace.keyboardFlar = false; - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'Keyboard Shortcuts', - action: 'Keyboard Shortcuts', - }); - }, + clickHandler: (hand: any): void => { + this.openLongTraceFile(hand, true); }, - { - title: '第三方文件', - icon: 'file-fill', - fileModel: this.wasm ? 'wasm' : 'db', - clickHandler: (item: MenuItem): void => { - this.search = false; - this.showContent(this.spThirdParty!); - }, + }, + { + title: 'Record new trace', + icon: 'copyhovered', + clickHandler: (item: MenuItem): void => this.clickHandleByRecordNewTrace(), + }, + { + title: 'Record template', + icon: 'copyhovered', + clickHandler: (item: MenuItem): void => this.clickHandleByRecordTemplate(), + }, + ], + }; + } + + private initSupportMenus() { + return { + collapsed: false, + title: 'Support', + second: false, + icon: '', + describe: 'Support', + children: [ + { + title: 'Help Documents', + icon: 'smart-help', + clickHandler: (item: MenuItem): void => this.clickHandleByHelpDocuments(), + }, + { + title: 'Flags', + icon: 'menu', + clickHandler: (item: MenuItem): void => this.clickHandleByFlags(), + }, + { + title: 'Keyboard Shortcuts', + icon: 'smart-help', + clickHandler: (item: MenuItem): void => this.clickHandleByKeyboardShortcuts(), + }, + { + title: 'Third File', + icon: 'file-fill', + fileModel: this.wasm ? 'wasm' : 'db', + clickHandler: (item: MenuItem): void => { + this.returnOriginalUrl(); + this.search = false; + this.showContent(this.spThirdParty!); }, - ], - }, - ]; + }, + ], + }; + } + + private clickHandleByHelpDocuments(): void { + this.spHelp!.dark = this.dark; + this.search = false; + this.showContent(this.spHelp!); + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'help_page', + action: 'help_doc', + }); + this.changeUrl(); + } + + private clickHandleByFlags(): void { + this.returnOriginalUrl(); + this.search = false; + this.showContent(this.spFlags!); + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'flags', + action: 'flags', + }); + } + + private clickHandleByKeyboardShortcuts(): void { + this.returnOriginalUrl(); + document + .querySelector('body > sp-application')! + .shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; + SpSystemTrace.keyboardFlar = false; + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'Keyboard Shortcuts', + action: 'Keyboard Shortcuts', + }); + } + + private clickHandleByRecordNewTrace(): void { + this.returnOriginalUrl(); + this.spRecordTrace!.synchronizeDeviceList(); + this.spRecordTemplate!.record_template = false; + this.spRecordTrace!.refreshConfig(true); + this.showContent(this.spRecordTrace!); + } + + private clickHandleByRecordTemplate(): void { + this.returnOriginalUrl(); + this.spRecordTemplate!.refreshHint(); + this.spRecordTemplate!.record_template = true; + this.spRecordTemplate!.refreshConfig(false); + this.spRecordTemplate!.synchronizeDeviceList(); + this.showContent(this.spRecordTemplate!); + } + + private changeUrl() { + let url = new URL(window.location.href); + let actionParam = url.searchParams.get('action'); + let newActionValue = 'help'; + if (actionParam) { + url.searchParams.set('action', newActionValue); + } else { + url.searchParams.append('action', newActionValue); + } + let newURL = url.href; + history.pushState({}, '', newURL); + } + + private returnOriginalUrl() { + history.pushState({}, '', window.location.origin + window.location.pathname); } private handleSqliteMode(ev: any, showFileName: string, fileSize: number, fileName: string): void { @@ -865,6 +926,7 @@ export class SpApplication extends BaseElement { that.freshMenuDisable(false); that.spInfoAndStats!.initInfoAndStatsData(); that.cutTraceFile!.style.display = 'none'; + that.headerDiv!.style.pointerEvents = 'auto'; } ); }; @@ -882,7 +944,7 @@ export class SpApplication extends BaseElement { that.freshMenuDisable(false); that.chartFilter!.setAttribute('mode', ''); that.progressEL!.loading = false; - }) + }); } else { let fileSizeStr = (fileSize / 1048576).toFixed(1); postLog(fileName, fileSizeStr); @@ -890,6 +952,9 @@ export class SpApplication extends BaseElement { info('Parse trace using wasm mode '); let completeHandler = async (res: any): Promise => { await this.traceLoadCompleteHandler(res, fileSizeStr, showFileName, fileName); + if (this.markJson) { + window.publish(window.SmartEvent.UI.ImportRecord, this.markJson); + } }; threadPool.init('wasm').then((res) => { let reader: FileReader | null = new FileReader(); @@ -900,7 +965,7 @@ export class SpApplication extends BaseElement { let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json`; SpApplication.loadingProgress = 0; SpApplication.progressStep = 3; - let data = this.result as ArrayBuffer; + let data = that.markPositionHandler(this.result as ArrayBuffer); info('initData start Parse Data'); that.spSystemTrace!.loadDatabaseArrayBuffer( data, @@ -913,6 +978,22 @@ export class SpApplication extends BaseElement { } } + private markPositionHandler(buf: ArrayBuffer): ArrayBuffer { + const decoder = new TextDecoder('utf-8'); + const headText = decoder.decode(buf.slice(0, 100)); + let hasMark = headText.includes('MarkPositionJSON'); + if (hasMark) { + let markLength = headText.split('->')[0].replace('MarkPositionJSON', ''); + let mark = decoder.decode(buf.slice(0, markLength.length + parseInt(markLength))); + if (mark.includes('->')) { + this.markJson = mark.split('->')[1]; + } + return buf.slice(markLength.length + parseInt(markLength)); + } else { + return buf; + } + } + private async traceLoadCompleteHandler( res: any, fileSize: string, @@ -942,6 +1023,7 @@ export class SpApplication extends BaseElement { this.loadTraceCompleteMenuHandler(index); if (res.status) { info('loadDatabaseArrayBuffer success'); + (window as any).traceFileName = fileName; this.showCurrentTraceMenu(fileSize, showFileName, fileName); this.importConfigDiv!.style.display = Utils.SCHED_SLICE_MAP.size > 0 ? 'block' : 'none'; this.showContent(this.spSystemTrace!); @@ -956,6 +1038,7 @@ export class SpApplication extends BaseElement { this.mainMenu!.menus = this.mainMenu!.menus!; } this.progressEL!.loading = false; + this.headerDiv!.style.pointerEvents = 'auto'; this.spInfoAndStats!.initInfoAndStatsData(); } @@ -982,7 +1065,7 @@ export class SpApplication extends BaseElement { } private loadTraceCompleteMenuHandler(index: number): void { - let that = this; + const that = this; this.mainMenu!.menus!.splice(index, 1, { collapsed: false, title: 'Support', @@ -993,38 +1076,26 @@ export class SpApplication extends BaseElement { { title: 'Help Documents', icon: 'smart-help', - clickHandler: function (item: MenuItem) { - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'help_page', - action: 'help_doc', - }); - that.search = false; - that.spHelp!.dark = that.dark; - that.showContent(that.spHelp!); - }, + clickHandler: (item: MenuItem): void => this.clickHandleByHelpDocuments(), }, { title: 'Flags', icon: 'menu', - clickHandler: function (item: MenuItem): void { - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'flags', - action: 'flags', - }); - that.search = false; - that.showContent(that.spFlags!); - }, + clickHandler: (item: MenuItem): void => this.clickHandleByFlags(), }, { title: 'Keyboard Shortcuts', icon: 'smart-help', - clickHandler: function (item: MenuItem): void { - document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; - SpSystemTrace.keyboardFlar = false; - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - event: 'Keyboard Shortcuts', - action: 'Keyboard Shortcuts', - }); + clickHandler: (item: MenuItem): void => this.clickHandleByKeyboardShortcuts(), + }, + { + title: 'Third File', + icon: 'file-fill', + fileModel: this.wasm ? 'wasm' : 'db', + clickHandler: (item: MenuItem): void => { + this.returnOriginalUrl(); + this.search = false; + this.showContent(this.spThirdParty!); }, }, ], @@ -1064,8 +1135,14 @@ export class SpApplication extends BaseElement { let hiPerfArray = new Uint8Array(hiperfData); let allOtherData = [ebpfData, arkTsData, hiperfData]; let otherDataLength = traceData.byteLength + ebpfData.byteLength + arkTsData.byteLength + hiperfData.byteLength; - let timeStamp = this.currentDataTime[0] + this.currentDataTime[1] + this.currentDataTime[2] + '_' + - this.currentDataTime[3] + this.currentDataTime[4] + this.currentDataTime[5]; + let timeStamp = + this.currentDataTime[0] + + this.currentDataTime[1] + + this.currentDataTime[2] + + '_' + + this.currentDataTime[3] + + this.currentDataTime[4] + + this.currentDataTime[5]; this.traceFileName = `hiprofiler_long_${timeStamp}_${indexedDbPageNum}.htrace`; if (otherDataLength > maxTraceFileLength) { if (traceData.byteLength > maxTraceFileLength) { @@ -1277,11 +1354,13 @@ export class SpApplication extends BaseElement { private openFileInit(): void { clearTraceFileCache(); this.litSearch!.clear(); + this.markJson = undefined; SpStatisticsHttpUtil.addOrdinaryVisitAction({ event: 'open_trace', action: 'open_trace', }); info('openTraceFile'); + this.headerDiv!.style.pointerEvents = 'none'; this.spSystemTrace!.clearPointPair(); this.spSystemTrace!.reset((command: string, percent: number) => { this.setProgress(command); @@ -1425,7 +1504,8 @@ export class SpApplication extends BaseElement { action: 'download', }); }, - }, { + }, + { title: 'Download Database', icon: 'download', fileModel: this.wasm ? 'wasm' : 'db', @@ -1436,7 +1516,7 @@ export class SpApplication extends BaseElement { action: 'download', }); }, - } + }, ]; this.getTraceQuerySqlMenus(menus); if ((window as any).cpuCount === 0 || !FlagsConfig.getFlagsConfigEnableStatus('SchedulingAnalysis')) { @@ -1477,7 +1557,9 @@ export class SpApplication extends BaseElement { title: 'Keyboard Shortcuts', icon: 'smart-help', clickHandler: (item: MenuItem): void => { - document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; + document + .querySelector('body > sp-application')! + .shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; SpStatisticsHttpUtil.addOrdinaryVisitAction({ event: 'Keyboard Shortcuts', action: 'Keyboard Shortcuts', @@ -1492,7 +1574,8 @@ export class SpApplication extends BaseElement { this.search = false; this.showContent(this.spThirdParty!); }, - }] + }, + ]; } private getTraceQuerySqlMenus(menus: Array): void { @@ -1611,6 +1694,9 @@ export class SpApplication extends BaseElement { if (arg.text) { this.litSearch!.setPercent(arg.text || '', arg.loading ? -1 : 101); } + if (this.headerDiv) { + this.headerDiv.style.pointerEvents = arg.loading ? 'none' : 'auto'; + } window.publish(window.SmartEvent.UI.MouseEventEnable, { mouseEnable: !arg.loading, }); @@ -1620,6 +1706,7 @@ export class SpApplication extends BaseElement { private initEvents(): void { this.addEventListener('copy', function (event) { + SpSystemTrace.isMouseLeftDown = false; let clipdata = event.clipboardData; let value = clipdata!.getData('text/plain'); let searchValue = value.toString().trim(); @@ -1628,6 +1715,7 @@ export class SpApplication extends BaseElement { this.initSearchEvents(); this.initSystemTraceEvents(); this.filterConfig!.addEventListener('click', (ev) => { + SpSystemTrace.isMouseLeftDown = false; if (this!.hasAttribute('chart_filter')) { this!.removeAttribute('chart_filter'); this.chartFilter!.setAttribute('hidden', ''); @@ -1644,37 +1732,49 @@ export class SpApplication extends BaseElement { this!.removeAttribute('chart_filter'); } }); - this.cutTraceFile!.addEventListener('click', () => { + this.cutTraceFile!.addEventListener('click', (ev) => { this.croppingFile(this.progressEL!, this.litSearch!); }); } + private initRecordEvents(): void { + this.exportRecord?.addEventListener('click', () => { + this.headerDiv!.style.pointerEvents = 'none'; + window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Downloading trace file with mark' }); + window.publish(window.SmartEvent.UI.ExportRecord, { bt: this.exportRecord }); + }); + } + private initSearchChangeEvents(): void { - this.litSearch!.valueChangeHandler = (value: string): void => { - this.litSearch!.isClearValue = false; - if (value.length > 0) { - let list: any[] = []; - this.progressEL!.loading = true; - this.spSystemTrace!.searchCPU(value).then((cpus) => { - list = cpus; - this.spSystemTrace!.searchFunction(list, value).then((mixedResults) => { - if (this.litSearch!.searchValue !== '') { - this.litSearch!.list = this.spSystemTrace!.searchSdk(mixedResults, value); - this.litSearch!.index = this.spSystemTrace!.showStruct(false, -1, this.litSearch!.list); - } - this.progressEL!.loading = false; + let timer: any = null; + this.litSearch!.valueChangeHandler = (value: string) => { + if (timer) clearTimeout(timer); + timer = setTimeout(() => { + this.litSearch!.isClearValue = false; + if (value.length > 0) { + let list: any[] = []; + this.progressEL!.loading = true; + this.spSystemTrace!.searchCPU(value).then((cpus) => { + list = cpus; + this.spSystemTrace!.searchFunction(list, value).then((mixedResults) => { + if (this.litSearch!.searchValue !== '') { + this.litSearch!.list = this.spSystemTrace!.searchSdk(mixedResults, value); + this.litSearch!.index = this.spSystemTrace!.showStruct(false, -1, this.litSearch!.list); + } + this.progressEL!.loading = false; + }); }); - }); - } else { - let indexEL = this.litSearch!.shadowRoot!.querySelector('#index'); - indexEL!.textContent = '0'; - this.litSearch!.list = []; - this.spSystemTrace?.visibleRows.forEach((it) => { - it.highlight = false; - it.draw(); - }); - this.spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); - } + } else { + let indexEL = this.litSearch!.shadowRoot!.querySelector('#index'); + indexEL!.textContent = '0'; + this.litSearch!.list = []; + this.spSystemTrace?.visibleRows.forEach((it) => { + it.highlight = false; + it.draw(); + }); + this.spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); + } + }, 1000); }; } private initSearchEvents(): void { @@ -2045,9 +2145,9 @@ export class SpApplication extends BaseElement { } let blobUrl = URL.createObjectURL(new Blob([cutBuffer!])); window.open( - `index.html?link=true&local=true&traceName=${encodeURIComponent(traceName)}_cut_${cutLeftTs}${fileType}&trace=${encodeURIComponent( - blobUrl - )}` + `index.html?link=true&local=true&traceName=${encodeURIComponent( + traceName + )}_cut_${cutLeftTs}${fileType}&trace=${encodeURIComponent(blobUrl)}` ); } else { litSearch.setPercent(msg, -1); diff --git a/ide/src/trace/SpApplicationPublicFunc.ts b/ide/src/trace/SpApplicationPublicFunc.ts index 89ec084c3efe2d708d322a8cd1e35c16a804648f..aed1c479ff8914cb2868037f0d67ee82c9826f62 100644 --- a/ide/src/trace/SpApplicationPublicFunc.ts +++ b/ide/src/trace/SpApplicationPublicFunc.ts @@ -353,6 +353,7 @@ export const applicationHtml: string = `
Confirm
+ diff --git a/ide/src/trace/bean/CpuFreqStruct.ts b/ide/src/trace/bean/CpuFreqStruct.ts index fe4545185454a97628b11e4e0de29191c1f40922..e8f0079cd0e4ae0d1c3a5d3cd8d652b8e37c7d2a 100644 --- a/ide/src/trace/bean/CpuFreqStruct.ts +++ b/ide/src/trace/bean/CpuFreqStruct.ts @@ -26,65 +26,50 @@ export class CpuFreqStruct extends BaseStruct { startNS: number | undefined; dur: number | undefined; // Self-supplementing, the database is not returned - static draw(freqBeanStructCanvasCtx: any, freqBeanStruct: CpuFreqStruct) { - if (freqBeanStruct.frame) { - let freqBeanStructWidth = freqBeanStruct.frame.width || 0; - let freqBeanStructIndex = freqBeanStruct.cpu || 0; - freqBeanStructIndex += 2; - freqBeanStructCanvasCtx.fillStyle = ColorUtils.colorForTid(freqBeanStructIndex); - freqBeanStructCanvasCtx.strokeStyle = ColorUtils.colorForTid(freqBeanStructIndex); - if (freqBeanStruct.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS) { - freqBeanStructCanvasCtx.lineWidth = 1; - freqBeanStructCanvasCtx.globalAlpha = 0.6; - let freqBeanStructDrawHeight: number = Math.floor( - ((freqBeanStruct.value || 0) * (freqBeanStruct.frame.height || 0) * 1.0) / CpuFreqStruct.maxFreq - ); - freqBeanStructCanvasCtx.fillRect( - freqBeanStruct.frame.x, - freqBeanStruct.frame.y + freqBeanStruct.frame.height - freqBeanStructDrawHeight, - freqBeanStructWidth, - freqBeanStructDrawHeight - ); - freqBeanStructCanvasCtx.beginPath(); - freqBeanStructCanvasCtx.arc( - freqBeanStruct.frame.x, - freqBeanStruct.frame.y + freqBeanStruct.frame.height - freqBeanStructDrawHeight, - 3, - 0, - 2 * Math.PI, - true - ); - freqBeanStructCanvasCtx.fill(); - freqBeanStructCanvasCtx.globalAlpha = 1.0; - freqBeanStructCanvasCtx.stroke(); - freqBeanStructCanvasCtx.beginPath(); - freqBeanStructCanvasCtx.moveTo( - freqBeanStruct.frame.x + 3, - freqBeanStruct.frame.y + freqBeanStruct.frame.height - freqBeanStructDrawHeight + static draw(freqCtx: any, freqData: CpuFreqStruct): void { + if (freqData.frame) { + let freqWidth = freqData.frame.width || 0; + let freqIndex = freqData.cpu || 0; + freqIndex += 2; + freqCtx.fillStyle = ColorUtils.colorForTid(freqIndex); + freqCtx.strokeStyle = ColorUtils.colorForTid(freqIndex); + if (freqData.startNS === CpuFreqStruct.hoverCpuFreqStruct?.startNS) { + freqCtx.lineWidth = 1; + freqCtx.globalAlpha = 0.6; + let drawHeight: number = Math.floor( + ((freqData.value || 0) * (freqData.frame.height || 0) * 1.0) / CpuFreqStruct.maxFreq ); - freqBeanStructCanvasCtx.lineWidth = 3; - freqBeanStructCanvasCtx.lineTo( - freqBeanStruct.frame.x + freqBeanStructWidth, - freqBeanStruct.frame.y + freqBeanStruct.frame.height - freqBeanStructDrawHeight + freqCtx.fillRect( + freqData.frame.x, + freqData.frame.y + freqData.frame.height - drawHeight, + freqWidth, + drawHeight ); - freqBeanStructCanvasCtx.stroke(); + freqCtx.beginPath(); + freqCtx.arc(freqData.frame.x, freqData.frame.y + freqData.frame.height - drawHeight, 3, 0, 2 * Math.PI, true); + freqCtx.fill(); + freqCtx.globalAlpha = 1.0; + freqCtx.stroke(); + freqCtx.beginPath(); + freqCtx.moveTo(freqData.frame.x + 3, freqData.frame.y + freqData.frame.height - drawHeight); + freqCtx.lineWidth = 3; + freqCtx.lineTo(freqData.frame.x + freqWidth, freqData.frame.y + freqData.frame.height - drawHeight); + freqCtx.stroke(); } else { - freqBeanStructCanvasCtx.globalAlpha = 0.6; - freqBeanStructCanvasCtx.lineWidth = 1; + freqCtx.globalAlpha = 0.6; + freqCtx.lineWidth = 1; let drawHeight: number = Math.floor( - ((freqBeanStruct.value || 0) * (freqBeanStruct.frame.height || 0)) / CpuFreqStruct.maxFreq + ((freqData.value || 0) * (freqData.frame.height || 0)) / CpuFreqStruct.maxFreq ); - freqBeanStructCanvasCtx.fillRect( - freqBeanStruct.frame.x, - freqBeanStruct.frame.y + freqBeanStruct.frame.height - drawHeight, - freqBeanStructWidth, + freqCtx.fillRect( + freqData.frame.x, + freqData.frame.y + freqData.frame.height - drawHeight, + freqWidth, drawHeight ); } } - freqBeanStructCanvasCtx.globalAlpha = 1.0; - freqBeanStructCanvasCtx.lineWidth = 1; + freqCtx.globalAlpha = 1.0; + freqCtx.lineWidth = 1; } } - -const textPadding = 2; diff --git a/ide/src/trace/bean/CpuStruct.ts b/ide/src/trace/bean/CpuStruct.ts index 09218cb4ce94879854b64073289e32ebc2002b4c..5911b260b57c3f4a1efd01087b44d4bda791643b 100644 --- a/ide/src/trace/bean/CpuStruct.ts +++ b/ide/src/trace/bean/CpuStruct.ts @@ -36,75 +36,51 @@ export class CpuStruct extends BaseStruct { tid: number | undefined; type: string | undefined; - static draw(cpuBeanStructCanvasCtx: CanvasRenderingContext2D, cpuBeanStruct: CpuStruct) { - if (cpuBeanStruct.frame) { - let cpuBeanStructWidth = cpuBeanStruct.frame.width || 0; - if (cpuBeanStruct.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { - cpuBeanStructCanvasCtx.fillStyle = ColorUtils.colorForTid( - (cpuBeanStruct.processId || 0) > 0 ? cpuBeanStruct.processId || 0 : cpuBeanStruct.tid || 0 + static draw(cpuCtx: CanvasRenderingContext2D, cpuStruct: CpuStruct): void { + if (cpuStruct.frame) { + let cpuWidth = cpuStruct.frame.width || 0; + if (cpuStruct.processId === CpuStruct.hoverCpuStruct?.processId || !CpuStruct.hoverCpuStruct) { + cpuCtx.fillStyle = ColorUtils.colorForTid( + (cpuStruct.processId || 0) > 0 ? cpuStruct.processId || 0 : cpuStruct.tid || 0 ); } else { - cpuBeanStructCanvasCtx.fillStyle = '#e0e0e0'; + cpuCtx.fillStyle = '#e0e0e0'; } - cpuBeanStructCanvasCtx.fillRect( - cpuBeanStruct.frame.x, - cpuBeanStruct.frame.y, - cpuBeanStructWidth, - cpuBeanStruct.frame.height - ); - if (cpuBeanStructWidth > textPadding * 2) { - let cpuBeanProcess = `${cpuBeanStruct.processName || 'Process'} [${cpuBeanStruct.processId}]`; - let cpuBeanThread = `${cpuBeanStruct.name || 'Thread'} [${cpuBeanStruct.tid}]`; - let cpuBeanProcessMeasure = cpuBeanStructCanvasCtx.measureText(cpuBeanProcess); - let cpuBeanThreadMeasure = cpuBeanStructCanvasCtx.measureText(cpuBeanThread); - let cpuBeanProcessCharWidth = Math.round(cpuBeanProcessMeasure.width / cpuBeanProcess.length); - let cpuBeanThreadCharWidth = Math.round(cpuBeanThreadMeasure.width / cpuBeanThread.length); - cpuBeanStructCanvasCtx.fillStyle = '#ffffff'; - let y = cpuBeanStruct.frame.height / 2 + cpuBeanStruct.frame.y; - if (cpuBeanProcessMeasure.width < cpuBeanStructWidth - textPadding * 2) { - let x1 = Math.floor( - cpuBeanStructWidth / 2 - cpuBeanProcessMeasure.width / 2 + cpuBeanStruct.frame.x + textPadding - ); - cpuBeanStructCanvasCtx.textBaseline = 'bottom'; - cpuBeanStructCanvasCtx.fillText(cpuBeanProcess, x1, y, cpuBeanStructWidth - textPadding * 2); - } else if (cpuBeanStructWidth - textPadding * 2 > cpuBeanProcessCharWidth * 4) { - let chatNum = (cpuBeanStructWidth - textPadding * 2) / cpuBeanProcessCharWidth; - let x1 = cpuBeanStruct.frame.x + textPadding; - cpuBeanStructCanvasCtx.textBaseline = 'bottom'; - cpuBeanStructCanvasCtx.fillText( - cpuBeanProcess.substring(0, chatNum - 4) + '...', - x1, - y, - cpuBeanStructWidth - textPadding * 2 - ); + cpuCtx.fillRect(cpuStruct.frame.x, cpuStruct.frame.y, cpuWidth, cpuStruct.frame.height); + if (cpuWidth > textPadding * 2) { + let cpuProcess = `${cpuStruct.processName || 'Process'} [${cpuStruct.processId}]`; + let cpuThread = `${cpuStruct.name || 'Thread'} [${cpuStruct.tid}]`; + let processMeasure = cpuCtx.measureText(cpuProcess); + let threadMeasure = cpuCtx.measureText(cpuThread); + let pChartWidth = Math.round(processMeasure.width / cpuProcess.length); + let tChartWidth = Math.round(threadMeasure.width / cpuThread.length); + cpuCtx.fillStyle = '#ffffff'; + let y = cpuStruct.frame.height / 2 + cpuStruct.frame.y; + if (processMeasure.width < cpuWidth - textPadding * 2) { + let x1 = Math.floor(cpuWidth / 2 - processMeasure.width / 2 + cpuStruct.frame.x + textPadding); + cpuCtx.textBaseline = 'bottom'; + cpuCtx.fillText(cpuProcess, x1, y, cpuWidth - textPadding * 2); + } else if (cpuWidth - textPadding * 2 > pChartWidth * 4) { + let chatNum = (cpuWidth - textPadding * 2) / pChartWidth; + let x1 = cpuStruct.frame.x + textPadding; + cpuCtx.textBaseline = 'bottom'; + cpuCtx.fillText(`${cpuProcess.substring(0, chatNum - 4)}...`, x1, y, cpuWidth - textPadding * 2); } - if (cpuBeanThreadMeasure.width < cpuBeanStructWidth - textPadding * 2) { - cpuBeanStructCanvasCtx.textBaseline = 'top'; - let x2 = Math.floor( - cpuBeanStructWidth / 2 - cpuBeanThreadMeasure.width / 2 + cpuBeanStruct.frame.x + textPadding - ); - cpuBeanStructCanvasCtx.fillText(cpuBeanThread, x2, y + 2, cpuBeanStructWidth - textPadding * 2); - } else if (cpuBeanStructWidth - textPadding * 2 > cpuBeanThreadCharWidth * 4) { - let chatNum = (cpuBeanStructWidth - textPadding * 2) / cpuBeanThreadCharWidth; - let x1 = cpuBeanStruct.frame.x + textPadding; - cpuBeanStructCanvasCtx.textBaseline = 'top'; - cpuBeanStructCanvasCtx.fillText( - cpuBeanThread.substring(0, chatNum - 4) + '...', - x1, - y + 2, - cpuBeanStructWidth - textPadding * 2 - ); + if (threadMeasure.width < cpuWidth - textPadding * 2) { + cpuCtx.textBaseline = 'top'; + let x2 = Math.floor(cpuWidth / 2 - threadMeasure.width / 2 + cpuStruct.frame.x + textPadding); + cpuCtx.fillText(cpuThread, x2, y + 2, cpuWidth - textPadding * 2); + } else if (cpuWidth - textPadding * 2 > tChartWidth * 4) { + let chatNum = (cpuWidth - textPadding * 2) / tChartWidth; + let x1 = cpuStruct.frame.x + textPadding; + cpuCtx.textBaseline = 'top'; + cpuCtx.fillText(`${cpuThread.substring(0, chatNum - 4)}...`, x1, y + 2, cpuWidth - textPadding * 2); } } - if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, cpuBeanStruct)) { - cpuBeanStructCanvasCtx.strokeStyle = '#232c5d'; - cpuBeanStructCanvasCtx.lineWidth = 2; - cpuBeanStructCanvasCtx.strokeRect( - cpuBeanStruct.frame.x, - cpuBeanStruct.frame.y, - cpuBeanStructWidth - 2, - cpuBeanStruct.frame.height - ); + if (CpuStruct.selectCpuStruct && CpuStruct.equals(CpuStruct.selectCpuStruct, cpuStruct)) { + cpuCtx.strokeStyle = '#232c5d'; + cpuCtx.lineWidth = 2; + cpuCtx.strokeRect(cpuStruct.frame.x, cpuStruct.frame.y, cpuWidth - 2, cpuStruct.frame.height); } } } @@ -113,11 +89,11 @@ export class CpuStruct extends BaseStruct { if ( d1 && d2 && - d1.cpu == d2.cpu && - d1.tid == d2.tid && - d1.processId == d2.processId && - d1.startTime == d2.startTime && - d1.dur == d2.dur + d1.cpu === d2.cpu && + d1.tid === d2.tid && + d1.processId === d2.processId && + d1.startTime === d2.startTime && + d1.dur === d2.dur ) { return true; } else { diff --git a/ide/src/trace/bean/FpsStruct.ts b/ide/src/trace/bean/FpsStruct.ts index 0a3b98abbee92b9bea575bbf00df2ba7efe2ec70..06c6b9ef9d044595ee50d60fdb07b512ce616e46 100644 --- a/ide/src/trace/bean/FpsStruct.ts +++ b/ide/src/trace/bean/FpsStruct.ts @@ -27,96 +27,63 @@ export class FpsStruct extends BaseStruct { startNS: number | undefined = 0; dur: number | undefined; //自补充,数据库没有返回 - static draw(fpsBeanStructCanvasCtx: CanvasRenderingContext2D, fpsBeanStructData: FpsStruct) { - if (fpsBeanStructData.frame) { - let fpsBeanWidth = fpsBeanStructData.frame.width || 0; - fpsBeanStructCanvasCtx.fillStyle = '#535da6'; - fpsBeanStructCanvasCtx.strokeStyle = '#535da6'; - if (fpsBeanStructData.startNS === FpsStruct.hoverFpsStruct?.startNS) { - fpsBeanStructCanvasCtx.lineWidth = 1; - fpsBeanStructCanvasCtx.globalAlpha = 0.6; - let drawHeight: number = - ((fpsBeanStructData.fps || 0) * (fpsBeanStructData.frame.height || 0) * 1.0) / FpsStruct.maxFps; - fpsBeanStructCanvasCtx.fillRect( - fpsBeanStructData.frame.x, - fpsBeanStructData.frame.y + fpsBeanStructData.frame.height - drawHeight, - fpsBeanWidth, - drawHeight - ); - fpsBeanStructCanvasCtx.beginPath(); - fpsBeanStructCanvasCtx.arc( - fpsBeanStructData.frame.x, - fpsBeanStructData.frame.y + fpsBeanStructData.frame.height - drawHeight, - 3, - 0, - 2 * Math.PI, - true - ); - fpsBeanStructCanvasCtx.fill(); - fpsBeanStructCanvasCtx.globalAlpha = 1.0; - fpsBeanStructCanvasCtx.stroke(); - fpsBeanStructCanvasCtx.beginPath(); - fpsBeanStructCanvasCtx.moveTo( - fpsBeanStructData.frame.x + 3, - fpsBeanStructData.frame.y + fpsBeanStructData.frame.height - drawHeight - ); - fpsBeanStructCanvasCtx.lineWidth = 3; - fpsBeanStructCanvasCtx.lineTo( - fpsBeanStructData.frame.x + fpsBeanWidth, - fpsBeanStructData.frame.y + fpsBeanStructData.frame.height - drawHeight - ); - fpsBeanStructCanvasCtx.stroke(); + static draw(fpsCtx: CanvasRenderingContext2D, fpsData: FpsStruct): void { + if (fpsData.frame) { + let fpsBeanWidth = fpsData.frame.width || 0; + fpsCtx.fillStyle = '#535da6'; + fpsCtx.strokeStyle = '#535da6'; + if (fpsData.startNS === FpsStruct.hoverFpsStruct?.startNS) { + fpsCtx.lineWidth = 1; + fpsCtx.globalAlpha = 0.6; + let drawHeight: number = ((fpsData.fps || 0) * (fpsData.frame.height || 0) * 1.0) / FpsStruct.maxFps; + fpsCtx.fillRect(fpsData.frame.x, fpsData.frame.y + fpsData.frame.height - drawHeight, fpsBeanWidth, drawHeight); + fpsCtx.beginPath(); + fpsCtx.arc(fpsData.frame.x, fpsData.frame.y + fpsData.frame.height - drawHeight, 3, 0, 2 * Math.PI, true); + fpsCtx.fill(); + fpsCtx.globalAlpha = 1.0; + fpsCtx.stroke(); + fpsCtx.beginPath(); + fpsCtx.moveTo(fpsData.frame.x + 3, fpsData.frame.y + fpsData.frame.height - drawHeight); + fpsCtx.lineWidth = 3; + fpsCtx.lineTo(fpsData.frame.x + fpsBeanWidth, fpsData.frame.y + fpsData.frame.height - drawHeight); + fpsCtx.stroke(); } else { - fpsBeanStructCanvasCtx.globalAlpha = 0.6; - fpsBeanStructCanvasCtx.lineWidth = 1; - let drawHeight: number = - ((fpsBeanStructData.fps || 0) * (fpsBeanStructData.frame.height || 0) * 1.0) / FpsStruct.maxFps; - fpsBeanStructCanvasCtx.fillRect( - fpsBeanStructData.frame.x, - fpsBeanStructData.frame.y + fpsBeanStructData.frame.height - drawHeight, - fpsBeanWidth, - drawHeight - ); + fpsCtx.globalAlpha = 0.6; + fpsCtx.lineWidth = 1; + let drawHeight: number = ((fpsData.fps || 0) * (fpsData.frame.height || 0) * 1.0) / FpsStruct.maxFps; + fpsCtx.fillRect(fpsData.frame.x, fpsData.frame.y + fpsData.frame.height - drawHeight, fpsBeanWidth, drawHeight); } } - fpsBeanStructCanvasCtx.globalAlpha = 1.0; - fpsBeanStructCanvasCtx.lineWidth = 1; + fpsCtx.globalAlpha = 1.0; + fpsCtx.lineWidth = 1; } static setFrame( - fpsBeanStructNode: FpsStruct, - fpsBeanFramePadding: number, + fpsStruct: FpsStruct, + padding: number, startNS: number, endNS: number, totalNS: number, frame: Rect - ) { + ): void { let fpsBeanStructX1: number, fpsBeanStructX2: number; - if ((fpsBeanStructNode.startNS || 0) < startNS) { + if ((fpsStruct.startNS || 0) < startNS) { fpsBeanStructX1 = 0; } else { - fpsBeanStructX1 = ns2x(fpsBeanStructNode.startNS || 0, startNS, endNS, totalNS, frame); + fpsBeanStructX1 = ns2x(fpsStruct.startNS || 0, startNS, endNS, totalNS, frame); } - if ((fpsBeanStructNode.startNS || 0) + (fpsBeanStructNode.dur || 0) > endNS) { + if ((fpsStruct.startNS || 0) + (fpsStruct.dur || 0) > endNS) { fpsBeanStructX2 = frame.width; } else { - fpsBeanStructX2 = ns2x( - (fpsBeanStructNode.startNS || 0) + (fpsBeanStructNode.dur || 0), - startNS, - endNS, - totalNS, - frame - ); + fpsBeanStructX2 = ns2x((fpsStruct.startNS || 0) + (fpsStruct.dur || 0), startNS, endNS, totalNS, frame); } let getV: number = fpsBeanStructX2 - fpsBeanStructX1 <= 1 ? 1 : fpsBeanStructX2 - fpsBeanStructX1; let rectangle: Rect = new Rect( Math.floor(fpsBeanStructX1), - Math.ceil(frame.y + fpsBeanFramePadding), + Math.ceil(frame.y + padding), Math.ceil(getV), - Math.floor(frame.height - fpsBeanFramePadding * 2) + Math.floor(frame.height - padding * 2) ); - fpsBeanStructNode.frame = rectangle; + fpsStruct.frame = rectangle; } -} - -const textPadding = 2; +} \ No newline at end of file diff --git a/ide/src/trace/bean/FrameChartStruct.ts b/ide/src/trace/bean/FrameChartStruct.ts index 7ecd6d01ddbb430387012cf4c6aa0e6c2cd1ec7c..dd60ef44787b3ba21326aceecb16320756804aac 100644 --- a/ide/src/trace/bean/FrameChartStruct.ts +++ b/ide/src/trace/bean/FrameChartStruct.ts @@ -26,6 +26,12 @@ const lightBlue = { b: 255, a: 0.9, }; +const lightGreen = { + r: 132, + g: 200, + b: 112, + a: 0.9, +}; export class ChartStruct extends BaseStruct { static hoverFuncStruct: ChartStruct | undefined; @@ -131,7 +137,11 @@ export function draw(canvasCtx: CanvasRenderingContext2D, node: ChartStruct): vo if (node.isSearch) { canvasCtx.fillStyle = `rgba(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b}, ${lightBlue.a})`; } else { - canvasCtx.fillStyle = getHeatColor(node.percent); + if (node.isJsStack) { + canvasCtx.fillStyle = `rgba(${lightGreen.r}, ${lightGreen.g}, ${lightGreen.b}, ${lightGreen.a})`; + } else { + canvasCtx.fillStyle = getHeatColor(node.percent); + } } } canvasCtx.fillRect(node.frame.x, node.frame.y, node.frame.width, drawHeight); @@ -144,15 +154,10 @@ export function draw(canvasCtx: CanvasRenderingContext2D, node: ChartStruct): vo canvasCtx.strokeStyle = '#000'; } } else { - if (node.isJsStack) { - canvasCtx.lineWidth = 0.6; - canvasCtx.strokeStyle = `rgb(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b})`; + if (spApplication.dark) { + canvasCtx.strokeStyle = '#000'; } else { - if (spApplication.dark) { - canvasCtx.strokeStyle = '#000'; - } else { - canvasCtx.strokeStyle = '#fff'; - } + canvasCtx.strokeStyle = '#fff'; } } canvasCtx.strokeRect(node.frame.x, node.frame.y, node.frame.width - canvasCtx.lineWidth, drawHeight); diff --git a/ide/src/trace/bean/HeapStruct.ts b/ide/src/trace/bean/HeapStruct.ts index 74a03ee30eedd4f48a64568ca18297edab13f8f6..7d7ea5202e1eec3ebdf8234e549abd9c03d6684d 100644 --- a/ide/src/trace/bean/HeapStruct.ts +++ b/ide/src/trace/bean/HeapStruct.ts @@ -14,8 +14,6 @@ */ import { BaseStruct } from './BaseStruct'; -import { ns2x } from '../component/trace/TimerShaftElement'; -import { Rect } from '../component/trace/timer-shaft/Rect'; export class HeapStruct extends BaseStruct { static hoverHeapStruct: HeapStruct | undefined; @@ -27,61 +25,39 @@ export class HeapStruct extends BaseStruct { density: number | undefined; maxHeapSize: number = 0; minHeapSize: number = 0; - static draw(heapBeanStructCanvasCtx: CanvasRenderingContext2D, heapBeanData: HeapStruct) { - if (heapBeanData.frame) { - let width = heapBeanData.frame.width || 0; - heapBeanStructCanvasCtx.fillStyle = '#2db3aa'; - heapBeanStructCanvasCtx.strokeStyle = '#2db3aa'; - if (heapBeanData.startTime === HeapStruct.hoverHeapStruct?.startTime) { - heapBeanStructCanvasCtx.lineWidth = 1; - heapBeanStructCanvasCtx.globalAlpha = 0.6; + + static draw(heapCtx: CanvasRenderingContext2D, heapData: HeapStruct): void { + if (heapData.frame) { + let width = heapData.frame.width || 0; + heapCtx.fillStyle = '#2db3aa'; + heapCtx.strokeStyle = '#2db3aa'; + if (heapData.startTime === HeapStruct.hoverHeapStruct?.startTime) { + heapCtx.lineWidth = 1; + heapCtx.globalAlpha = 0.6; let drawHeight: number = Math.ceil( - ((heapBeanData.heapsize || 0) * (heapBeanData.frame.height || 0)) / heapBeanData.maxHeapSize - ); - heapBeanStructCanvasCtx.fillRect( - heapBeanData.frame.x, - heapBeanData.frame.y + heapBeanData.frame.height - drawHeight, - width, - drawHeight - ); - heapBeanStructCanvasCtx.beginPath(); - heapBeanStructCanvasCtx.arc( - heapBeanData.frame.x, - heapBeanData.frame.y + heapBeanData.frame.height - drawHeight, - 3, - 0, - 2 * Math.PI, - true + ((heapData.heapsize || 0) * (heapData.frame.height || 0)) / heapData.maxHeapSize ); - heapBeanStructCanvasCtx.fill(); - heapBeanStructCanvasCtx.globalAlpha = 1.0; - heapBeanStructCanvasCtx.stroke(); - heapBeanStructCanvasCtx.beginPath(); - heapBeanStructCanvasCtx.moveTo( - heapBeanData.frame.x + 3, - heapBeanData.frame.y + heapBeanData.frame.height - drawHeight - ); - heapBeanStructCanvasCtx.lineWidth = 3; - heapBeanStructCanvasCtx.lineTo( - heapBeanData.frame.x + width, - heapBeanData.frame.y + heapBeanData.frame.height - drawHeight - ); - heapBeanStructCanvasCtx.stroke(); + heapCtx.fillRect(heapData.frame.x, heapData.frame.y + heapData.frame.height - drawHeight, width, drawHeight); + heapCtx.beginPath(); + heapCtx.arc(heapData.frame.x, heapData.frame.y + heapData.frame.height - drawHeight, 3, 0, 2 * Math.PI, true); + heapCtx.fill(); + heapCtx.globalAlpha = 1.0; + heapCtx.stroke(); + heapCtx.beginPath(); + heapCtx.moveTo(heapData.frame.x + 3, heapData.frame.y + heapData.frame.height - drawHeight); + heapCtx.lineWidth = 3; + heapCtx.lineTo(heapData.frame.x + width, heapData.frame.y + heapData.frame.height - drawHeight); + heapCtx.stroke(); } else { - heapBeanStructCanvasCtx.globalAlpha = 0.6; - heapBeanStructCanvasCtx.lineWidth = 1; + heapCtx.globalAlpha = 0.6; + heapCtx.lineWidth = 1; let drawHeight: number = Math.ceil( - ((heapBeanData.heapsize || 0) * (heapBeanData.frame.height || 0)) / heapBeanData.maxHeapSize - ); - heapBeanStructCanvasCtx.fillRect( - heapBeanData.frame.x, - heapBeanData.frame.y + heapBeanData.frame.height - drawHeight, - width, - drawHeight + ((heapData.heapsize || 0) * (heapData.frame.height || 0)) / heapData.maxHeapSize ); + heapCtx.fillRect(heapData.frame.x, heapData.frame.y + heapData.frame.height - drawHeight, width, drawHeight); } } - heapBeanStructCanvasCtx.globalAlpha = 1.0; - heapBeanStructCanvasCtx.lineWidth = 1; + heapCtx.globalAlpha = 1.0; + heapCtx.lineWidth = 1; } } diff --git a/ide/src/trace/bean/ProcessMemStruct.ts b/ide/src/trace/bean/ProcessMemStruct.ts index 707ea38edb0fa50c2a937962b86889d3edbf6c00..09a238d8c00bbf0f7180a177e9fd9d2b3b15dd49 100644 --- a/ide/src/trace/bean/ProcessMemStruct.ts +++ b/ide/src/trace/bean/ProcessMemStruct.ts @@ -18,7 +18,6 @@ import { ColorUtils } from '../component/trace/base/ColorUtils'; export class ProcessMemStruct extends BaseStruct { static hoverProcessMemStruct: ProcessMemStruct | undefined; - // trackId: number | undefined; processName: string | undefined; pid: number | undefined; upid: number | undefined; @@ -31,62 +30,37 @@ export class ProcessMemStruct extends BaseStruct { maxValue: number | undefined; delta: number | undefined; - static draw(processMemBeanStructCanvasCtx: CanvasRenderingContext2D, processMemBeanStructData: ProcessMemStruct) { - if (processMemBeanStructData.frame) { - let width = processMemBeanStructData.frame.width || 0; - if (processMemBeanStructData.startTime === ProcessMemStruct.hoverProcessMemStruct?.startTime) { - processMemBeanStructCanvasCtx.lineWidth = 1; - processMemBeanStructCanvasCtx.globalAlpha = 0.6; + static draw(pMemCtx: CanvasRenderingContext2D, pMemData: ProcessMemStruct): void { + if (pMemData.frame) { + let width = pMemData.frame.width || 0; + if (pMemData.startTime === ProcessMemStruct.hoverProcessMemStruct?.startTime) { + pMemCtx.lineWidth = 1; + pMemCtx.globalAlpha = 0.6; let drawHeight: number = Math.floor( - ((processMemBeanStructData.value || 0) * (processMemBeanStructData.frame.height || 0) * 1.0) / - (processMemBeanStructData.maxValue || 0) + ((pMemData.value || 0) * (pMemData.frame.height || 0) * 1.0) / (pMemData.maxValue || 0) ); - processMemBeanStructCanvasCtx.fillRect( - processMemBeanStructData.frame.x, - processMemBeanStructData.frame.y + processMemBeanStructData.frame.height - drawHeight, - width, - drawHeight - ); - processMemBeanStructCanvasCtx.beginPath(); - processMemBeanStructCanvasCtx.arc( - processMemBeanStructData.frame.x, - processMemBeanStructData.frame.y + processMemBeanStructData.frame.height - drawHeight, - 3, - 0, - 2 * Math.PI, - true - ); - processMemBeanStructCanvasCtx.fill(); - processMemBeanStructCanvasCtx.globalAlpha = 1.0; - processMemBeanStructCanvasCtx.stroke(); - processMemBeanStructCanvasCtx.beginPath(); - processMemBeanStructCanvasCtx.moveTo( - processMemBeanStructData.frame.x + 3, - processMemBeanStructData.frame.y + processMemBeanStructData.frame.height - drawHeight - ); - processMemBeanStructCanvasCtx.lineWidth = 3; - processMemBeanStructCanvasCtx.lineTo( - processMemBeanStructData.frame.x + width, - processMemBeanStructData.frame.y + processMemBeanStructData.frame.height - drawHeight - ); - processMemBeanStructCanvasCtx.stroke(); + pMemCtx.fillRect(pMemData.frame.x, pMemData.frame.y + pMemData.frame.height - drawHeight, width, drawHeight); + pMemCtx.beginPath(); + pMemCtx.arc(pMemData.frame.x, pMemData.frame.y + pMemData.frame.height - drawHeight, 3, 0, 2 * Math.PI, true); + pMemCtx.fill(); + pMemCtx.globalAlpha = 1.0; + pMemCtx.stroke(); + pMemCtx.beginPath(); + pMemCtx.moveTo(pMemData.frame.x + 3, pMemData.frame.y + pMemData.frame.height - drawHeight); + pMemCtx.lineWidth = 3; + pMemCtx.lineTo(pMemData.frame.x + width, pMemData.frame.y + pMemData.frame.height - drawHeight); + pMemCtx.stroke(); } else { - processMemBeanStructCanvasCtx.fillStyle = ColorUtils.colorForTid(processMemBeanStructData.maxValue || 0); - processMemBeanStructCanvasCtx.strokeStyle = ColorUtils.colorForTid(processMemBeanStructData.maxValue || 0); - processMemBeanStructCanvasCtx.globalAlpha = 0.6; - processMemBeanStructCanvasCtx.lineWidth = 1; + pMemCtx.fillStyle = ColorUtils.colorForTid(pMemData.maxValue || 0); + pMemCtx.strokeStyle = ColorUtils.colorForTid(pMemData.maxValue || 0); + pMemCtx.globalAlpha = 0.6; + pMemCtx.lineWidth = 1; let drawHeight: number = - ((processMemBeanStructData.value || 0) * (processMemBeanStructData.frame.height || 0) * 1.0) / - (processMemBeanStructData.maxValue || 1); - processMemBeanStructCanvasCtx.fillRect( - processMemBeanStructData.frame.x, - processMemBeanStructData.frame.y + processMemBeanStructData.frame.height - drawHeight, - width, - drawHeight - ); + ((pMemData.value || 0) * (pMemData.frame.height || 0) * 1.0) / (pMemData.maxValue || 1); + pMemCtx.fillRect(pMemData.frame.x, pMemData.frame.y + pMemData.frame.height - drawHeight, width, drawHeight); } } - processMemBeanStructCanvasCtx.globalAlpha = 1.0; - processMemBeanStructCanvasCtx.lineWidth = 1; + pMemCtx.globalAlpha = 1.0; + pMemCtx.lineWidth = 1; } } diff --git a/ide/src/trace/bean/ProcessStruct.ts b/ide/src/trace/bean/ProcessStruct.ts index 04ff2d1babf518524d05fe5c4d02643c194d7d23..15b69b6efa7affa3a75b22951e2feb07b792f6b7 100644 --- a/ide/src/trace/bean/ProcessStruct.ts +++ b/ide/src/trace/bean/ProcessStruct.ts @@ -35,7 +35,6 @@ export class ProcessStruct extends BaseStruct { static draw(processBeanCanvasCtx: CanvasRenderingContext2D, processBeanStruct: ProcessStruct) { if (processBeanStruct.frame) { - let width = processBeanStruct.frame.width || 0; processBeanCanvasCtx.fillStyle = ColorUtils.colorForTid(processBeanStruct.pid || 0); let miniHeight = Math.round(processBeanStruct.frame.height / CpuStruct.cpuCount); processBeanCanvasCtx.fillRect( diff --git a/ide/src/trace/component/SpFlag.html.ts b/ide/src/trace/component/SpFlag.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..273c5cea4fe0a2c30c8f4f9fccbcd34c870e38ce --- /dev/null +++ b/ide/src/trace/component/SpFlag.html.ts @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const SpFlagHtml = ` +
+
+

Feature flags

+
+
+ `; diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts index 347e88b6f3460a03e7fc529ce0b7ca90623990b7..ea2855c451960d2e38420ca7b64188be6f9148af 100644 --- a/ide/src/trace/component/SpFlags.ts +++ b/ide/src/trace/component/SpFlags.ts @@ -14,6 +14,7 @@ */ import { BaseElement, element } from '../../base-ui/BaseElement'; +import { SpFlagHtml } from './SpFlag.html'; @element('sp-flags') export class SpFlags extends BaseElement { @@ -27,113 +28,7 @@ export class SpFlags extends BaseElement { } initHtml(): string { - return ` - ${this.initHtmlStyle()} -
-
-

Feature flags

-
-
- `; - } - - private initHtmlStyle(): string { - return ` - - `; + return SpFlagHtml; } private createConfigDiv(): HTMLDivElement { @@ -342,7 +237,7 @@ export class FlagsConfig { { title: 'VSync', switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], - describeContent: '', + describeContent: 'VSync Signal drawing', }, ]; diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index a54d88af39d19505885ca1e5a34669cd306ed209..2e0c51540af388804256f77e511d6d5fca0fcccf 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -18,6 +18,7 @@ import { LitMainMenuGroup } from '../../base-ui/menu/LitMainMenuGroup'; import { LitMainMenu, MenuItem } from '../../base-ui/menu/LitMainMenu'; import { LitMainMenuItem } from '../../base-ui/menu/LitMainMenuItem'; import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; +import { eventDefinitions } from '../enums/helpDocEnums' @element('sp-help') export class SpHelp extends BaseElement { @@ -71,6 +72,28 @@ export class SpHelp extends BaseElement { value.style.display = 'none'; } }); + let urlParams = new URL(window.location.href).searchParams; + if (urlParams && urlParams.get('action') && urlParams.get('action')!.length > 4) { + this.itemHelpClick(urlParams, that); + } + } + + private itemHelpClick(urlParams: URLSearchParams, that: this) { + if (urlParams.get('action')!.length > 4) { + let helpDocIndex = urlParams.get('action')!.substring(5) + let helpDocDetail = this.getEventDefinitionByIndex(Number(helpDocIndex)); + that.appContent!.innerHTML = + ``; + } + } + + private getEventDefinitionByIndex(index: number) { + for (let key in eventDefinitions) { + if (eventDefinitions[key].index === index) { + return eventDefinitions[key]; + } + } + return null; } private setupMainMenu(mainMenu: LitMainMenu, that: this): void { @@ -132,21 +155,21 @@ export class SpHelp extends BaseElement { title: '设备端抓取trace说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'record', 'quickstart_device_record'); + that.handleMemoryMenuItemClick(that, 'record', 'quickstart_device_record','1'); }, }, { title: 'web端抓取trace说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'online_record', 'quickstart_web_record'); + that.handleMemoryMenuItemClick(that, 'online_record', 'quickstart_web_record','2'); }, }, { title: 'web端加载trace说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'load', 'quickstart_systemtrace'); + that.handleMemoryMenuItemClick(that, 'load', 'quickstart_systemtrace','3'); }, }, ], @@ -165,24 +188,24 @@ export class SpHelp extends BaseElement { } private setupOtherMenuItems(that: this): MenuItem[] { return [ - this.createSubMenuItem('Sql分析和Metrics说明', 'sql', 'quickstart_sql_metrics', that), - this.createSubMenuItem('HiSystemEvent抓取和展示说明', 'hisys', 'quickstart_hisystemevent', that), - this.createSubMenuItem('sdk抓取和展示说明', 'sdk_record', 'quickstart_sdk', that), - this.createSubMenuItem('调用栈可视化和不同库函数调用占比说明', 'import_so', 'quickstart_Import_so', that), - this.createSubMenuItem('Hilog抓取和展示说明', 'hilog', 'quickstart_hilog', that), - this.createSubMenuItem('Ability Monitor抓取和展示说明', 'ability', 'quickstart_ability_monitor', that), - this.createSubMenuItem('Trace解析能力增强', 'trace_parsing', 'quickstart_parsing_ability', that), - this.createSubMenuItem('应用操作技巧', 'operation_skills', 'quickstart_Application_operation_skills', that), - this.createSubMenuItem('快捷键说明', 'keywords_shortcuts', 'quickstart_keywords_shortcuts', that), + this.createSubMenuItem('Sql分析和Metrics说明', 'sql', 'quickstart_sql_metrics', that,'17'), + this.createSubMenuItem('HiSystemEvent抓取和展示说明', 'hisys', 'quickstart_hisystemevent', that,'18'), + this.createSubMenuItem('sdk抓取和展示说明', 'sdk_record', 'quickstart_sdk', that,'19'), + this.createSubMenuItem('调用栈可视化和不同库函数调用占比说明', 'import_so', 'quickstart_Import_so', that,'20'), + this.createSubMenuItem('Hilog抓取和展示说明', 'hilog', 'quickstart_hilog', that,'21'), + this.createSubMenuItem('Ability Monitor抓取和展示说明', 'ability', 'quickstart_ability_monitor', that,'22'), + this.createSubMenuItem('Trace解析能力增强', 'trace_parsing', 'quickstart_parsing_ability', that,'23'), + this.createSubMenuItem('应用操作技巧', 'operation_skills', 'quickstart_Application_operation_skills', that,'24'), + this.createSubMenuItem('快捷键说明', 'keywords_shortcuts', 'quickstart_keywords_shortcuts', that,'25'), ]; } - private createSubMenuItem(title: string, event: string, docName: string, that: this): MenuItem { + private createSubMenuItem(title: string, event: string, docName: string, that: this, index: string): MenuItem { return { title: title, icon: '', clickHandler: (item: MenuItem) => { - that.handleMemoryMenuItemClick(that, event, docName); + that.handleMemoryMenuItemClick(that, event, docName, index); }, }; } @@ -200,41 +223,55 @@ export class SpHelp extends BaseElement { title: 'Js Memory抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'js_memory', 'quickstart_Js_memory'); + that.handleMemoryMenuItemClick(that, 'js_memory', 'quickstart_Js_memory','4'); }, }, { title: 'Native Memory抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'native', 'quickstart_native_memory'); + that.handleMemoryMenuItemClick(that, 'native', 'quickstart_native_memory','5'); }, }, { title: '页内存抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'virtual_memory', 'quickstart_page_fault'); + that.handleMemoryMenuItemClick(that, 'virtual_memory', 'quickstart_page_fault','6'); }, }, { title: '系统内存抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'memory_template', 'quickstart_memory_template'); + that.handleMemoryMenuItemClick(that, 'memory_template', 'quickstart_memory_template','7'); }, }, ], }; } - private handleMemoryMenuItemClick(that: this, event: string, docName: string): void { + private handleMemoryMenuItemClick(that: this, event: string, docName: string,index?: string): void { SpStatisticsHttpUtil.addOrdinaryVisitAction({ event: event, action: 'help_doc', }); that.appContent!.innerHTML = ``; + this.changeItemURL(index!); + } + + private changeItemURL(index: string) { + let url = new URL(window.location.href); + let actionParam = url.searchParams.get("action"); + let newActionValue = `help_${index}`; + if (actionParam) { + url.searchParams.set("action", newActionValue); + let newURL = url.href; + history.pushState({}, "", newURL); + } else { + history.pushState({}, "", window.location.origin + window.location.pathname); + } } private setupNativeMenu(that: this) { @@ -249,7 +286,7 @@ export class SpHelp extends BaseElement { title: 'HiPerf的抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'perf', 'quickstart_hiperf'); + that.handleMemoryMenuItemClick(that, 'perf', 'quickstart_hiperf','8'); }, }, ], @@ -268,7 +305,7 @@ export class SpHelp extends BaseElement { title: 'Cpuprofiler抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'arkts', 'quickstart_arkts'); + that.handleMemoryMenuItemClick(that, 'arkts', 'quickstart_arkts','9'); }, }, ], @@ -287,35 +324,35 @@ export class SpHelp extends BaseElement { title: 'Frame timeline抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'frame_record', 'quickstart_Frametimeline'); + that.handleMemoryMenuItemClick(that, 'frame_record', 'quickstart_Frametimeline','10'); }, }, { title: 'Animation的抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'animation', 'quickstart_animation'); + that.handleMemoryMenuItemClick(that, 'animation', 'quickstart_animation','11'); }, }, { title: 'TaskPool抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'taskpool', 'quickstart_taskpool'); + that.handleMemoryMenuItemClick(that, 'taskpool', 'quickstart_taskpool','12'); }, }, { title: 'App startup的抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'app_startup', 'quickstart_app_startup'); + that.handleMemoryMenuItemClick(that, 'app_startup', 'quickstart_app_startup','13'); }, }, { title: 'Scheduling analysis抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'scheduling_record', 'quickstart_schedulinganalysis'); + that.handleMemoryMenuItemClick(that, 'scheduling_record', 'quickstart_schedulinganalysis','14'); }, }, ], @@ -334,14 +371,14 @@ export class SpHelp extends BaseElement { title: 'FileSystem抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'file_system', 'quickstart_filesystem'); + that.handleMemoryMenuItemClick(that, 'file_system', 'quickstart_filesystem','15'); }, }, { title: 'Bio抓取和展示说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'bio', 'quickstart_bio'); + that.handleMemoryMenuItemClick(that, 'bio', 'quickstart_bio','16'); }, }, ], @@ -353,7 +390,7 @@ export class SpHelp extends BaseElement { title: 'TraceStreamer数据库说明', icon: '', clickHandler: function (item: MenuItem) { - that.handleMemoryMenuItemClick(that, 'trace_streamer_explain', 'des_tables'); + that.handleMemoryMenuItemClick(that, 'trace_streamer_explain', 'des_tables','26'); }, }; } diff --git a/ide/src/trace/component/SpRecordTrace.ts b/ide/src/trace/component/SpRecordTrace.ts index ff0d1d2f5304a5c37d07040d6d1f6c671b65a557..808bc6732e0d6038d64d5d92a6bccf2adb2dbdce 100644 --- a/ide/src/trace/component/SpRecordTrace.ts +++ b/ide/src/trace/component/SpRecordTrace.ts @@ -1177,61 +1177,57 @@ export class SpRecordTrace extends BaseElement { } ); this.litSearch!.setPercent(`downloading ${fileType} file `, 101); - let buffer = await pullRes.arrayBuffer(); - let chunks = Math.ceil(buffer.byteLength / indexDBMaxSize); - let offset = 0; - let sliceLen = 0; - let message = { - fileType: '', - startIndex: 0, - endIndex: 0, - size: 0, - }; - for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) { - let start = chunkIndex * indexDBMaxSize; - let end = Math.min(start + indexDBMaxSize, buffer.byteLength); - let chunk = buffer.slice(start, end); - if (chunkIndex === 0) { - message.fileType = fileType; - message.startIndex = chunkIndex; - } - sliceLen = Math.min(buffer.byteLength - offset, indexDBMaxSize); - if (chunkIndex === 0 && fileType === 'trace') { - this.sp!.longTraceHeadMessageList.push({ - pageNum: pageNumber, - data: buffer.slice(offset, kbSize), - }); - } - this.sp!.longTraceDataList.push({ - index: chunkIndex, - fileType: fileType, - pageNum: pageNumber, - startOffsetSize: offset, - endOffsetSize: offset + sliceLen, - }); - await LongTraceDBUtils.getInstance().indexedDBHelp.add(LongTraceDBUtils.getInstance().tableName, { - buf: chunk, - id: `${fileType}_${timStamp}_${pageNumber}_${chunkIndex}`, - fileType: fileType, - pageNum: pageNumber, - startOffset: offset, - endOffset: offset + sliceLen, - index: chunkIndex, - timStamp: timStamp, - }); - offset += sliceLen; - if (offset >= buffer.byteLength) { - message.endIndex = chunkIndex; - message.size = buffer.byteLength; - this.longTraceFileMapHandler(pageNumber, message); - } - } + await this.saveIndexDBByLongTrace(pullRes, fileType, pageNumber, timStamp); } } resolve(1); }); } + private async saveIndexDBByLongTrace(pullRes: Blob, fileType: string, pageNumber: number, timStamp: number) { + let buffer = await pullRes.arrayBuffer(); + let chunks = Math.ceil(buffer.byteLength / indexDBMaxSize); + let offset = 0; + let sliceLen = 0; + let message = {fileType: '', startIndex: 0, endIndex: 0, size: 0}; + for (let chunkIndex = 0; chunkIndex < chunks; chunkIndex++) { + let start = chunkIndex * indexDBMaxSize; + let end = Math.min(start + indexDBMaxSize, buffer.byteLength); + let chunk = buffer.slice(start, end); + if (chunkIndex === 0) { + message.fileType = fileType; + message.startIndex = chunkIndex; + } + sliceLen = Math.min(buffer.byteLength - offset, indexDBMaxSize); + if (chunkIndex === 0 && fileType === 'trace') { + this.sp!.longTraceHeadMessageList.push({ pageNum: pageNumber, data: buffer.slice(offset, kbSize)}); + } + this.sp!.longTraceDataList.push({ + index: chunkIndex, + fileType: fileType, + pageNum: pageNumber, + startOffsetSize: offset, + endOffsetSize: offset + sliceLen, + }); + await LongTraceDBUtils.getInstance().indexedDBHelp.add(LongTraceDBUtils.getInstance().tableName, { + buf: chunk, + id: `${fileType}_${timStamp}_${pageNumber}_${chunkIndex}`, + fileType: fileType, + pageNum: pageNumber, + startOffset: offset, + endOffset: offset + sliceLen, + index: chunkIndex, + timStamp: timStamp, + }); + offset += sliceLen; + if (offset >= buffer.byteLength) { + message.endIndex = chunkIndex; + message.size = buffer.byteLength; + this.longTraceFileMapHandler(pageNumber, message); + } + } + } + private longTraceFileMapHandler(pageNumber: number, message: { fileType: string, startIndex: number, diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index 9d7dbaa83cff3d5e463262641aa04f6f0f414f3c..1b275f6d275dc4ed30d30e985238d92387bc7c43 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -151,7 +151,7 @@ function jankClickHandlerFunc(sp: SpSystemTrace) { if (d.rowId === 'actual frameTime') { jankRowParent = sp.shadowRoot?.querySelector>("trace-row[row-id='frameTime']"); } else { - jankRowParent = sp.shadowRoot?.querySelector>(`trace-row[row-id='${d.pid}']`); + jankRowParent = sp.shadowRoot?.querySelector>(`trace-row[row-type='process'][row-id='${d.pid}']`); } jankRowParent!.expansion = true; let jankRow: any; @@ -180,9 +180,9 @@ function jankClickHandlerFunc(sp: SpSystemTrace) { // 绘制跟自己关联的线 datas.forEach((data) => { let endParentRow = sp.shadowRoot?.querySelector>( - `trace-row[row-id='${data.pid}'][folder]` + `trace-row[row-type='process'][row-id='${data.pid}'][folder]` ); - sp.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data); + sp.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data, true); }); }, jankClickHandler @@ -297,10 +297,10 @@ function cpuClickHandlerFunc(sp: SpSystemTrace) { }; } -function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRow) { +function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRow, entry?: any) { CpuStructOnClick(clickRowType, sp, cpuClickHandlerFunc(sp)) .then(() => ThreadStructOnClick(clickRowType, sp, threadClickHandlerFunc(sp), cpuClickHandlerFunc(sp))) - .then(() => FuncStructOnClick(clickRowType, sp, row, scrollToFuncHandlerFunc(sp))) + .then(() => FuncStructOnClick(clickRowType, sp, row, scrollToFuncHandlerFunc(sp), entry)) .then(() => CpuFreqStructOnClick(clickRowType, sp)) .then(() => CpuStateStructOnClick(clickRowType, sp)) .then(() => CpuFreqLimitsStructOnClick(clickRowType, sp)) @@ -314,7 +314,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo .then(() => AppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) .then(() => AllAppStartupStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) .then(() => SoStructOnClick(clickRowType, sp, scrollToFuncHandlerFunc(sp))) - .then(() => FrameAnimationStructOnClick(clickRowType, sp, row!)) + .then(() => FrameAnimationStructOnClick(clickRowType, sp,scrollToFuncHandlerFunc(sp), row!)) .then(() => FrameDynamicStructOnClick(clickRowType, sp, row)) .then(() => FrameSpacingStructOnClick(clickRowType, sp, row!)) .then(() => sampleStructOnClick(clickRowType, sp)) @@ -331,7 +331,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo } }).catch(e => { }); } -export default function spSystemTraceOnClickHandler(sp: SpSystemTrace, clickRowType: string, row?: TraceRow) { +export default function spSystemTraceOnClickHandler(sp: SpSystemTrace, clickRowType: string, row?: TraceRow, entry?: any) { if (row) { sp.currentRow = row; sp.setAttribute('clickRow', clickRowType); @@ -343,7 +343,7 @@ export default function spSystemTraceOnClickHandler(sp: SpSystemTrace, clickRowT sp.selectStructNull(); // 判断点击的线程是否在唤醒树内 timeoutJudge(sp); - allStructOnClick(clickRowType, sp, row); + allStructOnClick(clickRowType, sp, row, entry); if (!JankStruct.selectJankStruct) { sp.removeLinkLinesByBusinessType('janks'); } @@ -396,8 +396,18 @@ export function spSystemTraceDocumentOnMouseMove(sp: SpSystemTrace, ev: MouseEve ev.preventDefault(); return; } - if (ev.ctrlKey && ev.button === 0 && sp.isMouseLeftDown) { - sp.translateByMouseMove(ev); + if (ev.ctrlKey && ev.button === 0 && SpSystemTrace.isMouseLeftDown) { + // 计算当前tab组件的高度 + let tabHeight: number = sp.shadowRoot?.querySelector(`trace-sheet`)!.shadowRoot?.querySelector('lit-tabs')!.clientHeight! + 1; + // 计算当前屏幕内高与鼠标位置坐标高度的差值 + let diffHeight: number = window.innerHeight - ev.clientY; + // 如果差值大于面板高度,意味着鼠标位于泳道区域,可以通过ctrl+鼠标左键移动。否则不予生效 + if (diffHeight > tabHeight) { + sp.translateByMouseMove(ev); + } else { + // 若鼠标位于tab面板区,则将其中标志位置成false + SpSystemTrace.isMouseLeftDown = false; + } } sp.inFavoriteArea = sp.favoriteChartListEL?.containPoint(ev); if ((window as any).isSheetMove || sp.isMouseInSheet(ev)) { @@ -410,7 +420,9 @@ export function spSystemTraceDocumentOnMouseMove(sp: SpSystemTrace, ev: MouseEve if (sp.timerShaftEL?.isScaling()) { return; } + sp.timerShaftEL?.documentOnMouseMove(ev, sp); + if (isMouseInTimeShaft) { return; } @@ -458,7 +470,7 @@ export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEven return; } TraceRow.isUserInteraction = false; - sp.isMouseLeftDown = false; + SpSystemTrace.isMouseLeftDown = false if (sp.isMouseInSheet(ev)) { return; } @@ -469,6 +481,7 @@ export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEven } export function SpSystemTraceDocumentOnKeyPress(this: any, sp: SpSystemTrace, ev: KeyboardEvent) { + SpSystemTrace.isKeyUp = false; if (!sp.loadTraceCompleted) { return; } @@ -523,7 +536,7 @@ export function spSystemTraceDocumentOnMouseDown(sp: SpSystemTrace, ev: MouseEve return; } if (ev.button === 0) { - sp.isMouseLeftDown = true; + SpSystemTrace.isMouseLeftDown = true; if (ev.ctrlKey) { ev.preventDefault(); sp.style.cursor = 'move'; @@ -579,6 +592,7 @@ function handleTimerShaftActions(ev: MouseEvent, sp: SpSystemTrace) { } export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent) { + if ((window as any).collectResize) { return; } @@ -590,7 +604,7 @@ export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent ev.stopPropagation(); return; } - sp.isMouseLeftDown = false; + SpSystemTrace.isMouseLeftDown = false; if (ev.ctrlKey) { ev.preventDefault(); sp.offsetMouse = 0; @@ -614,12 +628,14 @@ export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent } export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEvent) { + SpSystemTrace.isKeyUp = true; if (sp.times.size > 0) { for (let timerId of sp.times) { clearTimeout(timerId); } } - if (ev.key.toLocaleLowerCase() === String.fromCharCode(47)) { + let flag: boolean = sp.parentElement?.querySelector('sp-record-trace')!.shadowRoot?.querySelector('lit-main-menu-item[icon="file-config"]')!.hasAttribute('back')!; + if (ev.key.toLocaleLowerCase() === String.fromCharCode(47) && !flag) { if (SpSystemTrace.keyboardFlar) { document.querySelector('body > sp-application')! .shadowRoot!.querySelector('#sp-keyboard')!.style.visibility = 'visible'; @@ -662,6 +678,7 @@ export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEven } document.addEventListener('keydown', sp.documentOnKeyDown); } + if (ev.ctrlKey) { spSystemTraceDocumentOnKeyUpCtrlKey(keyPress, sp); } @@ -688,11 +705,7 @@ function spSystemTraceDocumentOnKeyUpCtrlKey(keyPress: string, sp: SpSystemTrace sidebarButton.style.width = '48px'; importConfigDiv!.style.left = '45px'; searchBox!.style.display = 'none'; - if (timerShaft.style.height === '91.75px') { - rowPane.style.maxHeight = '900px' - } else { - rowPane.style.maxHeight = '797px' - } + rowPane.style.maxHeight = `100%`; } else { SpSystemTrace.isHiddenMenu = false; menuBox.style.width = '248px'; @@ -701,11 +714,7 @@ function spSystemTraceDocumentOnKeyUpCtrlKey(keyPress: string, sp: SpSystemTrace sidebarButton.style.width = '0px'; importConfigDiv!.style.left = '5px'; searchBox!.style.display = ''; - if (timerShaft.style.height === '91.75px') { - rowPane.style.maxHeight = '905.25px'; - } else { - rowPane.style.maxHeight = '849px'; - }; + rowPane.style.maxHeight = `100%`; } } if (keyPress === '[' && sp._slicesList.length > 1) { @@ -734,7 +743,7 @@ function handleClickActions(sp: SpSystemTrace, x: number, y: number, ev: MouseEv } let strict = true; let offset = false; - if (rows[0].rowType === TraceRow.ROW_TYPE_FRAME_DYNAMIC || rows[0].rowType === TraceRow.ROW_TYPE_FRAME_SPACING) { + if (rows[0] && (rows[0].rowType === TraceRow.ROW_TYPE_FRAME_DYNAMIC || rows[0].rowType === TraceRow.ROW_TYPE_FRAME_SPACING)) { strict = false; offset = true; } diff --git a/ide/src/trace/component/SpSystemTrace.init.ts b/ide/src/trace/component/SpSystemTrace.init.ts index 7543b7c13ff07ddb72e32db90d6ea7aa1763b87a..84368f9db9c2bd70c42dab982dd32c18f3206987 100644 --- a/ide/src/trace/component/SpSystemTrace.init.ts +++ b/ide/src/trace/component/SpSystemTrace.init.ts @@ -14,982 +14,1025 @@ */ import { SpSystemTrace } from './SpSystemTrace'; -import { TabPaneFrequencySample } from "./trace/sheet/cpu/TabPaneFrequencySample"; -import { TabPaneCounterSample } from "./trace/sheet/cpu/TabPaneCounterSample"; -import { RangeSelect } from "./trace/base/RangeSelect"; -import { TraceRow } from "./trace/base/TraceRow"; -import { SportRuler } from "./trace/timer-shaft/SportRuler"; -import { SelectionParam } from "../bean/BoxSelection"; -import { error, info } from "../../log/Log"; -import { SpStatisticsHttpUtil } from "../../statistics/util/SpStatisticsHttpUtil"; -import { queryEbpfSamplesCount } from "../database/sql/Memory.sql"; -import { SpChartManager } from "./chart/SpChartManager"; -import { ThreadStruct } from "../database/ui-worker/ProcedureWorkerThread"; -import { FlagsConfig } from "./SpFlags"; -import { threadPool } from "../database/SqlLite"; -import { JankStruct } from "../database/ui-worker/ProcedureWorkerJank"; -import { CpuStruct } from "../database/ui-worker/cpu/ProcedureWorkerCPU"; -import { PairPoint } from "../database/ui-worker/ProcedureWorkerCommon"; +import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample'; +import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample'; +import { RangeSelect } from './trace/base/RangeSelect'; +import { TraceRow } from './trace/base/TraceRow'; +import { SportRuler } from './trace/timer-shaft/SportRuler'; +import { SelectionParam } from '../bean/BoxSelection'; +import { error, info } from '../../log/Log'; +import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil'; +import { queryEbpfSamplesCount } from '../database/sql/Memory.sql'; +import { SpChartManager } from './chart/SpChartManager'; +import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; +import { FlagsConfig } from './SpFlags'; +import { threadPool } from '../database/SqlLite'; +import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; +import { CpuStruct } from '../database/ui-worker/cpu/ProcedureWorkerCPU'; +import { PairPoint } from '../database/ui-worker/ProcedureWorkerCommon'; import { TraceSheet } from './trace/base/TraceSheet'; import { TimerShaftElement } from './trace/TimerShaftElement'; import { SpChartList } from './trace/SpChartList'; type HTMLElementAlias = HTMLElement | null | undefined; function rightButtonOnClick(sp: SpSystemTrace, rightStar: HTMLElementAlias) { - Object.assign(sp, { - ext(): string { - return "Handle the right button click event"; - } - }) + Object.assign(sp, { + ext(): string { + return 'Handle the right button click event'; + }, + }); - return function (event: any) { - if (SpSystemTrace.btnTimer) { - return; - } - // 唤醒树有值则不再重复添加 - const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('['); - if (SpSystemTrace.wakeupList.length === 0) { - SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); - sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); - CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; - CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; - CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; - CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); - CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; - sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); - } else { - sp.wakeupListNull(); - SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); - sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); - CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; - CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; - CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; - CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); - CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; - sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); - } - setTimeout(() => { - requestAnimationFrame(() => sp.refreshCanvas(false)); - }, 300); - rightStar!.style.visibility = 'visible'; - rightStar!.style.cursor = 'pointer'; - SpSystemTrace.btnTimer = setTimeout(() => { - SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器 - }, 2000); + return function (event: any): void { + if (SpSystemTrace.btnTimer) { + return; } + // 唤醒树有值则不再重复添加 + const startIndex = CpuStruct.selectCpuStruct!.displayProcess?.indexOf('['); + if (SpSystemTrace.wakeupList.length === 0) { + SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); + sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); + CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; + CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; + CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; + CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); + CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; + sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); + } else { + sp.wakeupListNull(); + SpSystemTrace.wakeupList.unshift(CpuStruct.wakeupBean!); + sp.queryCPUWakeUpList(CpuStruct.wakeupBean!); + CpuStruct.selectCpuStruct!.ts = CpuStruct.selectCpuStruct!.startTime; + CpuStruct.selectCpuStruct!.thread = CpuStruct.selectCpuStruct!.name; + CpuStruct.selectCpuStruct!.pid = CpuStruct.selectCpuStruct!.processId; + CpuStruct.selectCpuStruct!.process = CpuStruct.selectCpuStruct!.displayProcess?.substring(0, startIndex).trim(); + CpuStruct.selectCpuStruct!.itid = CpuStruct.wakeupBean!.itid; + sessionStorage.setItem('saveselectcpustruct', JSON.stringify(CpuStruct.selectCpuStruct)); + } + setTimeout(() => { + requestAnimationFrame(() => sp.refreshCanvas(false)); + }, 300); + rightStar!.style.visibility = 'visible'; + rightStar!.style.cursor = 'pointer'; + SpSystemTrace.btnTimer = setTimeout(() => { + SpSystemTrace.btnTimer = null; // 2.清空节流阀,方便下次开启定时器 + }, 2000); + }; } function rightStarOnClick(sp: SpSystemTrace) { - return function (ev: any) { - let wakeupLists = []; - wakeupLists.push(CpuStruct.selectCpuStruct?.cpu); - for (let wakeupBean of SpSystemTrace.wakeupList) { - wakeupLists.push(wakeupBean.cpu); - } - let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort(); - for (let wakeupCpu of wakeupCpuLists) { - let cpuFavoriteRow: any = sp.shadowRoot?.querySelector>( - `trace-row[row-type='cpu-data'][row-id='${wakeupCpu}']` - ); - if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) { - continue; - } - cpuFavoriteRow!.setAttribute('collect-type', ''); - let replaceRow = document.createElement('div'); - replaceRow.setAttribute('row-id', cpuFavoriteRow.rowId + '-' + cpuFavoriteRow.rowType); - replaceRow.setAttribute('type', 'replaceRow'); - replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId); - replaceRow.style.display = 'none'; - cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene'); - if (sp.rowsEL!.contains(cpuFavoriteRow)) { - sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow); - } - cpuFavoriteRow.tampName = cpuFavoriteRow.name; - sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, sp.currentCollectGroup, true); - sp.collectRows.push(cpuFavoriteRow); - sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); - sp.currentClickRow = null; - cpuFavoriteRow.setAttribute('draggable', 'true'); - cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp, cpuFavoriteRow)); - cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp)); - cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp, cpuFavoriteRow)); - cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp)); - } - sp.refreshFavoriteCanvas(); - sp.refreshCanvas(true); + return function (ev: any): void { + let wakeupLists = []; + wakeupLists.push(CpuStruct.selectCpuStruct?.cpu); + for (let wakeupBean of SpSystemTrace.wakeupList) { + wakeupLists.push(wakeupBean.cpu); + } + let wakeupCpuLists = Array.from(new Set(wakeupLists)).sort(); + for (let wakeupCpu of wakeupCpuLists) { + let cpuFavoriteRow: any = sp.shadowRoot?.querySelector>( + `trace-row[row-type='cpu-data'][row-id='${wakeupCpu}']` + ); + if (cpuFavoriteRow === null || cpuFavoriteRow === undefined) { + continue; + } + cpuFavoriteRow!.setAttribute('collect-type', ''); + let replaceRow = document.createElement('div'); + replaceRow.setAttribute('row-id', `${cpuFavoriteRow.rowId}-${cpuFavoriteRow.rowType}`); + replaceRow.setAttribute('type', 'replaceRow'); + replaceRow.setAttribute('row-parent-id', cpuFavoriteRow.rowParentId); + replaceRow.style.display = 'none'; + cpuFavoriteRow.rowHidden = !cpuFavoriteRow.hasAttribute('scene'); + if (sp.rowsEL!.contains(cpuFavoriteRow)) { + sp.rowsEL!.replaceChild(replaceRow, cpuFavoriteRow); + } + cpuFavoriteRow.tampName = cpuFavoriteRow.name; + sp.favoriteChartListEL!.insertRow(cpuFavoriteRow, sp.currentCollectGroup, true); + sp.collectRows.push(cpuFavoriteRow); + sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); + sp.currentClickRow = null; + cpuFavoriteRow.setAttribute('draggable', 'true'); + cpuFavoriteRow.addEventListener('dragstart', cpuFavoriteRowDragStart(sp, cpuFavoriteRow)); + cpuFavoriteRow.addEventListener('dragover', cpuFavoriteRowDragOver(sp)); + cpuFavoriteRow.addEventListener('drop', cpuFavoriteRowDropHandler(sp, cpuFavoriteRow)); + cpuFavoriteRow.addEventListener('dragend', cpuFavoriteRowDragendHandler(sp)); } + sp.refreshFavoriteCanvas(); + sp.refreshCanvas(true); + }; } function cpuFavoriteRowDragStart(sp: SpSystemTrace, cpuFavoriteRow: any) { - return function () { - sp.currentClickRow = cpuFavoriteRow; - } + return function (): void { + sp.currentClickRow = cpuFavoriteRow; + }; } function cpuFavoriteRowDragOver(sp: SpSystemTrace) { - return function (ev: any) { - ev.preventDefault(); - ev.dataTransfer.dropEffect = 'move'; - } + return function (ev: any): void { + ev.preventDefault(); + ev.dataTransfer.dropEffect = 'move'; + }; } function cpuFavoriteRowDropHandler(sp: SpSystemTrace, cpuFavoriteRow: any) { - return function (ev: any) { - if ( - sp.favoriteChartListEL != null && - sp.currentClickRow != null && - sp.currentClickRow !== cpuFavoriteRow - ) { - let rect = cpuFavoriteRow.getBoundingClientRect(); - if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { - //向上移动 - sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow); - } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { - //向下移动 - sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling); - } - sp.refreshFavoriteCanvas(); - } + return function (ev: any): void { + if (sp.favoriteChartListEL && sp.currentClickRow && sp.currentClickRow !== cpuFavoriteRow) { + let rect = cpuFavoriteRow.getBoundingClientRect(); + if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { + //向上移动 + sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow); + } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { + //向下移动 + sp.favoriteChartListEL.insertRowBefore(sp.currentClickRow, cpuFavoriteRow.nextSibling); + } + sp.refreshFavoriteCanvas(); } + }; } -function cpuFavoriteRowDragendHandler(sp: SpSystemTrace) { - return function () { - sp.linkNodes.forEach((itln) => { - if (itln[0].rowEL.collect) { - itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; - } else { - itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - if (itln[1].rowEL.collect) { - itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; - } else { - itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; - itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; - }); - sp.currentClickRow = null; +function cpuFavoriteRowDragendHandler(sp: SpSystemTrace): () => void { + return function (): void { + sp.linkNodes.forEach((itln) => { + if (itln[0].rowEL.collect) { + itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; + } else { + itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + if (itln[1].rowEL.collect) { + itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; + } else { + itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; + itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; + }); + sp.currentClickRow = null; + }; +} +function triangleFlagHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { + let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); + if (event.detail.timeCallback && temporaryTime) { + event.detail.timeCallback(temporaryTime); } + }; } -function triangleFlagHandler(sp: SpSystemTrace) { - return function (event: any) { - let temporaryTime = sp.timerShaftEL?.drawTriangle(event.detail.time, event.detail.type); - if (event.detail.timeCallback && temporaryTime) event.detail.timeCallback(temporaryTime); - }; +function numberCalibrationHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { + sp.timerShaftEL!.sportRuler!.times = event.detail.time; + sp.timerShaftEL!.sportRuler!.counts = event.detail.counts; + sp.timerShaftEL!.sportRuler!.durations = event.detail.durations; + sp.timerShaftEL!.sportRuler?.draw(); + }; } -function numberCalibrationHandler(sp: SpSystemTrace) { - return function (event: any) { - sp.timerShaftEL!.sportRuler!.times = event.detail.time; - sp.timerShaftEL!.sportRuler!.counts = event.detail.counts; - sp.timerShaftEL!.sportRuler!.durations = event.detail.durations; - sp.timerShaftEL!.sportRuler?.draw(); - } -} -function flagChangeHandler(sp: SpSystemTrace) { - return function (event: any) { - sp.timerShaftEL?.modifyFlagList(event.detail); - if (event.detail.hidden) { - sp.selectFlag = undefined; - if (sp._flagList.length <= 0) { - if (TraceRow.rangeSelectObject) { - let showTab = sp.getShowTab(); - showTab = showTab.filter((it) => it !== 'box-flag'); - sp.traceSheetEL?.displayTab(...showTab); - } else { - sp.traceSheetEL?.setMode('hidden'); - } - } - sp.refreshCanvas(true); +function flagChangeHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { + sp.timerShaftEL?.modifyFlagList(event.detail); + if (event.detail.hidden) { + sp.selectFlag = undefined; + if (sp._flagList.length <= 0) { + if (TraceRow.rangeSelectObject) { + let showTab = sp.getShowTab(); + showTab = showTab.filter((it) => it !== 'box-flag'); + sp.traceSheetEL?.displayTab(...showTab); + } else { + sp.traceSheetEL?.setMode('hidden'); } + } + sp.refreshCanvas(true); } + }; } -function slicesChangeHandler(sp: SpSystemTrace) { - return function (event: any) { - sp.timerShaftEL?.modifySlicesList(event.detail); - if (event.detail.hidden) { - sp.slicestime = null; - if (sp._slicesList.length <= 0) { - if (TraceRow.rangeSelectObject) { - let showTab = sp.getShowTab(); - showTab = showTab.filter((it) => it !== 'tabpane-current'); - sp.traceSheetEL?.displayTab(...showTab); - } else { - sp.traceSheetEL?.setMode('hidden'); - } - } - sp.refreshCanvas(true); +function slicesChangeHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { + sp.timerShaftEL?.modifySlicesList(event.detail); + if (event.detail.hidden) { + sp.slicestime = null; + if (sp._slicesList.length <= 0) { + if (TraceRow.rangeSelectObject) { + let showTab = sp.getShowTab(); + showTab = showTab.filter((it) => it !== 'tabpane-current'); + sp.traceSheetEL?.displayTab(...showTab); + } else { + sp.traceSheetEL?.setMode('hidden'); } + } + sp.refreshCanvas(true); } + }; } -function collectHandler(sp: SpSystemTrace) { - return function (event: any) { - let currentRow = event.detail.row; - if (currentRow.collect) { - collectHandlerYes(sp, currentRow, event); +function collectHandler(sp: SpSystemTrace): (event: any) => void { + return function (event: any): void { + let currentRow = event.detail.row; + if (currentRow.collect) { + collectHandlerYes(sp, currentRow, event); + } else { + collectHandlerNo(sp, currentRow, event); + } + sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); + sp.refreshFavoriteCanvas(); + sp.refreshCanvas(true); + sp.linkNodes.forEach((itln) => { + if (itln[0].rowEL === currentRow) { + if (itln[0].rowEL.collect) { + itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; } else { - collectHandlerNo(sp, currentRow, event); + itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; } - sp.timerShaftEL?.displayCollect(sp.collectRows.length !== 0); - sp.refreshFavoriteCanvas(); - sp.refreshCanvas(true); - sp.linkNodes.forEach((itln) => { - if (itln[0].rowEL === currentRow) { - if (itln[0].rowEL.collect) { - itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; - } else { - itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; - } else if (itln[1].rowEL === currentRow) { - if (itln[1].rowEL.collect) { - itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; - } else { - itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; - } - }); - // 收藏夹元素拖动排序功能 - sp.currentClickRow = null; - currentRow.setAttribute('draggable', 'true'); - currentRow.addEventListener('dragstart', () => { - sp.currentClickRow = currentRow; - }); - currentRow.addEventListener('dragover', (ev: any) => { - ev.preventDefault(); - ev.dataTransfer.dropEffect = 'move'; - }); - currentRow.addEventListener('drop', collectHandlerDrop(sp, currentRow)); - currentRow.addEventListener('dragend', collectHandlerDragEnd(sp)); - }; -} -function collectHandlerNo(sp: SpSystemTrace, currentRow: any, event: any) { - sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect'); - if (event.detail.type !== 'auto-collect') { - let rowIndex = sp.collectRows.indexOf(currentRow); - if (rowIndex !== -1) { - sp.collectRows.splice(rowIndex, 1); - } - } - let row = currentRow; - let allowExpansionRow = []; - while (row.hasParentRowEl) { - let parent = row.parentRowEl; - allowExpansionRow.push(parent); - row = parent; - } - for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { - if (allowExpansionRow[index]?.hasAttribute('scene')) { - if (allowExpansionRow[index]!.expansion) { - allowExpansionRow[index].updateChildRowStatus(); - } else { - allowExpansionRow[index].expansion = true; - } + itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; + } else if (itln[1].rowEL === currentRow) { + if (itln[1].rowEL.collect) { + itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; + } else { + itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; } + itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; + } + }); + // 收藏夹元素拖动排序功能 + sp.currentClickRow = null; + currentRow.setAttribute('draggable', 'true'); + currentRow.addEventListener('dragstart', () => { + sp.currentClickRow = currentRow; + }); + currentRow.addEventListener('dragover', (ev: any) => { + ev.preventDefault(); + ev.dataTransfer.dropEffect = 'move'; + }); + currentRow.addEventListener('drop', collectHandlerDrop(sp, currentRow)); + currentRow.addEventListener('dragend', collectHandlerDragEnd(sp)); + }; +} +function collectHandlerNo(sp: SpSystemTrace, currentRow: any, event: any): void { + sp.favoriteChartListEL?.deleteRow(currentRow, event.detail.type !== 'auto-collect'); + if (event.detail.type !== 'auto-collect') { + let rowIndex = sp.collectRows.indexOf(currentRow); + if (rowIndex !== -1) { + sp.collectRows.splice(rowIndex, 1); } - allowExpansionRow.length = 0; - let replaceRow = sp.rowsEL!.querySelector( - `div[row-id='${currentRow.rowId}-${currentRow.rowType}']` - ); - // 取消收藏时,删除父亲ID - currentRow.name = currentRow.tampName; - if (replaceRow != null) { - sp.rowsEL!.replaceChild(currentRow, replaceRow); - currentRow.style.boxShadow = `0 10px 10px #00000000`; - } -} -function collectHandlerYes(sp: SpSystemTrace, currentRow: any, event: any) { - if ( - !sp.collectRows.find((find) => { - return find === currentRow; - }) - ) { - sp.collectRows.push(currentRow); - } - let replaceRow = document.createElement('div'); - replaceRow.setAttribute('row-id', currentRow.rowId + '-' + currentRow.rowType); - replaceRow.setAttribute('type', 'replaceRow'); - replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); - replaceRow.style.display = 'none'; - if (!currentRow.hasAttribute('scene')) { - currentRow.setAttribute('row-hidden', ''); - } else { - currentRow.removeAttribute('row-hidden'); - } - // 添加收藏时,在线程名前面追加父亲ID - let rowParentId = currentRow.rowParentId; - currentRow.tampName = currentRow.name; - if (rowParentId) { - let parentRows = sp.shadowRoot?.querySelectorAll>(`trace-row[row-id='${rowParentId}']`); - parentRows?.forEach((parentRow) => { - if ( - parentRow?.name && - parentRow?.name != currentRow.name && - !parentRow.rowType!.startsWith('cpu') && - !parentRow.rowType!.startsWith('thread') && - !parentRow.rowType!.startsWith('func') && - !currentRow.name.includes(parentRow.name) - ) { - currentRow.name += '(' + parentRow.name + ')'; - } - }); + } + let row = currentRow; + let allowExpansionRow = []; + while (row.hasParentRowEl) { + let parent = row.parentRowEl; + allowExpansionRow.push(parent); + row = parent; + } + for (let index: number = allowExpansionRow.length - 1; index >= 0; index--) { + if (allowExpansionRow[index]?.hasAttribute('scene')) { + if (allowExpansionRow[index]!.expansion) { + allowExpansionRow[index].updateChildRowStatus(); + } else { + allowExpansionRow[index].expansion = true; + } } - if (!currentRow.hasParentRowEl) { - sp.rowsEL!.replaceChild(replaceRow, currentRow); - } - sp.favoriteChartListEL?.insertRow(currentRow, sp.currentCollectGroup, event.detail.type !== 'auto-collect'); -} -function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null) { - return function (ev: any) { - if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) { - let rect = currentRow!.getBoundingClientRect(); - if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { - //向上移动 - sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!); - } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { - //向下移动 - sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!); - } - sp.refreshFavoriteCanvas(); - } - }; + } + allowExpansionRow.length = 0; + let replaceRow = sp.rowsEL!.querySelector( + `div[row-id='${currentRow.rowId}-${currentRow.rowType}']` + ); + // 取消收藏时,删除父亲ID + currentRow.name = currentRow.tampName; + if (replaceRow !== null) { + sp.rowsEL!.replaceChild(currentRow, replaceRow); + currentRow.style.boxShadow = '0 10px 10px #00000000'; + } } -function collectHandlerDragEnd(sp: SpSystemTrace) { - return function (ev: any) { - sp.linkNodes.forEach((itln) => { - if (itln[0].rowEL.collect) { - if (sp.timerShaftEL?._checkExpand) { - itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; - } else { - itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; - } - } else { - itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - if (itln[1].rowEL.collect) { - if (sp.timerShaftEL?._checkExpand) { - itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; - } else { - itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; - } - } else { - itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; - } - itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; - itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; - }); - sp.currentClickRow = null; - }; +function collectHandlerYes(sp: SpSystemTrace, currentRow: any, event: any): void { + if ( + !sp.collectRows.find((find) => { + return find === currentRow; + }) + ) { + sp.collectRows.push(currentRow); + } + let replaceRow = document.createElement('div'); + replaceRow.setAttribute('row-id', `${currentRow.rowId}-${currentRow.rowType}`); + replaceRow.setAttribute('type', 'replaceRow'); + replaceRow.setAttribute('row-parent-id', currentRow.rowParentId); + replaceRow.style.display = 'none'; + if (!currentRow.hasAttribute('scene')) { + currentRow.setAttribute('row-hidden', ''); + } else { + currentRow.removeAttribute('row-hidden'); + } + // 添加收藏时,在线程名前面追加父亲ID + let rowParentId = currentRow.rowParentId; + currentRow.tampName = currentRow.name; + if (rowParentId) { + let parentRows = sp.shadowRoot?.querySelectorAll>(`trace-row[row-id='${rowParentId}']`); + parentRows?.forEach((parentRow) => { + if ( + parentRow?.name && + parentRow?.name !== currentRow.name && + !parentRow.rowType!.startsWith('cpu') && + !parentRow.rowType!.startsWith('thread') && + !parentRow.rowType!.startsWith('func') && + !currentRow.name.includes(parentRow.name) + ) { + currentRow.name += `(${parentRow.name})`; + } + }); + } + if (!currentRow.hasParentRowEl) { + sp.rowsEL!.replaceChild(replaceRow, currentRow); + } + sp.favoriteChartListEL?.insertRow(currentRow, sp.currentCollectGroup, event.detail.type !== 'auto-collect'); } -function selectHandler(sp: SpSystemTrace) { - sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => { - rows.forEach((item) => { - sp.setAttribute('clickRow', item.rowType!); - sp.setAttribute('rowName', item.name); - sp.setAttribute('rowId', item.rowId!); - }); - if (rows.length == 0) { - const allRows = [ - ...sp.shadowRoot!.querySelectorAll>('trace-row'), - ...sp.favoriteChartListEL!.getAllCollectRows(), - ]; - for (const row of allRows) { - row.checkType = '-1'; - if (row.folder) { - row.childrenList.forEach((item) => { - row.checkType = '-1'; - }); - } - } - sp.refreshCanvas(true); - if (!SportRuler.isMouseInSportRuler) { - sp.traceSheetEL?.setMode('hidden'); - } - return; - } - let checkRows = rows; - if (!refreshCheckBox) { - checkRows = [ - ...sp.shadowRoot!.querySelectorAll>("trace-row[check-type='2']"), - ...sp.favoriteChartListEL!.getAllSelectCollectRows()] +function collectHandlerDrop(sp: SpSystemTrace, currentRow: HTMLDivElement | undefined | null): (ev: any) => void { + return function (ev: any) { + if (sp.favoriteChartListEL !== null && sp.currentClickRow !== null && sp.currentClickRow !== currentRow) { + let rect = currentRow!.getBoundingClientRect(); + if (ev.clientY >= rect.top && ev.clientY < rect.top + rect.height / 2) { + //向上移动 + sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!); + } else if (ev.clientY <= rect.bottom && ev.clientY > rect.top + rect.height / 2) { + //向下移动 + sp.favoriteChartListEL!.insertRowBefore(sp.currentClickRow!, currentRow!.nextSibling!); + } + sp.refreshFavoriteCanvas(); + } + }; +} +function collectHandlerDragEnd(sp: SpSystemTrace): (ev: any) => void { + return function (ev: any): void { + sp.linkNodes.forEach((itln) => { + if (itln[0].rowEL.collect) { + if (sp.timerShaftEL?._checkExpand) { + itln[0].rowEL.translateY = + itln[0].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; + } else { + itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; } - selectHandlerRefreshCheckBox(sp, checkRows, refreshCheckBox); - if (!sp.isSelectClick) { - sp.rangeTraceRow = []; + } else { + itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + if (itln[1].rowEL.collect) { + if (sp.timerShaftEL?._checkExpand) { + itln[1].rowEL.translateY = + itln[1].rowEL.getBoundingClientRect().top - 195 + sp.timerShaftEL._usageFoldHeight!; + } else { + itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; } - selectHandlerRows(sp, checkRows); - }; + } else { + itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY; + itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY; + }); + sp.currentClickRow = null; + }; } -function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array>, refreshCheckBox: boolean) { - if (refreshCheckBox) { - if (rows.length > 0) { - sp.queryAllTraceRow().forEach((row) => { - row.checkType = '0'; - if (row.folder) { - row.childrenList.forEach((ite) => ite.checkType = '0'); - } - }); - rows.forEach((it) => it.checkType = '2'); - } else { - sp.queryAllTraceRow().forEach((row) => { - row.checkType = '-1'; - if (row.folder) { - row.childrenList.forEach((it) => it.checkType = '-1'); - } - }); - return; +function selectHandler(sp: SpSystemTrace): void { + sp.rangeSelect.selectHandler = (rows, refreshCheckBox): void => { + rows.forEach((item) => { + sp.setAttribute('clickRow', item.rowType!); + sp.setAttribute('rowName', item.name); + sp.setAttribute('rowId', item.rowId!); + }); + if (rows.length === 0) { + const allRows = [ + ...sp.shadowRoot!.querySelectorAll>('trace-row'), + ...sp.favoriteChartListEL!.getAllCollectRows(), + ]; + for (const row of allRows) { + row.checkType = '-1'; + if (row.folder) { + row.childrenList.forEach((item) => { + row.checkType = '-1'; + }); } + } + sp.refreshCanvas(true); + if (!SportRuler.isMouseInSportRuler) { + sp.traceSheetEL?.setMode('hidden'); + } + return; + } + let checkRows = rows; + if (!refreshCheckBox) { + checkRows = [ + ...sp.shadowRoot!.querySelectorAll>("trace-row[check-type='2']"), + ...sp.favoriteChartListEL!.getAllSelectCollectRows(), + ]; } + selectHandlerRefreshCheckBox(sp, checkRows, refreshCheckBox); + if (!sp.isSelectClick) { + sp.rangeTraceRow = []; + } + selectHandlerRows(sp, checkRows); + }; } -function selectHandlerRows(sp: SpSystemTrace, rows: Array>) { - let selection = new SelectionParam(); - selection.cpuStateRowsId = sp.stateRowsId; - selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; - selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; - selection.recordStartNs = (window as any).recordStartNS; - rows.forEach((it) => { - selection.pushSelection(it, sp); - if (sp.rangeTraceRow!.length !== rows.length) { - let event = sp.createPointEvent(it); - SpStatisticsHttpUtil.addOrdinaryVisitAction({ - action: 'trace_row', - event: event, - }); +function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array>, refreshCheckBox: boolean): void { + if (refreshCheckBox) { + if (rows.length > 0) { + sp.queryAllTraceRow().forEach((row) => { + row.checkType = '0'; + if (row.folder) { + row.childrenList.forEach((ite) => (ite.checkType = '0')); } - }); - if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { - selection.promiseList.push( - queryEbpfSamplesCount( - TraceRow.rangeSelectObject?.startNS || 0, - TraceRow.rangeSelectObject?.endNS || 0, - selection.diskIOipids - ).then((res) => { - if (res.length > 0) { - selection.fsCount = res[0].fsCount; - selection.vmCount = res[0].vmCount; - } - return new Promise((resolve) => resolve(1)); - }) - ); - } - sp.rangeTraceRow = rows; - sp.isSelectClick = false; - sp.selectStructNull(); - sp.timerShaftEL?.removeTriangle('inverted'); - if (selection.promiseList.length > 0) { - Promise.all(selection.promiseList).then(() => { - selection.promiseList = []; - sp.traceSheetEL?.rangeSelect(selection); - }); + }); + rows.forEach((it) => (it.checkType = '2')); } else { - sp.traceSheetEL?.rangeSelect(selection); - } - sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 - sp.selectionParam = selection; -} -function resizeObserverHandler(sp: SpSystemTrace) { - // @ts-ignore - new ResizeObserver((entries) => { - TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth(); - requestAnimationFrame(() => { - sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth()); - sp.shadowRoot!.querySelectorAll>('trace-row').forEach((it) => { - it.updateWidth(sp.clientWidth); - }); - }); - }).observe(sp); - - new ResizeObserver((entries) => { - sp.canvasPanelConfig(); - if (sp.traceSheetEL!.getAttribute('mode') == 'hidden') { - sp.timerShaftEL?.removeTriangle('triangle'); + sp.queryAllTraceRow().forEach((row) => { + row.checkType = '-1'; + if (row.folder) { + row.childrenList.forEach((it) => (it.checkType = '-1')); } - if (sp.favoriteChartListEL?.style.display === 'flex') { - sp.refreshFavoriteCanvas(); - } - sp.refreshCanvas(true); - }).observe(sp.rowsPaneEL!); -} -function mutationObserverHandler(sp: SpSystemTrace) { - new MutationObserver((mutations, observer) => { - for (const mutation of mutations) { - if (mutation.type === 'attributes') { - if (sp.style.visibility === 'visible') { - if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) { - sp.timerShaftEL?.setSlicesMark( - TraceRow.rangeSelectObject.startNS || 0, - TraceRow.rangeSelectObject.endNS || 0, - false - ); - SpSystemTrace.sliceRangeMark = undefined; - window.publish(window.SmartEvent.UI.RefreshCanvas, {}); - } - } - } - } - }).observe(sp, { - attributes: true, - childList: false, - subtree: false, - }); + }); + return; + } + } } -function intersectionObserverHandler(sp: SpSystemTrace) { - sp.intersectionObserver = new IntersectionObserver( - (entries) => { - entries.forEach((it) => { - let tr = it.target as TraceRow; - tr.intersectionRatio = it.intersectionRatio; - if (!it.isIntersecting) { - tr.sleeping = true; - sp.invisibleRows.indexOf(tr) == -1 && sp.invisibleRows.push(tr); - sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping); - } else { - tr.sleeping = false; - sp.visibleRows.indexOf(tr) == -1 && sp.visibleRows.push(tr); - sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping); - } - sp.visibleRows - .filter((vr) => vr.expansion) - .forEach((vr) => { - vr.sticky = sp.visibleRows.some((vro) => { - vr.childrenList.filter((it) => !it.collect).indexOf(vro) >= 0; - }); - }); - sp.visibleRows - .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion && !vr.collect) - .forEach((vr) => (vr.parentRowEl!.sticky = true)); - if (sp.handler) { - clearTimeout(sp.handler); - } - sp.handler = setTimeout(() => sp.refreshCanvas(false), 100); - }); - }, - { threshold: [0, 0.01, 0.99, 1] } +function selectHandlerRows(sp: SpSystemTrace, rows: Array>): void { + let selection = new SelectionParam(); + selection.cpuStateRowsId = sp.stateRowsId; + selection.leftNs = TraceRow.rangeSelectObject?.startNS || 0; + selection.rightNs = TraceRow.rangeSelectObject?.endNS || 0; + selection.recordStartNs = (window as any).recordStartNS; + rows.forEach((it) => { + selection.pushSelection(it, sp); + if (sp.rangeTraceRow!.length !== rows.length) { + let event = sp.createPointEvent(it); + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + action: 'trace_row', + event: event, + }); + } + }); + if (selection.diskIOipids.length > 0 && !selection.diskIOLatency) { + selection.promiseList.push( + queryEbpfSamplesCount( + TraceRow.rangeSelectObject?.startNS || 0, + TraceRow.rangeSelectObject?.endNS || 0, + selection.diskIOipids + ).then((res) => { + if (res.length > 0) { + selection.fsCount = res[0].fsCount; + selection.vmCount = res[0].vmCount; + } + return new Promise((resolve) => resolve(1)); + }) ); + } + sp.rangeTraceRow = rows; + sp.isSelectClick = false; + sp.selectStructNull(); + sp.timerShaftEL?.removeTriangle('inverted'); + if (selection.promiseList.length > 0) { + Promise.all(selection.promiseList).then(() => { + selection.promiseList = []; + sp.traceSheetEL?.rangeSelect(selection); + }); + } else { + sp.traceSheetEL?.rangeSelect(selection); + } + sp.timerShaftEL!.selectionList.push(selection); // 保持选中对象,为后面的再次选中该框选区域做准备。 + sp.selectionParam = selection; } -function observerHandler(sp: SpSystemTrace) { - resizeObserverHandler(sp); - mutationObserverHandler(sp); - intersectionObserverHandler(sp); +function resizeObserverHandler(sp: SpSystemTrace): void { + // @ts-ignore + new ResizeObserver((entries) => { + TraceRow.FRAME_WIDTH = sp.clientWidth - 249 - sp.getScrollWidth(); + requestAnimationFrame(() => { + sp.timerShaftEL?.updateWidth(sp.clientWidth - 1 - sp.getScrollWidth()); + sp.shadowRoot!.querySelectorAll>('trace-row').forEach((it) => { + it.updateWidth(sp.clientWidth); + }); + }); + }).observe(sp); + + new ResizeObserver((entries) => { + sp.canvasPanelConfig(); + if (sp.traceSheetEL!.getAttribute('mode') === 'hidden') { + sp.timerShaftEL?.removeTriangle('triangle'); + } + if (sp.favoriteChartListEL?.style.display === 'flex') { + sp.refreshFavoriteCanvas(); + } + sp.refreshCanvas(true); + }).observe(sp.rowsPaneEL!); } -function windowKeyDownHandler(sp: SpSystemTrace) { - return function (ev: KeyboardEvent) { - if (ev.key.toLocaleLowerCase() === 'escape') { - sp.queryAllTraceRow().forEach((it) => { - it.checkType = '-1'; - }); - TraceRow.rangeSelectObject = undefined; - sp.rangeSelect.rangeTraceRow = []; - sp.selectStructNull(); - sp.timerShaftEL?.setSlicesMark(); - sp.traceSheetEL?.setMode('hidden'); - sp.removeLinkLinesByBusinessType('janks', 'task'); +function mutationObserverHandler(sp: SpSystemTrace): void { + new MutationObserver((mutations, observer) => { + for (const mutation of mutations) { + if (mutation.type === 'attributes') { + if (sp.style.visibility === 'visible') { + if (TraceRow.rangeSelectObject && SpSystemTrace.sliceRangeMark) { + sp.timerShaftEL?.setSlicesMark( + TraceRow.rangeSelectObject.startNS || 0, + TraceRow.rangeSelectObject.endNS || 0, + false + ); + SpSystemTrace.sliceRangeMark = undefined; + window.publish(window.SmartEvent.UI.RefreshCanvas, {}); + } } + } } + }).observe(sp, { + attributes: true, + childList: false, + subtree: false, + }); } -function smartEventSubscribe(sp: SpSystemTrace) { - window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data)); - window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => { }); - window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false)); - window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => { - sp.keyboardEnable = tr.enable; - if (!sp.keyboardEnable) { - sp.stopWASD(); - } - }); - window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => { - if (!collapse) { - // 一键折叠之前,记录当前打开的泳道图 - sp.expandRowList = - Array.from(sp.rowsEL!.querySelectorAll>(`trace-row[folder][expansion]`)) || []; - } - sp.collapseAll = true; - sp.setAttribute('disable', ''); - sp.expandRowList!.forEach((it) => (it.expansion = collapse)); - sp.collapseAll = false; - sp.removeAttribute('disable'); - sp.refreshCanvas(true); - }); - window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => { - sp.mouseEventEnable = tr.mouseEnable; - if (sp.mouseEventEnable) { - sp.removeAttribute('disable'); +function intersectionObserverHandler(sp: SpSystemTrace): void { + sp.intersectionObserver = new IntersectionObserver( + (entries) => { + entries.forEach((it) => { + let tr = it.target as TraceRow; + tr.intersectionRatio = it.intersectionRatio; + if (!it.isIntersecting) { + tr.sleeping = true; + sp.invisibleRows.indexOf(tr) === -1 && sp.invisibleRows.push(tr); + sp.visibleRows = sp.visibleRows.filter((it) => !it.sleeping); } else { - sp.setAttribute('disable', ''); + tr.sleeping = false; + sp.visibleRows.indexOf(tr) === -1 && sp.visibleRows.push(tr); + sp.invisibleRows = sp.invisibleRows.filter((it) => it.sleeping); } - }); - window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => sp.currentCollectGroup = group); + sp.visibleRows + .filter((vr) => vr.expansion) + .forEach((vr) => { + vr.sticky = sp.visibleRows.some((vro) => { + vr.childrenList.filter((it) => !it.collect).indexOf(vro) >= 0; + }); + }); + sp.visibleRows + .filter((vr) => !vr.folder && vr.parentRowEl && vr.parentRowEl.expansion && !vr.collect) + .forEach((vr) => (vr.parentRowEl!.sticky = true)); + if (sp.handler) { + clearTimeout(sp.handler); + } + sp.handler = setTimeout(() => sp.refreshCanvas(false), 100); + }); + }, + { threshold: [0, 0.01, 0.99, 1] } + ); +} +function observerHandler(sp: SpSystemTrace): void { + resizeObserverHandler(sp); + mutationObserverHandler(sp); + intersectionObserverHandler(sp); +} +function windowKeyDownHandler(sp: SpSystemTrace): (ev: KeyboardEvent) => void { + return function (ev: KeyboardEvent) { + if (ev.key.toLocaleLowerCase() === 'escape') { + sp.queryAllTraceRow().forEach((it) => { + it.checkType = '-1'; + }); + TraceRow.rangeSelectObject = undefined; + sp.rangeSelect.rangeTraceRow = []; + sp.selectStructNull(); + sp.timerShaftEL?.setSlicesMark(); + sp.traceSheetEL?.setMode('hidden'); + sp.removeLinkLinesByBusinessType('janks', 'task'); + } + }; +} +function smartEventSubscribe(sp: SpSystemTrace): void { + window.subscribe(window.SmartEvent.UI.SliceMark, (data) => sp.sliceMarkEventHandler(data)); + window.subscribe(window.SmartEvent.UI.TraceRowComplete, (tr) => {}); + window.subscribe(window.SmartEvent.UI.RefreshCanvas, () => sp.refreshCanvas(false)); + window.subscribe(window.SmartEvent.UI.KeyboardEnable, (tr) => { + sp.keyboardEnable = tr.enable; + if (!sp.keyboardEnable) { + sp.stopWASD(); + } + }); + window.subscribe(window.SmartEvent.UI.CollapseAllLane, (collapse: boolean) => { + if (!collapse) { + // 一键折叠之前,记录当前打开的泳道图 + sp.expandRowList = Array.from(sp.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; + } + sp.collapseAll = true; + sp.setAttribute('disable', ''); + sp.expandRowList!.forEach((it) => (it.expansion = collapse)); + sp.collapseAll = false; + sp.removeAttribute('disable'); + sp.refreshCanvas(true); + }); + window.subscribe(window.SmartEvent.UI.MouseEventEnable, (tr) => { + sp.mouseEventEnable = tr.mouseEnable; + if (sp.mouseEventEnable) { + sp.removeAttribute('disable'); + } else { + sp.setAttribute('disable', ''); + } + }); + window.subscribe(window.SmartEvent.UI.CollectGroupChange, (group: string) => (sp.currentCollectGroup = group)); } export function documentInitEvent(sp: SpSystemTrace): void { - if (!document) { - return - } - document.addEventListener('triangle-flag', triangleFlagHandler(sp)); - document.addEventListener('number_calibration', numberCalibrationHandler(sp)); - document.addEventListener('flag-change', flagChangeHandler(sp)); - document.addEventListener('slices-change', slicesChangeHandler(sp)); - if (sp.timerShaftEL?.collecBtn) { - sp.timerShaftEL.collecBtn.onclick = () => { - if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) { - sp.timerShaftEL!.collecBtn!.removeAttribute('close'); - sp.favoriteChartListEL?.showCollectArea(); - } else { - sp.timerShaftEL!.collecBtn!.setAttribute('close', ''); - sp.favoriteChartListEL?.hideCollectArea(); - } - }; - } - document.addEventListener('collect', collectHandler(sp)); + if (!document) { + return; + } + document.addEventListener('triangle-flag', triangleFlagHandler(sp)); + document.addEventListener('number_calibration', numberCalibrationHandler(sp)); + document.addEventListener('flag-change', flagChangeHandler(sp)); + document.addEventListener('slices-change', slicesChangeHandler(sp)); + if (sp.timerShaftEL?.collecBtn) { + sp.timerShaftEL.collecBtn.onclick = (): void => { + if (sp.timerShaftEL!.collecBtn!.hasAttribute('close')) { + sp.timerShaftEL!.collecBtn!.removeAttribute('close'); + sp.favoriteChartListEL?.showCollectArea(); + } else { + sp.timerShaftEL!.collecBtn!.setAttribute('close', ''); + sp.favoriteChartListEL?.hideCollectArea(); + } + }; + } + document.addEventListener('collect', collectHandler(sp)); } -export function spSystemTraceInitElement(sp: SpSystemTrace) { - window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines()); - sp.traceSheetEL = sp.shadowRoot?.querySelector('.trace-sheet'); - if (!sp || !sp.shadowRoot || !sp.traceSheetEL) { - return; - } - let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot - ?.querySelector('#current-selection > tabpane-current-selection') - ?.shadowRoot?.querySelector('#rightButton'); - let rightStar: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot - ?.querySelector('#current-selection > tabpane-current-selection') - ?.shadowRoot?.querySelector('#right-star'); - sp.tipEL = sp.shadowRoot.querySelector('.tip'); - sp.rowsPaneEL = sp.shadowRoot.querySelector('.rows-pane'); - sp.rowsEL = sp.rowsPaneEL; - sp.spacerEL = sp.shadowRoot.querySelector('.spacer'); - sp.timerShaftEL = sp.shadowRoot.querySelector('.timer-shaft'); - sp.favoriteChartListEL = sp.shadowRoot.querySelector('#favorite-chart-list'); - if (!sp.traceSheetEL.shadowRoot) { - return; - } - sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector('tabpane-frequency-sample'); - sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector('tabpane-counter-sample'); - sp.rangeSelect = new RangeSelect(sp); - rightButton?.addEventListener('click', rightButtonOnClick(sp, rightStar)); - rightStar?.addEventListener('click', rightStarOnClick(sp)); - documentInitEvent(sp); - SpSystemTrace.scrollViewWidth = sp.getScrollWidth(); - selectHandler(sp); - observerHandler(sp); - window.addEventListener('keydown', windowKeyDownHandler(sp)); - sp.chartManager = new SpChartManager(sp); - sp.canvasPanel = sp.shadowRoot.querySelector('#canvas-panel')!; - sp.canvasPanelCtx = sp.canvasPanel.getContext('2d'); - sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context(); - sp.canvasPanelConfig(); - smartEventSubscribe(sp); +export function spSystemTraceInitElement(sp: SpSystemTrace): void { + window.subscribe(window.SmartEvent.UI.LoadFinishFrame, () => sp.drawAllLines()); + sp.traceSheetEL = sp.shadowRoot?.querySelector('.trace-sheet'); + if (!sp || !sp.shadowRoot || !sp.traceSheetEL) { + return; + } + let rightButton: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot + ?.querySelector('#current-selection > tabpane-current-selection') + ?.shadowRoot?.querySelector('#rightButton'); + let rightStar: HTMLElement | null | undefined = sp.traceSheetEL.shadowRoot + ?.querySelector('#current-selection > tabpane-current-selection') + ?.shadowRoot?.querySelector('#right-star'); + sp.tipEL = sp.shadowRoot.querySelector('.tip'); + sp.rowsPaneEL = sp.shadowRoot.querySelector('.rows-pane'); + sp.rowsEL = sp.rowsPaneEL; + sp.spacerEL = sp.shadowRoot.querySelector('.spacer'); + sp.timerShaftEL = sp.shadowRoot.querySelector('.timer-shaft'); + sp.favoriteChartListEL = sp.shadowRoot.querySelector('#favorite-chart-list'); + if (!sp.traceSheetEL.shadowRoot) { + return; + } + sp.tabCpuFreq = sp.traceSheetEL.shadowRoot.querySelector('tabpane-frequency-sample'); + sp.tabCpuState = sp.traceSheetEL.shadowRoot.querySelector('tabpane-counter-sample'); + sp.rangeSelect = new RangeSelect(sp); + rightButton?.addEventListener('click', rightButtonOnClick(sp, rightStar)); + rightStar?.addEventListener('click', rightStarOnClick(sp)); + documentInitEvent(sp); + SpSystemTrace.scrollViewWidth = sp.getScrollWidth(); + selectHandler(sp); + observerHandler(sp); + window.addEventListener('keydown', windowKeyDownHandler(sp)); + sp.chartManager = new SpChartManager(sp); + sp.canvasPanel = sp.shadowRoot.querySelector('#canvas-panel')!; + sp.canvasPanelCtx = sp.canvasPanel.getContext('2d'); + sp.canvasFavoritePanelCtx = sp.favoriteChartListEL!.context(); + sp.canvasPanelConfig(); + smartEventSubscribe(sp); } -function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: any) { - if (findEntry.startTime > TraceRow.range!.endNS || (findEntry.startTime + findEntry.dur) < TraceRow.range!.startNS) { - sp.moveRangeToLeft(findEntry.startTime!, findEntry.dur!); +function moveRangeToCenterAndHighlight(sp: SpSystemTrace, findEntry: any): void { + if (findEntry) { + if (findEntry.startTime > TraceRow.range!.endNS || findEntry.startTime + findEntry.dur < TraceRow.range!.startNS) { + sp.moveRangeToLeft(findEntry.startTime!, findEntry.dur!); } sp.queryAllTraceRow().forEach((item) => { - item.highlight = false; + item.highlight = false; }); - if (findEntry.type == 'cpu') { - findEntryTypeCpu(sp, findEntry); - } else if (findEntry.type == 'func') { - findEntryTypeFunc(sp, findEntry); - } else if (findEntry.type == 'thread||process') { - findEntryTypeThreadProcess(sp, findEntry); - } else if (findEntry.type == 'sdk') { - findEntryTypeSdk(sp, findEntry); + if (findEntry.type === 'cpu') { + findEntryTypeCpu(sp, findEntry); + } else if (findEntry.type === 'func') { + findEntryTypeFunc(sp, findEntry); + } else if (findEntry.type === 'thread||process') { + findEntryTypeThreadProcess(sp, findEntry); + } else if (findEntry.type === 'sdk') { + findEntryTypeSdk(sp, findEntry); } sp.timerShaftEL?.drawTriangle(findEntry.startTime || 0, 'inverted'); + } } -export function spSystemTraceShowStruct(sp: SpSystemTrace, previous: boolean, currentIndex: number, structs: Array, retargetIndex?: number) { - if (structs.length == 0) { - return 0; - } - let findIndex = spSystemTraceShowStructFindIndex(sp, previous, currentIndex, structs, retargetIndex); - let findEntry: any; +export function spSystemTraceShowStruct( + sp: SpSystemTrace, + previous: boolean, + currentIndex: number, + structs: Array, + retargetIndex?: number +): number { + if (structs.length === 0) { + return 0; + } + let findIndex = spSystemTraceShowStructFindIndex(previous, currentIndex, structs, retargetIndex); + let findEntry: any; + if (findIndex >= 0) { findEntry = structs[findIndex]; - moveRangeToCenterAndHighlight(sp, findEntry); - return findIndex; -} -function spSystemTraceShowStructFindIndex(sp: SpSystemTrace, previous: boolean, currentIndex: number, structs: Array, retargetIndex: number | undefined) { - if (TraceRow.range!.startNS > SpSystemTrace.currentStartTime && !retargetIndex) { - SpSystemTrace.currentStartTime = TraceRow.range!.startNS; - } - let findIndex = -1; + } else { if (previous) { - if (retargetIndex) { - findIndex = retargetIndex - 1; - } else { - for (let i = structs.length - 1; i >= 0; i--) { - let it = structs[i]; - if ( - i < currentIndex && - it.startTime! >= TraceRow.range!.startNS && - it.startTime! + it.dur! <= TraceRow.range!.endNS - ) { - findIndex = i; - break; - } - if (it.startTime! + it.dur! <= TraceRow.range!.startNS) { - findIndex = i; - break; - } - } - if (findIndex == -1) { - findIndex = structs.length - 1; - } + for (let i = structs.length - 1; i >= 0; i--) { + let it = structs[i]; + if (it.startTime! + it.dur! < TraceRow.range!.startNS) { + findIndex = i; + break; } + } + if (findIndex === -1) { + findIndex = structs.length - 1; + } } else { - //左滑 - if (SpSystemTrace.currentStartTime > TraceRow.range!.startNS) { - SpSystemTrace.currentStartTime = TraceRow.range!.startNS; - if (structs[currentIndex].startTime < TraceRow.range!.startNS || structs[currentIndex].startTime! + structs[currentIndex].dur! > TraceRow.range!.endNS) { - currentIndex = -1; - } - } - findIndex = structs.findIndex((it, idx) => { - if (idx > currentIndex && - it.startTime! >= TraceRow.range!.startNS && - it.startTime! + it.dur! <= TraceRow.range!.endNS - ) { - return true; - } - if (it.startTime! >= TraceRow.range!.endNS) { - return true - } - }); - if (findIndex == -1) { - findIndex = 0; - } - + findIndex = structs.findIndex((it) => it.startTime! > TraceRow.range!.endNS); + if (findIndex === -1) { + findIndex = 0; + } } - return findIndex; + findEntry = structs[findIndex]; + } + moveRangeToCenterAndHighlight(sp, findEntry); + return findIndex; } -function findEntryTypeCpu(sp: SpSystemTrace, findEntry: any) { - CpuStruct.selectCpuStruct = findEntry; - CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; - sp.queryAllTraceRow(`trace-row[row-type='cpu-data']`, (row) => row.rowType === 'cpu-data').forEach((item) => { - if (item.rowId === `${findEntry.cpu}`) { - sp.rechargeCpuData( - findEntry, - item.dataListCache.find((it) => it.startTime > findEntry.startTime) - ); - item.fixedList = [findEntry]; +function spSystemTraceShowStructFindIndex( + previous: boolean, + currentIndex: number, + structs: Array, + retargetIndex: number | undefined +): number { + const rangeStart = TraceRow.range!.startNS; + const rangeEnd = TraceRow.range!.endNS; + if (rangeStart > SpSystemTrace.currentStartTime && !retargetIndex) { + SpSystemTrace.currentStartTime = rangeStart; + } + let findIndex = -1; + if (previous) { + if (retargetIndex) { + findIndex = retargetIndex - 1; + SpSystemTrace.retargetIndex = findIndex; + } else { + for (let i = structs.length - 1; i >= 0; i--) { + let it = structs[i]; + if (i < currentIndex && it.startTime! >= rangeStart && it.startTime! + it.dur! <= rangeEnd) { + findIndex = i; + break; } - item.highlight = item.rowId == `${findEntry.cpu}`; - item.draw(true); - }); - sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); - sp.onClickHandler(TraceRow.ROW_TYPE_CPU); -} -function findEntryTypeFunc(sp: SpSystemTrace, findEntry: any) { - sp.observerScrollHeightEnable = true; - sp.scrollToActFunc( - { - startTs: findEntry.startTime, - dur: findEntry.dur, - tid: findEntry.tid, - pid: findEntry.pid, - depth: findEntry.depth, - argsetid: findEntry.argsetid, - funName: findEntry.funName, - cookie: findEntry.cookie, - }, - true - ); -} -function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: any) { - let threadProcessRow = sp.rowsEL?.querySelectorAll>('trace-row')[0]; - if (threadProcessRow) { - let filterRow = threadProcessRow.childrenList.filter( - (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType - )[0]; - filterRow!.highlight = true; - sp.closeAllExpandRows(findEntry.rowParentId); - sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); - let completeEntry = () => { - sp.hoverStructNull(); - sp.selectStructNull(); - sp.wakeupListNull(); - sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); - }; - if (filterRow!.isComplete) { - completeEntry(); - } else { - filterRow!.onComplete = completeEntry; + } + } + } else { + if (currentIndex > 0) { + if (SpSystemTrace.currentStartTime > rangeStart) { + SpSystemTrace.currentStartTime = rangeStart; + if ( + structs[currentIndex].startTime < rangeStart || + structs[currentIndex].startTime! + structs[currentIndex].dur! > rangeEnd + ) { + currentIndex = -1; } + } + if (SpSystemTrace.currentStartTime !== 0 && SpSystemTrace.currentStartTime < rangeStart) { + SpSystemTrace.currentStartTime = 0; + SpSystemTrace.retargetIndex = 0; + } } + findIndex = structs.findIndex((it, idx) => { + return idx > currentIndex && it.startTime! >= rangeStart && it.startTime! + it.dur! <= rangeEnd; + }); + } + return findIndex; } -function findEntryTypeSdk(sp: SpSystemTrace, findEntry: any) { - let parentRow = sp.shadowRoot!.querySelector>(`trace-row[row-type='sdk'][folder]`); - if (parentRow) { - let sdkRow = parentRow.childrenList.filter( - (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType - )[0]; - sdkRow!.highlight = true; +function findEntryTypeCpu(sp: SpSystemTrace, findEntry: any): void { + CpuStruct.selectCpuStruct = findEntry; + CpuStruct.hoverCpuStruct = CpuStruct.selectCpuStruct; + sp.queryAllTraceRow("trace-row[row-type='cpu-data']", (row) => row.rowType === 'cpu-data').forEach((item) => { + if (item.rowId === `${findEntry.cpu}`) { + sp.rechargeCpuData( + findEntry, + item.dataListCache.find((it) => it.startTime > findEntry.startTime) + ); + item.fixedList = [findEntry]; } - sp.hoverStructNull(); - sp.selectStructNull(); - sp.wakeupListNull(); - sp.onClickHandler(findEntry.rowType!); + item.highlight = item.rowId === `${findEntry.cpu}`; + item.draw(true); + }); + sp.scrollToProcess(`${findEntry.cpu}`, '', 'cpu-data', true); + sp.onClickHandler(TraceRow.ROW_TYPE_CPU); +} +function findEntryTypeFunc(sp: SpSystemTrace, findEntry: any): void { + sp.observerScrollHeightEnable = true; + sp.scrollToActFunc( + { + startTs: findEntry.startTime, + dur: findEntry.dur, + tid: findEntry.tid, + pid: findEntry.pid, + depth: findEntry.depth, + argsetid: findEntry.argsetid, + funName: findEntry.funName, + cookie: findEntry.cookie, + }, + true + ); +} +function findEntryTypeThreadProcess(sp: SpSystemTrace, findEntry: any): void { + let threadProcessRow = sp.rowsEL?.querySelectorAll>('trace-row')[0]; + if (threadProcessRow) { + let filterRow = threadProcessRow.childrenList.filter( + (row) => row.rowId === findEntry.rowId && row.rowId === findEntry.rowType + )[0]; + filterRow!.highlight = true; sp.closeAllExpandRows(findEntry.rowParentId); sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); -} -async function spSystemTraceInitBuffer(sp: SpSystemTrace, param: { buf?: ArrayBuffer; Url?: string }, wasmConfigUri: string, progress: Function) { - if (param.buf) { - let configJson = ''; - try { - configJson = await fetch(wasmConfigUri).then((res) => res.text()); - } catch (e) { - error('getWasmConfigFailed', e); - } - let parseConfig = FlagsConfig.getSpTraceStreamParseConfig(); - let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress); - if (!status) { - return { status: false, msg: msg }; - } - SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap == undefined ? undefined : sdkConfigMap; - return null + let completeEntry = (): void => { + sp.hoverStructNull(); + sp.selectStructNull(); + sp.wakeupListNull(); + sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); + }; + if (filterRow!.isComplete) { + completeEntry(); } else { - return null; + filterRow!.onComplete = completeEntry; } + } } -async function spSystemTraceInitUrl(sp: SpSystemTrace, param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) { - if (param.url) { - let { status, msg } = await threadPool.initServer(param.url, progress); - if (!status) { - return { status: false, msg: msg }; - } else { - return null; - } +function findEntryTypeSdk(sp: SpSystemTrace, findEntry: any): void { + let parentRow = sp.shadowRoot!.querySelector>("trace-row[row-type='sdk'][folder]"); + if (parentRow) { + let sdkRow = parentRow.childrenList.filter( + (child) => child.rowId === findEntry.rowId && child.rowType === findEntry.rowType + )[0]; + sdkRow!.highlight = true; + } + sp.hoverStructNull(); + sp.selectStructNull(); + sp.wakeupListNull(); + sp.onClickHandler(findEntry.rowType!); + sp.closeAllExpandRows(findEntry.rowParentId); + sp.scrollToProcess(`${findEntry.rowId}`, `${findEntry.rowParentId}`, findEntry.rowType, true); +} +async function spSystemTraceInitBuffer( + sp: SpSystemTrace, + param: { buf?: ArrayBuffer; Url?: string }, + wasmConfigUri: string, + progress: Function +): Promise<{ + status: boolean; + msg: string; +} | null> { + if (param.buf) { + let configJson = ''; + try { + configJson = await fetch(wasmConfigUri).then((res) => res.text()); + } catch (e) { + error('getWasmConfigFailed', e); + } + let parseConfig = FlagsConfig.getSpTraceStreamParseConfig(); + let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress); + if (!status) { + return { status: false, msg: msg }; + } + SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap === undefined ? undefined : sdkConfigMap; + return null; + } else { + return null; + } +} +async function spSystemTraceInitUrl( + sp: SpSystemTrace, + param: { buf?: ArrayBuffer; url?: string }, + wasmConfigUri: string, + progress: Function +): Promise<{ + status: boolean; + msg: string; +} | null> { + if (param.url) { + let { status, msg } = await threadPool.initServer(param.url, progress); + if (!status) { + return { status: false, msg: msg }; } else { - return null; + return null; } + } else { + return null; + } } -export async function spSystemTraceInit(sp: SpSystemTrace, param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) { - progress('Load database', 6); - sp.rowsPaneEL!.scroll({ top: 0, left: 0 }); - let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress); - if (rsBuf) { - return rsBuf; +export async function spSystemTraceInit( + sp: SpSystemTrace, + param: { buf?: ArrayBuffer; url?: string }, + wasmConfigUri: string, + progress: Function +): Promise { + progress('Load database', 6); + sp.rowsPaneEL!.scroll({ top: 0, left: 0 }); + let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress); + if (rsBuf) { + return rsBuf; + } + let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, progress); + if (rsUrl) { + return rsUrl; + } + await sp.chartManager?.init(progress); + let rowId: string = ''; + sp.rowsEL?.querySelectorAll>('trace-row').forEach((it) => { + if (it.name.includes('Ark Ts')) { + rowId = it.rowId!; } - let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, progress); - if (rsUrl) { - return rsUrl; + if (it.folder) { + it.addEventListener('expansion-change', sp.extracted(it)); } - await sp.chartManager?.init(progress); - let rowId: string = ''; - sp.rowsEL?.querySelectorAll>('trace-row').forEach((it) => { - if (it.name.includes('Ark Ts')) { - rowId = it.rowId!; - } - if (it.folder) it.addEventListener('expansion-change', sp.extracted(it)); - }); - progress('completed', 100); - info('All TraceRow Data initialized'); - sp.loadTraceCompleted = true; - sp.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { - if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) { - it.addTemplateTypes('Ark Ts'); - for (let child of it.childrenList) { - child.addTemplateTypes('Ark Ts'); - } - } - if (it.folder) { - let offsetYTimeOut: any = undefined; - it.addEventListener('expansion-change', expansionChangeHandler(sp, offsetYTimeOut)); - } - if (sp.loadTraceCompleted) { - sp.traceSheetEL?.displaySystemLogsData(); - sp.traceSheetEL?.displaySystemStatesData(); - } - sp.intersectionObserver?.observe(it); - }); - return { status: true, msg: 'success' }; -} -function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: any) { - return function (event: any) { - let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce( - (pre, cur) => pre + cur.clientHeight!, 0); - let offset = sp.rowsPaneEL!.scrollHeight - max; - sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset; - JankStruct.delJankLineFlag = false; - if (offsetYTimeOut) { - clearTimeout(offsetYTimeOut); - } - if (event.detail.expansion) { - offsetYTimeOut = setTimeout(() => { - sp.linkNodes.forEach((linkNode) => { - JankStruct.selectJankStructList?.forEach((selectStruct: any) => { - if (event.detail.rowId == selectStruct.pid) { - JankStruct.selectJankStruct = selectStruct; - JankStruct.hoverJankStruct = selectStruct; - } - }); - linkNodeHandler(linkNode, sp); - }); - }, 300); - } else { - if (JankStruct!.selectJankStruct) { - JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); - } - offsetYTimeOut = setTimeout(() => { - sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp)); - }, 300); - } - let refreshTimeOut = setTimeout(() => { - sp.refreshCanvas(true); - clearTimeout(refreshTimeOut); - }, 360); + }); + progress('completed', 100); + info('All TraceRow Data initialized'); + sp.loadTraceCompleted = true; + sp.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { + if (rowId !== '' && (it.rowId?.includes(rowId) || it.name.includes(rowId))) { + it.addTemplateTypes('Ark Ts'); + for (let child of it.childrenList) { + child.addTemplateTypes('Ark Ts'); + } + } + if (it.folder) { + let offsetYTimeOut: any = undefined; + it.addEventListener('expansion-change', expansionChangeHandler(sp, offsetYTimeOut)); + } + if (sp.loadTraceCompleted) { + sp.traceSheetEL?.displaySystemLogsData(); + sp.traceSheetEL?.displaySystemStatesData(); } + sp.intersectionObserver?.observe(it); + }); + return { status: true, msg: 'success' }; } -function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace) { - if (linkNode[0].rowEL.collect) { - linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; +function expansionChangeHandler(sp: SpSystemTrace, offsetYTimeOut: any): (event: any) => void { + return function (event: any) { + let max = [...sp.rowsPaneEL!.querySelectorAll('trace-row')].reduce((pre, cur) => pre + cur.clientHeight!, 0); + let offset = sp.rowsPaneEL!.scrollHeight - max; + sp.rowsPaneEL!.scrollTop = sp.rowsPaneEL!.scrollTop - offset; + JankStruct.delJankLineFlag = false; + if (offsetYTimeOut) { + clearTimeout(offsetYTimeOut); } - linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; - if (linkNode[1].rowEL.collect) { - linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; + if (event.detail.expansion) { + offsetYTimeOut = setTimeout(() => { + sp.linkNodes.forEach((linkNode) => { + JankStruct.selectJankStructList?.forEach((selectStruct: any) => { + if (event.detail.rowId === selectStruct.pid) { + JankStruct.selectJankStruct = selectStruct; + JankStruct.hoverJankStruct = selectStruct; + } + }); + linkNodeHandler(linkNode, sp); + }); + }, 300); } else { - linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + if (JankStruct!.selectJankStruct) { + JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); + } + offsetYTimeOut = setTimeout(() => { + sp.linkNodes?.forEach((linkNode) => linkNodeHandler(linkNode, sp)); + }, 300); } - linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; + let refreshTimeOut = setTimeout(() => { + sp.refreshCanvas(true); + clearTimeout(refreshTimeOut); + }, 360); + }; +} +function linkNodeHandler(linkNode: PairPoint[], sp: SpSystemTrace): void { + if (linkNode[0].rowEL.collect) { + linkNode[0].rowEL.translateY = linkNode[0].rowEL.getBoundingClientRect().top - 195; + } else { + linkNode[0].rowEL.translateY = linkNode[0].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + linkNode[0].y = linkNode[0].rowEL!.translateY! + linkNode[0].offsetY; + if (linkNode[1].rowEL.collect) { + linkNode[1].rowEL.translateY = linkNode[1].rowEL.getBoundingClientRect().top - 195; + } else { + linkNode[1].rowEL.translateY = linkNode[1].rowEL.offsetTop - sp.rowsPaneEL!.scrollTop; + } + linkNode[1].y = linkNode[1].rowEL!.translateY! + linkNode[1].offsetY; } - const eventMap = { - 'cpu-data': 'Cpu', - 'cpu-state': 'Cpu State', - 'cpu-freq': 'Cpu Frequency', - 'cpu-limit-freq': 'Cpu Freq Limit', - 'process': 'Process', - 'native-memory': 'Native Memory', - 'thread': 'Thread', - 'func': 'Func', - 'mem': 'Memory', - 'virtual-memory-cell': 'Virtual Memory', - 'virtual-memory-group': 'Virtual Memory', - 'fps': 'FPS', - 'ability-monitor': 'Ability Monitor', - 'cpu-ability': 'Cpu Ability', - 'memory-ability': 'Memory Ability', - 'disk-ability': 'DiskIO Ability', - 'network-ability': 'Network Ability', - 'sdk': 'Sdk', - 'sdk-counter': 'SDK Counter', - 'sdk-slice': 'Sdk Slice', - 'energy': 'Energy', - 'power-energy': 'Power Event', - 'system-energy': 'System Event', - 'anomaly-energy': 'Anomaly Event', - 'clock-group': 'Clocks', - 'clock': 'clock', - 'irq-group': 'Irqs', - 'irq': 'irq', - 'hiperf': 'HiPerf (All)', - 'hiperf-event': 'HiPerf Event', - 'hiperf-report': 'HiPerf Report', - 'hiperf-process': 'HiPerf Process', - 'hiperf-thread': 'HiPerf Thread', - 'js-memory': 'Js Memory', -} -export function spSystemTraceInitPointToEvent(sp: SpSystemTrace) { - sp.eventMap = eventMap; + 'cpu-data': 'Cpu', + 'cpu-state': 'Cpu State', + 'cpu-freq': 'Cpu Frequency', + 'cpu-limit-freq': 'Cpu Freq Limit', + process: 'Process', + 'native-memory': 'Native Memory', + thread: 'Thread', + func: 'Func', + mem: 'Memory', + 'virtual-memory-cell': 'Virtual Memory', + 'virtual-memory-group': 'Virtual Memory', + fps: 'FPS', + 'ability-monitor': 'Ability Monitor', + 'cpu-ability': 'Cpu Ability', + 'memory-ability': 'Memory Ability', + 'disk-ability': 'DiskIO Ability', + 'network-ability': 'Network Ability', + sdk: 'Sdk', + 'sdk-counter': 'SDK Counter', + 'sdk-slice': 'Sdk Slice', + energy: 'Energy', + 'power-energy': 'Power Event', + 'system-energy': 'System Event', + 'anomaly-energy': 'Anomaly Event', + 'clock-group': 'Clocks', + clock: 'clock', + 'irq-group': 'Irqs', + irq: 'irq', + hiperf: 'HiPerf (All)', + 'hiperf-event': 'HiPerf Event', + 'hiperf-report': 'HiPerf Report', + 'hiperf-process': 'HiPerf Process', + 'hiperf-thread': 'HiPerf Thread', + 'js-memory': 'Js Memory', +}; +export function spSystemTraceInitPointToEvent(sp: SpSystemTrace): void { + sp.eventMap = eventMap; } diff --git a/ide/src/trace/component/SpSystemTrace.line.ts b/ide/src/trace/component/SpSystemTrace.line.ts index d369a628bfc367b7253d64c69b22c41ab64fd611..c8b3e075e7392c9eeae536410f7fe9c0eaed5c86 100644 --- a/ide/src/trace/component/SpSystemTrace.line.ts +++ b/ide/src/trace/component/SpSystemTrace.line.ts @@ -69,11 +69,11 @@ function selectJankApp( // startRow为子泳道,子泳道不存在,使用父泳道 if (startRow) { startParentRow = sp.shadowRoot?.querySelector>( - `trace-row[row-id='${startRow.rowParentId}'][folder]` + `trace-row[row-type='process'][row-id='${startRow.rowParentId}'][folder]` ); } else { startRow = sp.shadowRoot?.querySelector>( - `trace-row[row-id='${selectJankStruct?.pid}'][folder]` + `trace-row[row-type='process'][row-id='${selectJankStruct?.pid}'][folder]` ); } let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); @@ -126,7 +126,7 @@ function findJankApp( expansionFlag = collectionHasJank(startRow, collectList); let startOffsetY = 20 * (selectJankStruct!.depth! + 0.5); let startParentRow = sp.shadowRoot?.querySelector>( - `trace-row[row-id='${startRow.rowParentId}'][folder]` + `trace-row[row-type='process'][row-id='${startRow.rowParentId}'][folder]` ); if (startParentRow && !startParentRow.expansion && expansionFlag) { startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5); @@ -161,9 +161,9 @@ function addPointLink( if (data.children.length >= 1) { let endP; if (data.children[0].frame_type == 'frameTime') { - endP = sp.shadowRoot?.querySelector>("trace-row[row-id='frameTime']"); + endP = sp.shadowRoot?.querySelector>("trace-row[row-type='janks'][row-id='frameTime']"); } else { - endP = sp.shadowRoot?.querySelector>(`trace-row[row-id='${data.children[0].pid}'][folder]`); + endP = sp.shadowRoot?.querySelector>(`trace-row[row-type='process'][row-id='${data.children[0].pid}'][folder]`); } sp.drawJankLine(endP, findJankEntry, data.children[0]); } @@ -189,9 +189,12 @@ function drawJankLineEndParent( sp: SpSystemTrace, data: any, startRow: any, - selectJankStruct: JankStruct + selectJankStruct: JankStruct, + isBinderClick: boolean = false ): void { - endParentRow.expansion = true; + if (isBinderClick) { + endParentRow.expansion = true; + } //终点的父泳道过滤出选中的Struct let endRowStruct = getEndStruct(data, sp); //泳道未展开的情况,查找endRowStruct @@ -236,7 +239,8 @@ export function spSystemTraceDrawJankLine( sp: SpSystemTrace, endParentRow: any, selectJankStruct: JankStruct, - data: any + data: any, + isBinderClick: boolean = false ): void { let collectList = sp.favoriteChartListEL!.getAllCollectRows(); let startRow: any; @@ -263,7 +267,7 @@ export function spSystemTraceDrawJankLine( } } if (endParentRow) { - drawJankLineEndParent(endParentRow, sp, data, startRow, selectJankStruct); + drawJankLineEndParent(endParentRow, sp, data, startRow, selectJankStruct, isBinderClick); } } diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index 1d960af3a0784a51f020d0e1e22ec34540753b24..44f735fbbcf9dc949a6052e5d8b6d27ade901fcb 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -84,7 +84,6 @@ import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSp import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler'; import { FileInfo } from '../../js-heap/model/UiStruct'; import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot'; -import { LogStruct } from '../database/ui-worker/ProcedureWorkerLog'; import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample'; import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample'; import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag'; @@ -121,6 +120,7 @@ import spSystemTraceOnClickHandler, { spSystemTraceDocumentOnMouseUp, } from './SpSystemTrace.event'; import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace'; +import { readTraceFileBuffer } from '../SpApplicationPublicFunc'; function dpr(): number { return window.devicePixelRatio || 1; @@ -138,8 +138,9 @@ type SlicesTimeAlias = SlicesTime | undefined | null; @element('sp-system-trace') export class SpSystemTrace extends BaseElement { mouseCurrentPosition = 0; + static isKeyUp: boolean = true; offsetMouse = 0; - isMouseLeftDown = false; + static isMouseLeftDown = false; static scrollViewWidth = 0; static isCanvasOffScreen = true; static DATA_DICT: Map = new Map(); @@ -208,6 +209,7 @@ export class SpSystemTrace extends BaseElement { _slicesList: Array = []; _flagList: Array = []; static currentStartTime: number = 0; + static retargetIndex: number = 0; set snapshotFile(data: FileInfo) { this.snapshotFiles = data; @@ -262,7 +264,8 @@ export class SpSystemTrace extends BaseElement { addPointPair(startPoint: PairPoint, endPoint: PairPoint): void { if (startPoint.rowEL.collect) { if (this.timerShaftEL?._checkExpand) { - startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; + startPoint.rowEL.translateY = + startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; } else { startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195; } @@ -335,7 +338,7 @@ export class SpSystemTrace extends BaseElement { return this.favoriteChartListEL!.getCollectRows(condition); } - createPointEvent(it: TraceRow) { + createPointEvent(it: TraceRow): any { let event = this.eventMap[`${it.rowType}`]; if (event) { return event; @@ -361,7 +364,7 @@ export class SpSystemTrace extends BaseElement { if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') { event = 'FrameTimeLine'; } else if (it.hasAttribute('frame_type')) { - event = it.getAttribute('frame_type') + ''; + event = `${it.getAttribute('frame_type')}`; } } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) { event = 'DeliverInputEvent'; @@ -375,7 +378,7 @@ export class SpSystemTrace extends BaseElement { } } - private handleFileSystemType(it: TraceRow, event: any) { + private handleFileSystemType(it: TraceRow, event: any): void { if (it.rowId === 'FileSystemLogicalWrite') { event = 'FileSystem Logical Write'; } else if (it.rowId === 'FileSystemLogicalRead') { @@ -437,7 +440,7 @@ export class SpSystemTrace extends BaseElement { return showTab; } - timerShaftELFlagClickHandler = (flag: FlagAlias) => { + timerShaftELFlagClickHandler = (flag: FlagAlias): void => { if (flag) { setTimeout(() => { if (TraceRow.rangeSelectObject) { @@ -450,7 +453,7 @@ export class SpSystemTrace extends BaseElement { } }; - timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias) => { + timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias): void => { this.hoverFlag = hoverFlag; this.selectFlag = selectFlag; this.refreshCanvas(true, 'flagChange'); @@ -500,14 +503,14 @@ export class SpSystemTrace extends BaseElement { this.visibleRows.forEach((it) => (it.needRefresh = true)); this.refreshCanvas(false, 'rangeChange'); }; - tim: number = -1; top: number = 0; handler: any = undefined; rowsElOnScroll = (e: any): void => { this.linkNodes.forEach((itln) => { if (itln[0].rowEL.collect) { if (this.timerShaftEL?._checkExpand) { - itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; + itln[0].rowEL.translateY = + itln[0].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; } else { itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195; } @@ -516,7 +519,8 @@ export class SpSystemTrace extends BaseElement { } if (itln[1].rowEL.collect) { if (this.timerShaftEL?._checkExpand) { - itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; + itln[1].rowEL.translateY = + itln[1].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!; } else { itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195; } @@ -546,7 +550,7 @@ export class SpSystemTrace extends BaseElement { offset = 147; getRowsContentHeight(): number { - return [...this.rowsEL!.querySelectorAll>(`trace-row:not([sleeping])`)] + return [...this.rowsEL!.querySelectorAll>('trace-row:not([sleeping])')] .map((it) => it.clientHeight) .reduce((acr, cur) => acr + cur, 0); } @@ -578,8 +582,7 @@ export class SpSystemTrace extends BaseElement { } else { v.translateY = v.getBoundingClientRect().top - 195 + this.timerShaftEL.usageFoldHeight!; } - } - else { + } else { if (SpSystemTrace.isHiddenMenu) { v.translateY = v.getBoundingClientRect().top - 195 + 48; } else { @@ -612,7 +615,7 @@ export class SpSystemTrace extends BaseElement { this.favoriteChartListEL?.drawWakeUp(); // draw wakeuplist for main canvas for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { - if (i + 1 == SpSystemTrace.wakeupList.length) { + if (i + 1 === SpSystemTrace.wakeupList.length) { return; } drawWakeUpList( @@ -680,27 +683,6 @@ export class SpSystemTrace extends BaseElement { } } - drawAllLine(row: TraceRow) { - let context: CanvasRenderingContext2D; - if (row.currentContext) { - context = row.currentContext; - } else { - context = row.collect ? this.canvasFavoritePanelCtx! : this.canvasPanelCtx!; - } - let startNS = TraceRow.range!.startNS; - let endNS = TraceRow.range!.endNS; - let totalNS = TraceRow.range!.totalNS; - drawFlagLineSegment(context, this.hoverFlag, this.selectFlag, row.frame, this.timerShaftEL!); - drawWakeUp(context, CpuStruct.wakeupBean, startNS, endNS, totalNS, row.frame); - for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) { - if (i + 1 == SpSystemTrace.wakeupList.length) { - return; - } - drawWakeUpList(context, SpSystemTrace.wakeupList[i + 1], startNS, endNS, totalNS, row.frame); - } - drawLogsLineSegment(context, this.traceSheetEL?.systemLogFlag, row.frame, this.timerShaftEL!); - } - documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev); onContextMenuHandler = (e: Event): void => { @@ -727,7 +709,7 @@ export class SpSystemTrace extends BaseElement { }; } - documentOnMouseOut = (ev: MouseEvent) => spSystemTraceDocumentOnMouseOut(this, ev); + documentOnMouseOut = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseOut(this, ev); keyPressMap: Map = new Map([ ['w', false], @@ -783,7 +765,8 @@ export class SpSystemTrace extends BaseElement { } } else if (SampleStruct.selectSampleStruct) { if (SampleStruct.selectSampleStruct.begin && SampleStruct.selectSampleStruct.end) { - this.currentSlicesTime.startTime = SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!; + this.currentSlicesTime.startTime = + SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!; this.currentSlicesTime.endTime = SampleStruct.selectSampleStruct.end - SampleStruct.selectSampleStruct.startTs!; } } else { @@ -796,9 +779,9 @@ export class SpSystemTrace extends BaseElement { const selectedStruct: any = CpuStruct.selectCpuStruct || ThreadStruct.selectThreadStruct || + TraceRow.rangeSelectObject || FuncStruct.selectFuncStruct || IrqStruct.selectIrqStruct || - TraceRow.rangeSelectObject || JankStruct.selectJankStruct || AppStartupStruct.selectStartupStruct || SoStruct.selectSoStruct || @@ -819,8 +802,9 @@ export class SpSystemTrace extends BaseElement { let end = selectedStruct.end - selectedStruct.startTs; this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey); } else { - startTs = selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || 0; - let dur = selectedStruct.dur || selectedStruct.totalTime || (selectedStruct.endNS - selectedStruct.startNS) || 0; + startTs = + selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || selectedStruct.ts || 0; + let dur = selectedStruct.dur || selectedStruct.totalTime || selectedStruct.endNS - selectedStruct.startNS || 0; this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey); } } else { @@ -840,7 +824,7 @@ export class SpSystemTrace extends BaseElement { }; // 一直按着回车键的时候执行搜索功能 - continueSearch = (ev: KeyboardEvent) => { + continueSearch = (ev: KeyboardEvent): void => { if (ev.key === 'Enter') { if (ev.shiftKey) { this.dispatchEvent( @@ -926,9 +910,9 @@ export class SpSystemTrace extends BaseElement { } } - isMouseInSheet = (ev: MouseEvent) => { + isMouseInSheet = (ev: MouseEvent): boolean => { this.isMousePointInSheet = - this.traceSheetEL?.getAttribute('mode') != 'hidden' && + this.traceSheetEL?.getAttribute('mode') !== 'hidden' && ev.offsetX > this.traceSheetEL!.offsetLeft && ev.offsetY > this.traceSheetEL!.offsetTop; return this.isMousePointInSheet; @@ -938,10 +922,6 @@ export class SpSystemTrace extends BaseElement { info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight); }; - verticalScrollHandler = (row: TraceRow): void => { - row.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - }; - /** * 根据选择的traceRow 处理foler * @param currentRow 当前点击checkbox的row @@ -1019,7 +999,7 @@ export class SpSystemTrace extends BaseElement { inFavoriteArea: boolean | undefined; documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev); - hoverStructNull() { + hoverStructNull(): SpSystemTrace { CpuStruct.hoverCpuStruct = undefined; CpuFreqStruct.hoverCpuFreqStruct = undefined; ThreadStruct.hoverThreadStruct = undefined; @@ -1054,7 +1034,7 @@ export class SpSystemTrace extends BaseElement { return this; } - selectStructNull() { + selectStructNull(): SpSystemTrace { CpuStruct.selectCpuStruct = undefined; CpuStruct.wakeupBean = null; CpuFreqStruct.selectCpuFreqStruct = undefined; @@ -1083,15 +1063,15 @@ export class SpSystemTrace extends BaseElement { return this; } - isWASDKeyPress() { + isWASDKeyPress(): boolean | undefined { return ( this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s') ); } - documentOnClick = (ev: MouseEvent) => spSystemTraceDocumentOnClick(this, ev); + documentOnClick = (ev: MouseEvent): void => spSystemTraceDocumentOnClick(this, ev); - clickEmptyArea() { + clickEmptyArea(): void { this.queryAllTraceRow().forEach((it) => { it.checkType = '-1'; it.rangeSelect = false; @@ -1125,7 +1105,7 @@ export class SpSystemTrace extends BaseElement { ], [ TraceRow.ROW_TYPE_SAMPLE, - (): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined + (): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined, ], [ TraceRow.ROW_TYPE_CPU_FREQ, @@ -1155,9 +1135,18 @@ export class SpSystemTrace extends BaseElement { (): boolean => AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined, ], - [TraceRow.ROW_TYPE_STATIC_INIT, () => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined], - [TraceRow.ROW_TYPE_JANK, () => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined], - [TraceRow.ROW_TYPE_HEAP, () => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined], + [ + TraceRow.ROW_TYPE_STATIC_INIT, + (): boolean => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined, + ], + [ + TraceRow.ROW_TYPE_JANK, + (): boolean => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined, + ], + [ + TraceRow.ROW_TYPE_HEAP, + (): boolean => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined, + ], [ TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL, (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, @@ -1227,21 +1216,20 @@ export class SpSystemTrace extends BaseElement { ], [ TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER, - () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, + (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, ], [ TraceRow.ROW_TYPE_VMTRACKER_SHM, - () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, + (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, ], [ TraceRow.ROW_TYPE_VM_TRACKER_SMAPS, - () => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, + (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined, ], - [TraceRow.ROW_TYPE_LOGS, () => LogStruct.hoverLogStruct !== null && LogStruct.hoverLogStruct !== undefined], ]); - onClickHandler(clickRowType: string, row?: TraceRow) { - spSystemTraceOnClickHandler(this, clickRowType, row); + onClickHandler(clickRowType: string, row?: TraceRow, entry?: any): void { + spSystemTraceOnClickHandler(this, clickRowType, row, entry); } makePoint( @@ -1266,14 +1254,14 @@ export class SpSystemTrace extends BaseElement { }; } - drawTaskPollLine(row?: TraceRow) { + drawTaskPollLine(row?: TraceRow): void { spSystemTraceDrawTaskPollLine(this, row); } - drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any) { - spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data); + drawJankLine(endParentRow: any, selectJankStruct: JankStruct, data: any, isBinderClick: boolean = false): void { + spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data, isBinderClick); } - drawThreadLine(endParentRow: any, selectThreadStruct: ThreadStruct | undefined, data: any) { + drawThreadLine(endParentRow: any, selectThreadStruct: ThreadStruct | undefined, data: any): void { spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data); } @@ -1342,7 +1330,6 @@ export class SpSystemTrace extends BaseElement { } this.offsetMouse = ev.clientX; const rangeRuler = this.timerShaftEL?.getRangeRuler()!; - rangeRuler.translate(offset); } @@ -1371,7 +1358,6 @@ export class SpSystemTrace extends BaseElement { this.addEventListener('mousedown', this.documentOnMouseDown); this.addEventListener('mouseup', this.documentOnMouseUp); this.addEventListener('mouseout', this.documentOnMouseOut); - document.addEventListener('keydown', this.documentOnKeyDown); document.addEventListener('keypress', this.documentOnKeyPress); document.addEventListener('keyup', this.documentOnKeyUp); @@ -1379,6 +1365,144 @@ export class SpSystemTrace extends BaseElement { this.wheelListener(); } + private subRecordExportListener(): void { + window.subscribe(window.SmartEvent.UI.ExportRecord, (params) => { + let range = this.timerShaftEL?.rangeRuler?.range; + if (range) { + let expandRows = Array.from(this.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; + let data = JSON.stringify({ + leftNS: range.startNS, + rightNS: range.endNS, + G1: this.favoriteChartListEL!.getCollectRowsInfo('1'), + G2: this.favoriteChartListEL!.getCollectRowsInfo('2'), + expand: expandRows.map((row) => { + return { + type: row.rowType, + name: row.name, + id: row.rowId, + }; + }), + scrollTop: this.rowsEL!.scrollTop, + favoriteScrollTop: this.favoriteChartListEL!.scrollTop, + }); + this.downloadRecordFile(data).then(() => {}); + } + }); + } + + private async downloadRecordFile(jsonStr: string): Promise { + let a = document.createElement('a'); + let buffer = await readTraceFileBuffer(); + if (buffer) { + let str = `MarkPositionJSON->${jsonStr}\n`; + let mark = new Blob([str]); + let markBuf = await mark.arrayBuffer(); + a.href = URL.createObjectURL(new Blob([`${markBuf.byteLength}`, mark, buffer])); + a.download = (window as any).traceFileName || `${new Date().getTime()}`; + a.click(); + } + window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Downloading trace file with mark' }); + } + + private subRecordImportListener(): void { + window.subscribe(window.SmartEvent.UI.ImportRecord, (data: string) => { + let record = JSON.parse(data); + if (record.leftNS !== undefined && record.rightNS !== undefined) { + this.favoriteChartListEL?.removeAllCollectRow(); + let currentGroup = this.currentCollectGroup; + if (record.G1) { + this.currentCollectGroup = '1'; + this.restoreRecordCollectRows(record.G1); + } + if (record.G2) { + this.currentCollectGroup = '2'; + this.restoreRecordCollectRows(record.G2); + } + if (record.expand) { + let expandRows = + Array.from(this.rowsEL!.querySelectorAll>('trace-row[folder][expansion]')) || []; + let expands: Array = record.expand; + //关闭不在记录中的父泳道 + for (let expandRow of expandRows) { + if ( + !expands.includes( + (it: any) => it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType + ) + ) { + expandRow.expansion = false; + } + } + //展开记录的泳道 + for (let it of record.expand) { + let traceRow = this.rowsEL!.querySelector>( + `trace-row[folder][row-id='${it.id}'][row-type='${it.type}']` + ); + if (traceRow && !traceRow.expansion) { + traceRow.expansion = true; + } + } + } + this.currentCollectGroup = currentGroup; + this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS); + TraceRow.range!.refresh = true; + this.refreshCanvas(true); + this.restoreRecordScrollTop(record.scrollTop, record.favoriteScrollTop); + } + }); + } + + private restoreRecordScrollTop(mainScrollTop: number, favoriteScrollTop: number): void { + if (mainScrollTop && mainScrollTop > 0) { + this.rowsPaneEL!.scroll({ + top: mainScrollTop, + left: 0, + behavior: 'smooth', + }); + } + if (favoriteScrollTop && favoriteScrollTop > 0) { + this.favoriteChartListEL?.scroll({ + top: favoriteScrollTop, + left: 0, + behavior: 'smooth', + }); + } + } + + private restoreRecordCollectRows(group: Array): void { + group.forEach((it: any) => { + let traceRow: TraceRow | undefined | null = this.rowsEL!.querySelector>( + `trace-row[row-id='${it.id}'][row-type='${it.type}']` + ); + if (traceRow === null || traceRow === undefined) { + if (it.parents.length > 0) { + let rootFolder = it.parents[0]; + let folderRow: TraceRow | undefined | null = this.rowsEL!.querySelector>( + `trace-row[row-id='${rootFolder.id}'][row-type='${rootFolder.type}']` + ); + if (folderRow) { + if (!folderRow!.expansion) { + folderRow!.expansion = true; + } + for (let i = 1; i < it.parents.length; i++) { + folderRow = folderRow!.childrenList.find( + (child) => child.rowId === it.parents[i].id && child.rowType === it.parents[i].type + ); + if (!folderRow!.expansion) { + folderRow!.expansion = true; + } + } + } + if (folderRow) { + traceRow = folderRow.childrenList.find((child) => child.rowId === it.id && child.rowType === it.type); + } + } + } + if (traceRow) { + traceRow.collectEL?.click(); + } + }); + } + private wheelListener() { document.addEventListener( 'wheel', @@ -1393,9 +1517,7 @@ export class SpSystemTrace extends BaseElement { keyCode: 83, }); this.timerShaftEL!.documentOnKeyPress(eventS); - setTimeout(() => { - this.timerShaftEL!.documentOnKeyUp(eventS); - }, 200); + setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventS), 200); } if (e.deltaY < 0) { e.preventDefault(); @@ -1406,9 +1528,7 @@ export class SpSystemTrace extends BaseElement { keyCode: 87, }); this.timerShaftEL!.documentOnKeyPress(eventW); - setTimeout(() => { - this.timerShaftEL!.documentOnKeyUp(eventW); - }, 200); + setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventW), 200); } } }, @@ -1419,6 +1539,8 @@ export class SpSystemTrace extends BaseElement { connectedCallback(): void { this.initPointToEvent(); this.eventListener(); + this.subRecordExportListener(); + this.subRecordImportListener(); /** * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。 * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用, @@ -1437,7 +1559,6 @@ export class SpSystemTrace extends BaseElement { } }); }); - window.subscribe(window.SmartEvent.UI.KeyPath, (data) => { this.invisibleRows.forEach((it) => (it.needRefresh = true)); this.visibleRows.forEach((it) => (it.needRefresh = true)); @@ -1453,7 +1574,6 @@ export class SpSystemTrace extends BaseElement { }); } }); - window.subscribe(window.SmartEvent.UI.CheckALL, (data) => { this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => { it.checkType = data.isCheck ? '2' : '0'; @@ -1466,7 +1586,7 @@ export class SpSystemTrace extends BaseElement { private scrollH: number = 0; subscribeBottomTabVisibleEvent(): void { - window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number, delta: number }) => { + window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number; delta: number }) => { if (data.show === 1) { //显示底部tab this.scrollH = this.rowsEL!.scrollHeight; @@ -1524,7 +1644,7 @@ export class SpSystemTrace extends BaseElement { rootRow.expandFunc(); if (!this.isInViewport(rootRow)) { setTimeout(() => { - rootRow!.scrollIntoView({ behavior: "smooth" }) + rootRow!.scrollIntoView({ behavior: 'smooth' }); }, 500); } } else { @@ -1535,16 +1655,9 @@ export class SpSystemTrace extends BaseElement { if (rootRow) { rootRow.expandFunc(); } - if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) { - if (!this.isInViewport(rootRow)) { - let top = (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + rootRow.offsetHeight / 2 + (++depth * 20); - this.rowsPaneEL!.scrollTo({ - top: top, - left: 0, - behavior: smooth ? 'smooth' : undefined, - }); - } - } + setTimeout(() => { + rootRow!.scrollIntoView({ behavior: 'smooth', block: 'center' }); + }, 500); } } @@ -1555,7 +1668,7 @@ export class SpSystemTrace extends BaseElement { rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) - ) + ); } scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true) { @@ -1635,7 +1748,7 @@ export class SpSystemTrace extends BaseElement { url: string, progress: Function, complete?: ((res: { status: boolean; msg: string }) => void) | undefined - ) { + ): void { this.observerScrollHeightEnable = false; this.init({ url: url }, '', progress).then((res) => { if (complete) { @@ -1665,16 +1778,16 @@ export class SpSystemTrace extends BaseElement { }); } - loadSample = async (ev: File) => { + loadSample = async (ev: File): Promise => { this.observerScrollHeightEnable = false; await this.initSample(ev); this.rowsEL?.querySelectorAll('trace-row').forEach((it: any) => this.observer.observe(it)); window.publish(window.SmartEvent.UI.MouseEventEnable, { mouseEnable: true, }); - } + }; - initSample = async (ev: File) => { + initSample = async (ev: File): Promise => { this.rowsPaneEL!.scroll({ top: 0, left: 0, @@ -1683,9 +1796,9 @@ export class SpSystemTrace extends BaseElement { this.loadTraceCompleted = true; this.rowsEL!.querySelectorAll>('trace-row').forEach((it) => { this.intersectionObserver?.observe(it); - }) - }) - } + }); + }); + }; queryAllTraceRow(selectors?: string, filter?: (row: TraceRow) => boolean): TraceRow[] { return [ @@ -1694,19 +1807,19 @@ export class SpSystemTrace extends BaseElement { ]; } - search(query: string) { + search(query: string): void { this.queryAllTraceRow().forEach((item) => { - if (query == null || query == undefined || query == '') { + if (query === null || query === undefined || query === '') { if ( - item.rowType == TraceRow.ROW_TYPE_CPU || - item.rowType == TraceRow.ROW_TYPE_CPU_FREQ || - item.rowType == TraceRow.ROW_TYPE_NATIVE_MEMORY || - item.rowType == TraceRow.ROW_TYPE_FPS || - item.rowType == TraceRow.ROW_TYPE_PROCESS || - item.rowType == TraceRow.ROW_TYPE_CPU_ABILITY || - item.rowType == TraceRow.ROW_TYPE_MEMORY_ABILITY || - item.rowType == TraceRow.ROW_TYPE_DISK_ABILITY || - item.rowType == TraceRow.ROW_TYPE_NETWORK_ABILITY + item.rowType === TraceRow.ROW_TYPE_CPU || + item.rowType === TraceRow.ROW_TYPE_CPU_FREQ || + item.rowType === TraceRow.ROW_TYPE_NATIVE_MEMORY || + item.rowType === TraceRow.ROW_TYPE_FPS || + item.rowType === TraceRow.ROW_TYPE_PROCESS || + item.rowType === TraceRow.ROW_TYPE_CPU_ABILITY || + item.rowType === TraceRow.ROW_TYPE_MEMORY_ABILITY || + item.rowType === TraceRow.ROW_TYPE_DISK_ABILITY || + item.rowType === TraceRow.ROW_TYPE_NETWORK_ABILITY ) { item.expansion = false; item.rowHidden = false; @@ -1739,10 +1852,10 @@ export class SpSystemTrace extends BaseElement { async searchFunction(cpuList: Array, query: string): Promise> { let processList: Array = []; let traceRow = - this.shadowRoot!.querySelector>(`trace-row[scene]`) || + this.shadowRoot!.querySelector>('trace-row[scene]') || this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene')); if (traceRow) { - this.shadowRoot!.querySelectorAll>(`trace-row[row-type='process'][scene]`).forEach((row) => { + this.shadowRoot!.querySelectorAll>("trace-row[row-type='process'][scene]").forEach((row) => { processList.push(row.rowId!); }); if (query.includes('_')) { @@ -1765,11 +1878,11 @@ export class SpSystemTrace extends BaseElement { searchSdk(dataList: Array, query: string): Array { let traceRow = - this.shadowRoot!.querySelector>(`trace-row[scene]`) || + this.shadowRoot!.querySelector>('trace-row[scene]') || this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene')); - let dataAll = `trace-row[row-type^='sdk']`; + let dataAll = "trace-row[row-type^='sdk']"; if (traceRow) { - dataAll = `trace-row[row-type^='sdk'][scene]`; + dataAll = "trace-row[row-type^='sdk'][scene]"; } let allTraceRow: any = []; let parentRows = this.shadowRoot!.querySelectorAll>(`${dataAll}`); @@ -1795,21 +1908,24 @@ export class SpSystemTrace extends BaseElement { return dataList; } - showStruct(previous: boolean, currentIndex: number, structs: Array, retargetIndex?: number) { + showStruct(previous: boolean, currentIndex: number, structs: Array, retargetIndex?: number): number { return spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex); } - private toTargetDepth = (entry: any, funcRowID: number, funcStract: any) => { + private toTargetDepth = (entry: any, funcRowID: string, funcStract: any): void => { if (entry) { this.hoverStructNull(); this.selectStructNull(); this.wakeupListNull(); - setTimeout(() => { - this.onClickHandler(TraceRow.ROW_TYPE_FUNC); - }, 0) + FuncStruct.hoverFuncStruct = entry; FuncStruct.selectFuncStruct = entry; + // 鼠标左键点击不需要触发点击事件 + if (FuncStruct.funcSelect) { + this.onClickHandler(TraceRow.ROW_TYPE_FUNC, undefined, entry); + } this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, 'func', true, entry.depth || 0); + FuncStruct.funcSelect = true; } }; @@ -1820,8 +1936,7 @@ export class SpSystemTrace extends BaseElement { funcStract.flag = 'Did not end'; } } - - let funcRowID = funcStract.cookie == null ? funcStract.tid : `${funcStract.funName}-${funcStract.pid}`; + let funcRowID = !funcStract.cookie ? `${funcStract.tid}` : `${funcStract.funName}-${funcStract.pid}`; let targetRow = this.favoriteChartListEL?.getCollectRow((row) => { return row.rowId === funcRowID && row.rowType === 'func'; }); @@ -1836,8 +1951,8 @@ export class SpSystemTrace extends BaseElement { if (!parentRow) { return; } - let filterRow = parentRow.childrenList.filter((child) => child.rowId == funcRowID && child.rowType == 'func')[0]; - if (filterRow == null) { + let filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0]; + if (!filterRow) { let funcRow = this.rowsEL?.querySelector>(`trace-row[row-id='${funcRowID}'][row-type='func']`); if (funcRow) { filterRow = funcRow; @@ -1852,7 +1967,7 @@ export class SpSystemTrace extends BaseElement { if (row && !row.expansion) { row.expansion = true; } - const completeEntry = () => { + const completeEntry = (): void => { this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract); }; if (filterRow!.isComplete) { @@ -1864,10 +1979,10 @@ export class SpSystemTrace extends BaseElement { } } - closeAllExpandRows(pid: string) { + closeAllExpandRows(pid: string): void { let expandRows = this.rowsEL?.querySelectorAll>(`trace-row[row-type='process'][expansion]`); expandRows?.forEach((row) => { - if (row.rowId != pid) { + if (row.rowId !== pid) { row.expansion = false; } }); @@ -1876,7 +1991,7 @@ export class SpSystemTrace extends BaseElement { moveRangeToLeft(startTime: number, dur: number) { let startNS = this.timerShaftEL?.getRange()?.startNS || 0; let endNS = this.timerShaftEL?.getRange()?.endNS || 0; - let harfDur = Math.trunc((endNS - startNS) - dur / 2); + let harfDur = Math.trunc(endNS - startNS - dur / 2); let leftNs = startTime; let rightNs = startTime + dur + harfDur; if (startTime - harfDur < 0) { @@ -1888,7 +2003,7 @@ export class SpSystemTrace extends BaseElement { this.refreshCanvas(true); } - moveRangeToCenter(startTime: number, dur: number) { + moveRangeToCenter(startTime: number, dur: number): void { let startNS = this.timerShaftEL?.getRange()?.startNS || 0; let endNS = this.timerShaftEL?.getRange()?.endNS || 0; let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2); @@ -1916,19 +2031,19 @@ export class SpSystemTrace extends BaseElement { it.name = t; it.type = 'thread'; if (next) { - if (it.startTime! + it.dur! > next!.startTime! || it.dur == -1 || it.dur === null || it.dur === undefined) { + if (it.startTime! + it.dur! > next!.startTime! || it.dur === -1 || it.dur === null || it.dur === undefined) { it.dur = next!.startTime! - it.startTime!; it.nofinish = true; } } else { - if (it.dur == -1 || it.dur === null || it.dur === undefined) { + if (it.dur === -1 || it.dur === null || it.dur === undefined) { it.dur = TraceRow.range!.endNS - it.startTime!; it.nofinish = true; } } } - reset(progress: Function | undefined | null) { + reset(progress: Function | undefined | null): void { this.visibleRows.length = 0; this.tipEL!.style.display = 'none'; this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight); @@ -1941,7 +2056,7 @@ export class SpSystemTrace extends BaseElement { TraceRowConfig.allTraceRowList = []; this.favoriteChartListEL!.reset(); if (this.rowsEL) { - this.rowsEL.querySelectorAll>(`trace-row`).forEach((row) => { + this.rowsEL.querySelectorAll>('trace-row').forEach((row) => { row.clearMemory(); this.rowsEL!.removeChild(row); }); @@ -1965,16 +2080,21 @@ export class SpSystemTrace extends BaseElement { procedurePool.clearCache(); Utils.clearData(); InitAnalysis.getInstance().isInitAnalysis = true; - procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => { }); + procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: any) => {}); if (threadPool) { - threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: any, len: number): void => { }); + threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: any, len: number): void => {}); } this.times.clear(); resetVSync(); SpSystemTrace.keyPathList = []; + TabPaneCurrentSelection.isTransformed = false; } - init = async (param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, progress: Function) => { + init = async ( + param: { buf?: ArrayBuffer; url?: string }, + wasmConfigUri: string, + progress: Function + ): Promise => { return spSystemTraceInit(this, param, wasmConfigUri, progress); }; @@ -2014,7 +2134,7 @@ export class SpSystemTrace extends BaseElement { }; } - displayTip(row: TraceRow, struct: any, html: string) { + displayTip(row: TraceRow, struct: any, html: string): void { let x = row.hoverX + 248; let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top; if ((struct === undefined || struct === null) && this.tipEL) { @@ -2023,8 +2143,12 @@ export class SpSystemTrace extends BaseElement { } if (this.tipEL) { this.tipEL.innerHTML = html; - if (row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART || row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) { - this.tipEL.style.maxWidth = row.clientWidth / 3 + 'px'; + if ( + row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER || + row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART || + row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT + ) { + this.tipEL.style.maxWidth = `${row.clientWidth / 3} px`; this.tipEL.style.wordBreak = ' break-all'; this.tipEL.style.height = 'unset'; this.tipEL.style.display = 'block'; @@ -2056,7 +2180,7 @@ export class SpSystemTrace extends BaseElement { }); } - wakeupListNull() { + wakeupListNull(): SpSystemTrace { SpSystemTrace.wakeupList = []; return this; } diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 12dfd1880405ac08f60ef0e83245c9f20e80e34a..cba83946a5489a9bf34035127a7e340bbc1e46bd 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -810,60 +810,50 @@ export class FrameChart extends BaseElement { */ private updateTipContent(): void { const hoverNode = ChartStruct.hoverFuncStruct; - if (!hoverNode) { - return; - } - const name = hoverNode?.symbol.replace(//g, '>'); - const percent = ((hoverNode?.percent || 0) * 100).toFixed(2); - const threadPercent = this.getCurrentPercentOfThread(hoverNode); - const processPercent = this.getCurrentPercentOfProcess(hoverNode); - switch (this._mode) { - case ChartMode.Byte: - const size = Utils.getByteWithUnit(this.getNodeValue(hoverNode)); - const countPercent = ((this.getNodeValue(hoverNode) / this.total) * 100).toFixed(2); - this.hintContent = ` + if (hoverNode) { + const name = hoverNode?.symbol.replace(//g, '>'); + const percent = ((hoverNode?.percent || 0) * 100).toFixed(2); + const threadPercent = this.getCurrentPercentOfThread(hoverNode); + const processPercent = this.getCurrentPercentOfProcess(hoverNode); + switch (this._mode) { + case ChartMode.Byte: + const size = Utils.getByteWithUnit(this.getNodeValue(hoverNode)); + const countPercent = ((this.getNodeValue(hoverNode) / this.total) * 100).toFixed(2); + this.hintContent = ` Symbol: ${name}
Lib: ${hoverNode?.lib}
Addr: ${hoverNode?.addr}
Size: ${size} (${percent}%)
Count: ${hoverNode?.count} (${countPercent}%)`; - break; - case ChartMode.Duration: - const duration = Utils.getProbablyTime(this.getNodeValue(hoverNode)); - this.hintContent = ` + break; + case ChartMode.Duration: + const duration = Utils.getProbablyTime(this.getNodeValue(hoverNode)); + this.hintContent = ` Name: ${name}
- Lib: ${hoverNode?.lib} -
+ Lib: ${hoverNode?.lib}
Addr: ${hoverNode?.addr}
Duration: ${duration}`; - - break; - case ChartMode.EventCount: - case ChartMode.Count: - const label = ChartMode.Count === this._mode ? 'Count' : 'EventCount'; - const count = this.getNodeValue(hoverNode); - this.hintContent = ` + break; + case ChartMode.EventCount: + case ChartMode.Count: + const label = ChartMode.Count === this._mode ? 'Count' : 'EventCount'; + const count = this.getNodeValue(hoverNode); + this.hintContent = ` Name: ${name}
- Lib: ${hoverNode?.lib} -
- Addr: ${hoverNode?.addr} -
+ Lib: ${hoverNode?.lib}
+ Addr: ${hoverNode?.addr}
${label}: ${count}`; - break; - } - if (this._mode != ChartMode.Byte) { - if (threadPercent) { - this.hintContent += ` -
- % in current Thread: ${threadPercent}%`; + break; } - if (processPercent) { - this.hintContent += ` -
- % in current Process: ${processPercent}%`; + if (this._mode !== ChartMode.Byte) { + if (threadPercent) { + this.hintContent += `
% in current Thread: ${threadPercent}%`; + } + if (processPercent) { + this.hintContent += `
% in current Process: ${processPercent}%`; + } + this.hintContent += `
% in all Process: ${percent}%`; } - this.hintContent += `
- % in all Process: ${percent}%`; } } diff --git a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts index 09bef06774607865aa72e67f4b05aa87a5f7a6c5..fb18372bbd325d9a47067f215fe9eb556419c113 100644 --- a/ide/src/trace/component/chart/SpAbilityMonitorChart.ts +++ b/ide/src/trace/component/chart/SpAbilityMonitorChart.ts @@ -40,9 +40,14 @@ import { abilityPurgeableDataSender, } from '../../database/data-trafic/VmTrackerDataSender'; import { MemoryConfig } from '../../bean/MemoryConfig'; -import {queryMemoryMaxData} from "../../database/sql/Memory.sql"; -import {queryDiskIoMaxData, queryNetWorkMaxData} from "../../database/sql/SqlLite.sql"; -import {queryAbilityExits, queryCPuAbilityMaxData, queryPurgeableSysData} from "../../database/sql/Ability.sql"; +import { queryMemoryMaxData } from '../../database/sql/Memory.sql'; +import { queryDiskIoMaxData, queryNetWorkMaxData } from '../../database/sql/SqlLite.sql'; +import { queryAbilityExits, queryCPuAbilityMaxData, queryPurgeableSysData } from '../../database/sql/Ability.sql'; +const networkNameList: Array = ['Bytes In/Sec', 'Bytes Out/Sec', 'Packets In/Sec', 'Packets Out/Sec']; +const memoryNameList: Array = ['MemoryTotal', 'Cached', 'SwapTotal']; +const diskIONameList: Array = ['Bytes Read/Sec', 'Bytes Written/Sec', 'Read Ops/Sec', 'Written Ops/Sec']; +const key = 'abilityMonitor'; + export class SpAbilityMonitorChart { private trace: SpSystemTrace; constructor(trace: SpSystemTrace) { @@ -72,11 +77,13 @@ export class SpAbilityMonitorChart { return maxByteName; }; - async init() { + async init(): Promise { let time = new Date().getTime(); let result = await queryAbilityExits(); info('Ability Monitor Exits Tables size is: ', result!.length); - if (result.length <= 0) return; + if (result.length <= 0) { + return; + } let processRow = this.initAbilityRow(); if (this.hasTable(result, 'trace_cpu_usage')) { await this.initCpuAbility(processRow); @@ -105,7 +112,7 @@ export class SpAbilityMonitorChart { info('The time to load the AbilityMonitor data is: ', durTime); } - private hasTable(result: Array, tableName: string) { + private hasTable(result: Array, tableName: string): boolean { return result.find((o) => { return o.event_name === tableName; }); @@ -113,7 +120,7 @@ export class SpAbilityMonitorChart { private initAbilityRow = (): TraceRow => { let abilityRow = TraceRow.skeleton(); - abilityRow.rowId = 'abilityMonitor'; + abilityRow.rowId = key; abilityRow.rowType = TraceRow.ROW_TYPE_MONITOR; abilityRow.style.height = '40px'; abilityRow.rowParentId = ''; @@ -174,29 +181,25 @@ export class SpAbilityMonitorChart { info('The time to load the Ability Cpu is: ', durTime); }; - private initUserMonitorTraceRow( - processRow: TraceRow, - cpuNameList: Array, - hasUserLoad: boolean - ): void { + private initUserMonitorTraceRow(processRow: TraceRow, cpuList: Array, load: boolean): void { let userTraceRow = TraceRow.skeleton(); - userTraceRow.rowParentId = `abilityMonitor`; + userTraceRow.rowParentId = key; userTraceRow.rowHidden = !processRow.expansion; - userTraceRow.rowId = cpuNameList[1]; + userTraceRow.rowId = cpuList[1]; userTraceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY; userTraceRow.style.height = '40px'; - userTraceRow.style.width = `100%`; + userTraceRow.style.width = '100%'; userTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; userTraceRow.selectChangeHandler = this.trace.selectChangeHandler; userTraceRow.setAttribute('children', ''); - userTraceRow.name = `CPU ${cpuNameList[1]} Load`; + userTraceRow.name = `CPU ${cpuList[1]} Load`; userTraceRow.supplierFrame = (): Promise => cpuAbilityUserDataSender(userTraceRow, 'CpuAbilityUserData').then((res): CpuAbilityMonitorStruct[] => { this.computeDur(res); return res; }); userTraceRow.focusHandler = (ev): void => { - let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2) + '%'; + let monitorCpuTip = `${(CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2)}%`; this.trace?.displayTip( userTraceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, @@ -218,9 +221,9 @@ export class SpAbilityMonitorChart { { context: context, useCache: useCache, - type: `monitorCpu1`, + type: 'monitorCpu1', maxCpuUtilization: 100, - maxCpuUtilizationName: hasUserLoad ? '100%' : '0%', + maxCpuUtilizationName: load ? '100%' : '0%', }, userTraceRow ); @@ -229,29 +232,25 @@ export class SpAbilityMonitorChart { processRow.addChildTraceRow(userTraceRow); } - private initTotalMonitorTraceRow( - processRow: TraceRow, - cpuNameList: Array, - hasTotal: boolean - ): void { + private initTotalMonitorTraceRow(parent: TraceRow, cpuList: Array, hasTotal: boolean): void { let traceRow = TraceRow.skeleton(); - traceRow.rowParentId = `abilityMonitor`; - traceRow.rowHidden = !processRow.expansion; - traceRow.rowId = cpuNameList[0]; + traceRow.rowParentId = key; + traceRow.rowHidden = !parent.expansion; + traceRow.rowId = cpuList[0]; traceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY; traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; traceRow.style.height = '40px'; - traceRow.style.width = `100%`; + traceRow.style.width = '100%'; traceRow.setAttribute('children', ''); - traceRow.name = `CPU ${cpuNameList[0]} Load`; + traceRow.name = `CPU ${cpuList[0]} Load`; traceRow.supplierFrame = (): Promise => cpuAbilityUserDataSender(traceRow, 'CpuAbilityMonitorData').then((res): CpuAbilityMonitorStruct[] => { this.computeDur(res); return res; }); traceRow.focusHandler = (ev): void => { - let monitorCpuTip = (CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2) + '%'; + let monitorCpuTip = `${(CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2)}'%'`; this.trace?.displayTip(traceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, `${monitorCpuTip}`); }; traceRow.findHoverStruct = (): void => { @@ -269,7 +268,7 @@ export class SpAbilityMonitorChart { { context: context, useCache: useCache, - type: `monitorCpu0`, + type: 'monitorCpu0', maxCpuUtilization: 100, maxCpuUtilizationName: hasTotal ? '100%' : '0%', }, @@ -277,33 +276,32 @@ export class SpAbilityMonitorChart { ); traceRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(traceRow); + parent.addChildTraceRow(traceRow); } - private initSysMonitorTraceRow( - processRow: TraceRow, - cpuNameList: Array, - hasSystemLoad: boolean - ): void { + private initSysMonitorTraceRow(parent: TraceRow, cpuList: Array, hasLoad: boolean): void { let sysTraceRow = TraceRow.skeleton(); - sysTraceRow.rowParentId = `abilityMonitor`; - sysTraceRow.rowHidden = !processRow.expansion; - sysTraceRow.rowId = cpuNameList[2]; + sysTraceRow.rowParentId = key; + sysTraceRow.rowHidden = !parent.expansion; + sysTraceRow.rowId = cpuList[2]; sysTraceRow.rowType = TraceRow.ROW_TYPE_CPU_ABILITY; sysTraceRow.style.height = '40px'; - sysTraceRow.style.width = `100%`; + sysTraceRow.style.width = '100%'; sysTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; sysTraceRow.selectChangeHandler = this.trace.selectChangeHandler; sysTraceRow.setAttribute('children', ''); - sysTraceRow.name = `CPU ${cpuNameList[2]} Load`; + sysTraceRow.name = `CPU ${cpuList[2]} Load`; sysTraceRow.supplierFrame = (): Promise => cpuAbilityUserDataSender(sysTraceRow, 'CpuAbilitySystemData').then((res): CpuAbilityMonitorStruct[] => { this.computeDur(res); return res; }); sysTraceRow.focusHandler = (): void => { - this.trace?.displayTip(sysTraceRow, CpuAbilityMonitorStruct.hoverCpuAbilityStruct, - `${(CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2) + '%'}`); + this.trace?.displayTip( + sysTraceRow, + CpuAbilityMonitorStruct.hoverCpuAbilityStruct, + `${(CpuAbilityMonitorStruct.hoverCpuAbilityStruct?.value || 0).toFixed(2)}%` + ); }; sysTraceRow.findHoverStruct = (): void => { CpuAbilityMonitorStruct.hoverCpuAbilityStruct = sysTraceRow.getHoverStruct(); @@ -320,105 +318,81 @@ export class SpAbilityMonitorChart { { context: context, useCache: useCache, - type: `monitorCpu2`, + type: 'monitorCpu2', maxCpuUtilization: 100, - maxCpuUtilizationName: hasSystemLoad ? '100%' : '0%', + maxCpuUtilizationName: hasLoad ? '100%' : '0%', }, sysTraceRow ); sysTraceRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(sysTraceRow); + parent.addChildTraceRow(sysTraceRow); } - private initMemoryAbility = async (processRow: TraceRow): Promise => { - let time = new Date().getTime(); - // sys.mem.total sys.mem.cached sys.mem.swap.total - let memoryNameList: Array = ['MemoryTotal', 'Cached', 'SwapTotal']; - let memoryTotal = await queryMemoryMaxData('sys.mem.total'); + private memoryUsedThreadHandle(memoryUsedRow: TraceRow, memoryTotal: any[]): void { let memoryTotalValue = memoryTotal[0].maxValue; - let memoryTotalId = memoryTotal[0].filter_id; let memoryTotalValueName = this.memoryMath(memoryTotalValue); - let memoryUsedTraceRow = TraceRow.skeleton(); - memoryUsedTraceRow.rowParentId = `abilityMonitor`; - memoryUsedTraceRow.rowHidden = !processRow.expansion; - memoryUsedTraceRow.rowId = memoryNameList[0]; - memoryUsedTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; - memoryUsedTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - memoryUsedTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - memoryUsedTraceRow.style.height = '40px'; - memoryUsedTraceRow.style.width = `100%`; - memoryUsedTraceRow.setAttribute('children', ''); - memoryUsedTraceRow.name = memoryNameList[0]; - memoryUsedTraceRow.supplierFrame = (): Promise => { - return abilityMemoryUsedDataSender(memoryTotalId, memoryUsedTraceRow).then( - (res): MemoryAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - }; - memoryUsedTraceRow.focusHandler = (ev): void => { - this.trace?.displayTip( - memoryUsedTraceRow, - MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, - `${Utils.getBinaryKBWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value || 0)}` - ); - }; - memoryUsedTraceRow.findHoverStruct = (): void => { - MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = memoryUsedTraceRow.getHoverStruct(); - }; - memoryUsedTraceRow.onThreadHandler = (useCache): void => { + memoryUsedRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (memoryUsedTraceRow.currentContext) { - context = memoryUsedTraceRow.currentContext; + if (memoryUsedRow.currentContext) { + context = memoryUsedRow.currentContext; } else { - context = memoryUsedTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = memoryUsedRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - memoryUsedTraceRow.canvasSave(context); + memoryUsedRow.canvasSave(context); (renders['monitorMemory'] as MemoryAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorMemory0`, + type: 'monitorMemory0', maxMemoryByte: memoryTotalValue, maxMemoryByteName: memoryTotalValueName, }, - memoryUsedTraceRow + memoryUsedRow ); - memoryUsedTraceRow.canvasRestore(context, this.trace); + memoryUsedRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(memoryUsedTraceRow); - let cached = await queryMemoryMaxData('sys.mem.cached'); - let cachedValue = cached[0].maxValue; - let cachedValueName = this.memoryMath(cachedValue); - let cachedId = cached[0].filter_id; - let cachedFilesTraceRow = TraceRow.skeleton(); - cachedFilesTraceRow.rowParentId = `abilityMonitor`; - cachedFilesTraceRow.rowHidden = !processRow.expansion; - cachedFilesTraceRow.rowId = memoryNameList[1]; - cachedFilesTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; - cachedFilesTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - cachedFilesTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - cachedFilesTraceRow.style.height = '40px'; - cachedFilesTraceRow.style.width = `100%`; - cachedFilesTraceRow.setAttribute('children', ''); - cachedFilesTraceRow.name = memoryNameList[1]; - cachedFilesTraceRow.supplierFrame = (): Promise => - abilityMemoryUsedDataSender(cachedId, cachedFilesTraceRow).then((res): MemoryAbilityMonitorStruct[] => { + } + + private async initMemoryUsedRow( + memoryUsedRow: TraceRow, + parent: TraceRow + ): Promise { + let memoryTotal = await queryMemoryMaxData('sys.mem.total'); + let memoryTotalId = memoryTotal[0].filter_id; + + memoryUsedRow.rowParentId = key; + memoryUsedRow.rowHidden = !parent.expansion; + memoryUsedRow.rowId = memoryNameList[0]; + memoryUsedRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; + memoryUsedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + memoryUsedRow.selectChangeHandler = this.trace.selectChangeHandler; + memoryUsedRow.style.height = '40px'; + memoryUsedRow.style.width = '100%'; + memoryUsedRow.setAttribute('children', ''); + memoryUsedRow.name = memoryNameList[0]; + memoryUsedRow.supplierFrame = (): Promise => { + return abilityMemoryUsedDataSender(memoryTotalId, memoryUsedRow).then((res): MemoryAbilityMonitorStruct[] => { this.computeDur(res); return res; }); - cachedFilesTraceRow.focusHandler = (ev): void => { + }; + memoryUsedRow.focusHandler = (ev): void => { this.trace?.displayTip( - cachedFilesTraceRow, + memoryUsedRow, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, `${Utils.getBinaryKBWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value || 0)}` ); }; - cachedFilesTraceRow.findHoverStruct = (): void => { - MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = cachedFilesTraceRow.getHoverStruct(); + memoryUsedRow.findHoverStruct = (): void => { + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = memoryUsedRow.getHoverStruct(); }; + this.memoryUsedThreadHandle(memoryUsedRow, memoryTotal); + } + + private cachedThreadHandler(cachedFilesTraceRow: TraceRow, cached: any[]): void { + let cachedValue = cached[0].maxValue; + let cachedValueName = this.memoryMath(cachedValue); cachedFilesTraceRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (cachedFilesTraceRow.currentContext) { @@ -431,7 +405,7 @@ export class SpAbilityMonitorChart { { context: context, useCache: useCache, - type: `monitorMemory1`, + type: 'monitorMemory1', maxMemoryByte: cachedValue, maxMemoryByteName: cachedValueName, }, @@ -439,479 +413,612 @@ export class SpAbilityMonitorChart { ); cachedFilesTraceRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(cachedFilesTraceRow); - let swap = await queryMemoryMaxData('sys.mem.swap.total'); - let swapValue = swap[0].maxValue; - let swapValueName = this.memoryMath(swapValue); - let swapId = swap[0].filter_id; - let compressedTraceRow = TraceRow.skeleton(); - compressedTraceRow.rowParentId = `abilityMonitor`; - compressedTraceRow.rowHidden = !processRow.expansion; - compressedTraceRow.rowId = memoryNameList[2]; - compressedTraceRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; - compressedTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - compressedTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - compressedTraceRow.style.height = '40px'; - compressedTraceRow.style.width = `100%`; - compressedTraceRow.setAttribute('children', ''); - compressedTraceRow.name = memoryNameList[2]; - compressedTraceRow.supplierFrame = (): Promise => - abilityMemoryUsedDataSender(swapId, compressedTraceRow).then((res): MemoryAbilityMonitorStruct[] => { + } + + private async initCachedRow( + cachedFilesRow: TraceRow, + parent: TraceRow + ): Promise { + let cached = await queryMemoryMaxData('sys.mem.cached'); + + let cachedId = cached[0].filter_id; + cachedFilesRow.rowParentId = key; + cachedFilesRow.rowHidden = !parent.expansion; + cachedFilesRow.rowId = memoryNameList[1]; + cachedFilesRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; + cachedFilesRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cachedFilesRow.selectChangeHandler = this.trace.selectChangeHandler; + cachedFilesRow.style.height = '40px'; + cachedFilesRow.style.width = '100%'; + cachedFilesRow.setAttribute('children', ''); + cachedFilesRow.name = memoryNameList[1]; + cachedFilesRow.supplierFrame = (): Promise => + abilityMemoryUsedDataSender(cachedId, cachedFilesRow).then((res): MemoryAbilityMonitorStruct[] => { this.computeDur(res); return res; }); - compressedTraceRow.focusHandler = (ev): void => { + cachedFilesRow.focusHandler = (ev): void => { this.trace?.displayTip( - compressedTraceRow, + cachedFilesRow, MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, `${Utils.getBinaryKBWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value || 0)}` ); }; - compressedTraceRow.findHoverStruct = (): void => { - MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = compressedTraceRow.getHoverStruct(); + cachedFilesRow.findHoverStruct = (): void => { + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = cachedFilesRow.getHoverStruct(); }; - compressedTraceRow.onThreadHandler = (useCache): void => { + this.cachedThreadHandler(cachedFilesRow, cached); + } + + private compressThreadHandler(compressedRow: TraceRow, swap: any[]): void { + let swapValue = swap[0].maxValue; + let swapValueName = this.memoryMath(swapValue); + compressedRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (compressedTraceRow.currentContext) { - context = compressedTraceRow.currentContext; + if (compressedRow.currentContext) { + context = compressedRow.currentContext; } else { - context = compressedTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = compressedRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - compressedTraceRow.canvasSave(context); + compressedRow.canvasSave(context); (renders['monitorMemory'] as MemoryAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorMemory2`, + type: 'monitorMemory2', maxMemoryByte: swapValue, maxMemoryByteName: swapValueName, }, - compressedTraceRow + compressedRow ); - compressedTraceRow.canvasRestore(context, this.trace); + compressedRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(compressedTraceRow); - let durTime = new Date().getTime() - time; - info('The time to load the Ability Memory is: ', durTime); - }; + } - private initDiskAbility = async (processRow: TraceRow): Promise => { - let time = new Date().getTime(); - let maxList = await queryDiskIoMaxData(); - let maxBytesRead = maxList[0].bytesRead; - let maxBytesReadName = this.diskIOMath(maxBytesRead); - let diskIONameList: Array = ['Bytes Read/Sec', 'Bytes Written/Sec', 'Read Ops/Sec', 'Written Ops/Sec']; - let bytesReadTraceRow = TraceRow.skeleton(); - bytesReadTraceRow.rowParentId = `abilityMonitor`; - bytesReadTraceRow.rowHidden = !processRow.expansion; - bytesReadTraceRow.rowId = diskIONameList[0]; - bytesReadTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; - bytesReadTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - bytesReadTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - bytesReadTraceRow.style.height = '40px'; - bytesReadTraceRow.style.width = `100%`; - bytesReadTraceRow.setAttribute('children', ''); - bytesReadTraceRow.name = 'Disk ' + diskIONameList[0]; - bytesReadTraceRow.supplierFrame = (): Promise => - abilityBytesReadDataSender(bytesReadTraceRow, 'AbilityBytesReadData').then((res): DiskAbilityMonitorStruct[] => { + private async initCompressedRow( + compressedRow: TraceRow, + parent: TraceRow + ): Promise { + let swap = await queryMemoryMaxData('sys.mem.swap.total'); + let swapId = swap[0].filter_id; + compressedRow.rowParentId = key; + compressedRow.rowHidden = !parent.expansion; + compressedRow.rowId = memoryNameList[2]; + compressedRow.rowType = TraceRow.ROW_TYPE_MEMORY_ABILITY; + compressedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + compressedRow.selectChangeHandler = this.trace.selectChangeHandler; + compressedRow.style.height = '40px'; + compressedRow.style.width = '100%'; + compressedRow.setAttribute('children', ''); + compressedRow.name = memoryNameList[2]; + compressedRow.supplierFrame = (): Promise => + abilityMemoryUsedDataSender(swapId, compressedRow).then((res): MemoryAbilityMonitorStruct[] => { this.computeDur(res); return res; }); - bytesReadTraceRow.focusHandler = (ev): void => { + compressedRow.focusHandler = (ev): void => { this.trace?.displayTip( - bytesReadTraceRow, - DiskAbilityMonitorStruct.hoverDiskAbilityStruct, - `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` + compressedRow, + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct, + `${Utils.getBinaryKBWithUnit(MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct?.value || 0)}` ); }; - bytesReadTraceRow.findHoverStruct = (): void => { - DiskAbilityMonitorStruct.hoverDiskAbilityStruct = bytesReadTraceRow.getHoverStruct(); + compressedRow.findHoverStruct = (): void => { + MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = compressedRow.getHoverStruct(); }; - bytesReadTraceRow.onThreadHandler = (useCache): void => { + this.compressThreadHandler(compressedRow, swap); + } + + private initMemoryAbility = async (processRow: TraceRow): Promise => { + let time = new Date().getTime(); + // sys.mem.total sys.mem.cached sys.mem.swap.total + let memoryUsedTraceRow = TraceRow.skeleton(); + this.initMemoryUsedRow(memoryUsedTraceRow, processRow); + processRow.addChildTraceRow(memoryUsedTraceRow); + + let cachedFilesTraceRow = TraceRow.skeleton(); + this.initCachedRow(cachedFilesTraceRow, processRow); + processRow.addChildTraceRow(cachedFilesTraceRow); + + let compressedTraceRow = TraceRow.skeleton(); + this.initCompressedRow(compressedTraceRow, processRow); + processRow.addChildTraceRow(compressedTraceRow); + let durTime = new Date().getTime() - time; + info('The time to load the Ability Memory is: ', durTime); + }; + + private bytesReadThreadHandler(bytesReadRow: TraceRow, maxList: any[]): void { + let maxBytesRead = maxList[0].bytesRead; + let maxBytesReadName = this.diskIOMath(maxBytesRead); + bytesReadRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (bytesReadTraceRow.currentContext) { - context = bytesReadTraceRow.currentContext; + if (bytesReadRow.currentContext) { + context = bytesReadRow.currentContext; } else { - context = bytesReadTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = bytesReadRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - bytesReadTraceRow.canvasSave(context); + bytesReadRow.canvasSave(context); (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorDiskIo0`, + type: 'monitorDiskIo0', maxDiskRate: maxBytesRead, maxDiskRateName: maxBytesReadName, }, - bytesReadTraceRow + bytesReadRow ); - bytesReadTraceRow.canvasRestore(context, this.trace); + bytesReadRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(bytesReadTraceRow); - let maxBytesWrite = maxList[0].bytesWrite; - let maxBytesWriteName = this.diskIOMath(maxBytesWrite); - let bytesWrittenTraceRow = TraceRow.skeleton(); - bytesWrittenTraceRow.rowParentId = `abilityMonitor`; - bytesWrittenTraceRow.rowHidden = !processRow.expansion; - bytesWrittenTraceRow.rowId = diskIONameList[1]; - bytesWrittenTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; - bytesWrittenTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - bytesWrittenTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - bytesWrittenTraceRow.style.height = '40px'; - bytesWrittenTraceRow.style.width = `100%`; - bytesWrittenTraceRow.setAttribute('children', ''); - bytesWrittenTraceRow.name = 'Disk ' + diskIONameList[1]; - bytesWrittenTraceRow.supplierFrame = (): Promise => - abilityBytesReadDataSender(bytesWrittenTraceRow, 'AbilityBytesWrittenData').then( - (res): DiskAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - bytesWrittenTraceRow.focusHandler = (ev): void => { + } + + private initBytesReadRow( + bytesReadRow: TraceRow, + parentRow: TraceRow, + maxList: any[] + ): void { + bytesReadRow.rowParentId = key; + bytesReadRow.rowHidden = !parentRow.expansion; + bytesReadRow.rowId = diskIONameList[0]; + bytesReadRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; + bytesReadRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesReadRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesReadRow.style.height = '40px'; + bytesReadRow.style.width = '100%'; + bytesReadRow.setAttribute('children', ''); + bytesReadRow.name = `Disk ${diskIONameList[0]}`; + bytesReadRow.supplierFrame = (): Promise => + abilityBytesReadDataSender(bytesReadRow, 'AbilityBytesReadData').then((res): DiskAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + bytesReadRow.focusHandler = (ev): void => { this.trace?.displayTip( - bytesWrittenTraceRow, + bytesReadRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` ); }; - bytesWrittenTraceRow.findHoverStruct = (): void => { - DiskAbilityMonitorStruct.hoverDiskAbilityStruct = bytesWrittenTraceRow.getHoverStruct(); + bytesReadRow.findHoverStruct = (): void => { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = bytesReadRow.getHoverStruct(); }; - bytesWrittenTraceRow.onThreadHandler = (useCache): void => { + this.bytesReadThreadHandler(bytesReadRow, maxList); + } + private bytesWriteThreadHandler(bytesWriteRow: TraceRow, maxList: any[]): void { + let maxBytesWrite = maxList[0].bytesWrite; + let maxBytesWriteName = this.diskIOMath(maxBytesWrite); + bytesWriteRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (bytesWrittenTraceRow.currentContext) { - context = bytesWrittenTraceRow.currentContext; + if (bytesWriteRow.currentContext) { + context = bytesWriteRow.currentContext; } else { - context = bytesWrittenTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = bytesWriteRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - bytesWrittenTraceRow.canvasSave(context); + bytesWriteRow.canvasSave(context); (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorDiskIo1`, + type: 'monitorDiskIo1', maxDiskRate: maxBytesWrite, maxDiskRateName: maxBytesWriteName, }, - bytesWrittenTraceRow + bytesWriteRow ); - bytesWrittenTraceRow.canvasRestore(context, this.trace); + bytesWriteRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(bytesWrittenTraceRow); + } + + private initBytesWriteRow( + bytesWriteRow: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + bytesWriteRow.rowParentId = key; + bytesWriteRow.rowHidden = !parent.expansion; + bytesWriteRow.rowId = diskIONameList[1]; + bytesWriteRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; + bytesWriteRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + bytesWriteRow.selectChangeHandler = this.trace.selectChangeHandler; + bytesWriteRow.style.height = '40px'; + bytesWriteRow.style.width = '100%'; + bytesWriteRow.setAttribute('children', ''); + bytesWriteRow.name = `Disk ${diskIONameList[1]}`; + bytesWriteRow.supplierFrame = (): Promise => + abilityBytesReadDataSender(bytesWriteRow, 'AbilityBytesWrittenData').then((res): DiskAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + bytesWriteRow.focusHandler = (ev): void => { + this.trace?.displayTip( + bytesWriteRow, + DiskAbilityMonitorStruct.hoverDiskAbilityStruct, + `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` + ); + }; + bytesWriteRow.findHoverStruct = (): void => { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = bytesWriteRow.getHoverStruct(); + }; + this.bytesWriteThreadHandler(bytesWriteRow, maxList); + } + + private initReadOspRow(readOpsRow: TraceRow, parent: TraceRow, maxList: any[]): void { let maxReadOps = maxList[0].readOps; let maxReadOpsName = this.diskIOMath(maxReadOps); - let readOpsTraceRow = TraceRow.skeleton(); - readOpsTraceRow.rowParentId = `abilityMonitor`; - readOpsTraceRow.rowHidden = !processRow.expansion; - readOpsTraceRow.rowId = diskIONameList[2]; - readOpsTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; - readOpsTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - readOpsTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - readOpsTraceRow.style.height = '40px'; - readOpsTraceRow.style.width = `100%`; - readOpsTraceRow.setAttribute('children', ''); - readOpsTraceRow.name = 'Disk ' + diskIONameList[2]; - readOpsTraceRow.supplierFrame = (): Promise => - abilityBytesReadDataSender(readOpsTraceRow, 'AbilityReadOpsData').then((res): DiskAbilityMonitorStruct[] => { + readOpsRow.rowParentId = key; + readOpsRow.rowHidden = !parent.expansion; + readOpsRow.rowId = diskIONameList[2]; + readOpsRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; + readOpsRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + readOpsRow.selectChangeHandler = this.trace.selectChangeHandler; + readOpsRow.style.height = '40px'; + readOpsRow.style.width = '100%'; + readOpsRow.setAttribute('children', ''); + readOpsRow.name = `Disk ${diskIONameList[2]}`; + readOpsRow.supplierFrame = (): Promise => + abilityBytesReadDataSender(readOpsRow, 'AbilityReadOpsData').then((res): DiskAbilityMonitorStruct[] => { this.computeDur(res); return res; }); - readOpsTraceRow.focusHandler = (ev): void => { + readOpsRow.focusHandler = (ev): void => { this.trace?.displayTip( - readOpsTraceRow, + readOpsRow, DiskAbilityMonitorStruct.hoverDiskAbilityStruct, `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` ); }; - readOpsTraceRow.findHoverStruct = (): void => { - DiskAbilityMonitorStruct.hoverDiskAbilityStruct = readOpsTraceRow.getHoverStruct(); + readOpsRow.findHoverStruct = (): void => { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = readOpsRow.getHoverStruct(); }; - readOpsTraceRow.onThreadHandler = (useCache): void => { + readOpsRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (readOpsTraceRow.currentContext) { - context = readOpsTraceRow.currentContext; + if (readOpsRow.currentContext) { + context = readOpsRow.currentContext; } else { - context = readOpsTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = readOpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - readOpsTraceRow.canvasSave(context); + readOpsRow.canvasSave(context); (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorDiskIo2`, + type: 'monitorDiskIo2', maxDiskRate: maxReadOps, maxDiskRateName: maxReadOpsName, }, - readOpsTraceRow + readOpsRow ); - readOpsTraceRow.canvasRestore(context, this.trace); + readOpsRow.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(readOpsTraceRow); + } + + private writeOspThreadHandler(writeOpsRow: TraceRow, maxList: any[]): void { let maxWriteOps = maxList[0].writeOps; let maxWriteOpsName = this.diskIOMath(maxWriteOps); - let writtenOpsTraceRow = TraceRow.skeleton(); - writtenOpsTraceRow.rowParentId = `abilityMonitor`; - writtenOpsTraceRow.rowHidden = !processRow.expansion; - writtenOpsTraceRow.rowId = diskIONameList[3]; - writtenOpsTraceRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; - writtenOpsTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - writtenOpsTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - writtenOpsTraceRow.style.height = '40px'; - writtenOpsTraceRow.style.width = `100%`; - writtenOpsTraceRow.setAttribute('children', ''); - writtenOpsTraceRow.name = 'Disk ' + diskIONameList[3]; - writtenOpsTraceRow.supplierFrame = (): Promise => - abilityBytesReadDataSender(writtenOpsTraceRow, 'AbilityWrittenOpsData').then( - (res): DiskAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - writtenOpsTraceRow.focusHandler = (ev): void => { - this.trace?.displayTip( - writtenOpsTraceRow, - DiskAbilityMonitorStruct.hoverDiskAbilityStruct, - `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` - ); - }; - writtenOpsTraceRow.findHoverStruct = (): void => { - DiskAbilityMonitorStruct.hoverDiskAbilityStruct = writtenOpsTraceRow.getHoverStruct(); - }; - writtenOpsTraceRow.onThreadHandler = (useCache): void => { + writeOpsRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (writtenOpsTraceRow.currentContext) { - context = writtenOpsTraceRow.currentContext; + if (writeOpsRow.currentContext) { + context = writeOpsRow.currentContext; } else { - context = writtenOpsTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = writeOpsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - writtenOpsTraceRow.canvasSave(context); + writeOpsRow.canvasSave(context); (renders['monitorDiskIo'] as DiskIoAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorDiskIo3`, + type: 'monitorDiskIo3', maxDiskRate: maxWriteOps, maxDiskRateName: maxWriteOpsName, }, - writtenOpsTraceRow + writeOpsRow ); - writtenOpsTraceRow.canvasRestore(context, this.trace); + writeOpsRow.canvasRestore(context, this.trace); }; + } + + private initWriteOspRow( + writeOpsRow: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + writeOpsRow.rowParentId = key; + writeOpsRow.rowHidden = !parent.expansion; + writeOpsRow.rowId = diskIONameList[3]; + writeOpsRow.rowType = TraceRow.ROW_TYPE_DISK_ABILITY; + writeOpsRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + writeOpsRow.selectChangeHandler = this.trace.selectChangeHandler; + writeOpsRow.style.height = '40px'; + writeOpsRow.style.width = '100%'; + writeOpsRow.setAttribute('children', ''); + writeOpsRow.name = `Disk ${diskIONameList[3]}`; + writeOpsRow.supplierFrame = (): Promise => + abilityBytesReadDataSender(writeOpsRow, 'AbilityWrittenOpsData').then((res): DiskAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + writeOpsRow.focusHandler = (ev): void => { + this.trace?.displayTip( + writeOpsRow, + DiskAbilityMonitorStruct.hoverDiskAbilityStruct, + `${DiskAbilityMonitorStruct.hoverDiskAbilityStruct?.value || '0'} KB/S` + ); + }; + writeOpsRow.findHoverStruct = (): void => { + DiskAbilityMonitorStruct.hoverDiskAbilityStruct = writeOpsRow.getHoverStruct(); + }; + this.writeOspThreadHandler(writeOpsRow, maxList); + } + private initDiskAbility = async (processRow: TraceRow): Promise => { + let time = new Date().getTime(); + let maxList = await queryDiskIoMaxData(); + + let bytesReadTraceRow = TraceRow.skeleton(); + this.initBytesReadRow(bytesReadTraceRow, processRow, maxList); + processRow.addChildTraceRow(bytesReadTraceRow); + + let bytesWrittenTraceRow = TraceRow.skeleton(); + this.initBytesWriteRow(bytesWrittenTraceRow, processRow, maxList); + processRow.addChildTraceRow(bytesWrittenTraceRow); + + let readOpsTraceRow = TraceRow.skeleton(); + this.initReadOspRow(readOpsTraceRow, processRow, maxList); + processRow.addChildTraceRow(readOpsTraceRow); + + let writtenOpsTraceRow = TraceRow.skeleton(); + this.initWriteOspRow(writtenOpsTraceRow, processRow, maxList); processRow.addChildTraceRow(writtenOpsTraceRow); let durTime = new Date().getTime() - time; info('The time to load the Ability DiskIO is: ', durTime); }; - private initNetworkAbility = async (processRow: TraceRow): Promise => { - let time = new Date().getTime(); - let maxList = await queryNetWorkMaxData(); + private bytesInRowThreadHandler(row: TraceRow, maxList: any[]): void { let maxBytesIn = maxList[0].maxIn; let maxInByteName = this.networkMath(maxBytesIn); - let networkNameList: Array = ['Bytes In/Sec', 'Bytes Out/Sec', 'Packets In/Sec', 'Packets Out/Sec']; - let bytesInTraceRow = TraceRow.skeleton(); - bytesInTraceRow.rowParentId = `abilityMonitor`; - bytesInTraceRow.rowHidden = !processRow.expansion; - bytesInTraceRow.rowId = networkNameList[0]; - bytesInTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; - bytesInTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - bytesInTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - bytesInTraceRow.style.height = '40px'; - bytesInTraceRow.style.width = `100%`; - bytesInTraceRow.setAttribute('children', ''); - bytesInTraceRow.name = 'Network ' + networkNameList[0]; - bytesInTraceRow.supplierFrame = (): Promise => - abilityBytesInTraceDataSender(bytesInTraceRow, 'AbilityBytesInTraceData').then( - (res): NetworkAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - bytesInTraceRow.focusHandler = (ev): void => { - this.trace?.displayTip( - bytesInTraceRow, - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, - `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value || 0)}` - ); - }; - bytesInTraceRow.findHoverStruct = (): void => { - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = bytesInTraceRow.getHoverStruct(); - }; - bytesInTraceRow.onThreadHandler = (useCache): void => { + row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (bytesInTraceRow.currentContext) { - context = bytesInTraceRow.currentContext; + if (row.currentContext) { + context = row.currentContext; } else { - context = bytesInTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - bytesInTraceRow.canvasSave(context); + row.canvasSave(context); (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorNetwork0`, + type: 'monitorNetwork0', maxNetworkRate: maxBytesIn, maxNetworkRateName: maxInByteName, }, - bytesInTraceRow + row ); - bytesInTraceRow.canvasRestore(context, this.trace); + row.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(bytesInTraceRow); - let bytesOutTraceRow = TraceRow.skeleton(); - let maxBytesOut = maxList[0].maxOut; - let maxOutByteName = this.networkMath(maxBytesOut); - bytesOutTraceRow.rowParentId = `abilityMonitor`; - bytesOutTraceRow.rowHidden = !processRow.expansion; - bytesOutTraceRow.rowId = networkNameList[1]; - bytesOutTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; - bytesOutTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - bytesOutTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - bytesOutTraceRow.style.height = '40px'; - bytesOutTraceRow.style.width = `100%`; - bytesOutTraceRow.setAttribute('children', ''); - bytesOutTraceRow.name = 'Network ' + networkNameList[1]; - bytesOutTraceRow.supplierFrame = (): Promise => - abilityBytesInTraceDataSender(bytesOutTraceRow, 'AbilityBytesOutTraceData').then( - (res): NetworkAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - bytesOutTraceRow.focusHandler = (ev): void => { + } + + private initBytesInRow( + row: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + row.rowParentId = key; + row.rowHidden = !parent.expansion; + row.rowId = networkNameList[0]; + row.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.style.height = '40px'; + row.style.width = '100%'; + row.setAttribute('children', ''); + row.name = `Network ${networkNameList[0]}`; + row.supplierFrame = (): Promise => + abilityBytesInTraceDataSender(row, 'AbilityBytesInTraceData').then((res): NetworkAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + row.focusHandler = (ev): void => { this.trace?.displayTip( - bytesOutTraceRow, + row, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value || 0)}` ); }; - bytesOutTraceRow.findHoverStruct = (): void => { - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = bytesOutTraceRow.getHoverStruct(); + row.findHoverStruct = (): void => { + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = row.getHoverStruct(); }; - bytesOutTraceRow.onThreadHandler = (useCache): void => { + this.bytesInRowThreadHandler(row, maxList); + } + private bytesOutRowThreadHandler(row: TraceRow, maxList: any[]): void { + let maxBytesOut = maxList[0].maxOut; + let maxOutByteName = this.networkMath(maxBytesOut); + row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (bytesOutTraceRow.currentContext) { - context = bytesOutTraceRow.currentContext; + if (row.currentContext) { + context = row.currentContext; } else { - context = bytesOutTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - bytesOutTraceRow.canvasSave(context); + row.canvasSave(context); (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorNetwork1`, + type: 'monitorNetwork1', maxNetworkRate: maxBytesOut, maxNetworkRateName: maxOutByteName, }, - bytesOutTraceRow + row ); - bytesOutTraceRow.canvasRestore(context, this.trace); + row.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(bytesOutTraceRow); - let packetInTraceRow = TraceRow.skeleton(); - let maxPacketIn = maxList[0].maxPacketIn; - let maxInPacketName = this.networkMath(maxPacketIn); - packetInTraceRow.rowParentId = `abilityMonitor`; - packetInTraceRow.rowHidden = !processRow.expansion; - packetInTraceRow.rowId = networkNameList[2]; - packetInTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; - packetInTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - packetInTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - packetInTraceRow.style.height = '40px'; - packetInTraceRow.style.width = `100%`; - packetInTraceRow.setAttribute('children', ''); - packetInTraceRow.name = 'Network ' + networkNameList[2]; - packetInTraceRow.supplierFrame = (): Promise => - abilityBytesInTraceDataSender(packetInTraceRow, 'AbilityPacketInTraceData').then( - (res): NetworkAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } - ); - packetInTraceRow.focusHandler = (ev): void => { + } + + private initBytesOutRow( + row: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + row.rowParentId = key; + row.rowHidden = !parent.expansion; + row.rowId = networkNameList[1]; + row.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.style.height = '40px'; + row.style.width = '100%'; + row.setAttribute('children', ''); + row.name = `Network ${networkNameList[1]}`; + row.supplierFrame = (): Promise => + abilityBytesInTraceDataSender(row, 'AbilityBytesOutTraceData').then((res): NetworkAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + row.focusHandler = (ev): void => { this.trace?.displayTip( - packetInTraceRow, + row, NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value || 0)}` ); }; - packetInTraceRow.findHoverStruct = (): void => { - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = packetInTraceRow.getHoverStruct(); + row.findHoverStruct = (): void => { + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = row.getHoverStruct(); }; - packetInTraceRow.onThreadHandler = (useCache): void => { + this.bytesOutRowThreadHandler(row, maxList); + } + + private packetInRowThreadHandler(row: TraceRow, maxList: any[]): void { + let maxPacketIn = maxList[0].maxPacketIn; + let maxInPacketName = this.networkMath(maxPacketIn); + row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (packetInTraceRow.currentContext) { - context = packetInTraceRow.currentContext; + if (row.currentContext) { + context = row.currentContext; } else { - context = packetInTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - packetInTraceRow.canvasSave(context); + row.canvasSave(context); (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorNetwork-Packet2`, + type: 'monitorNetwork-Packet2', maxNetworkRate: maxPacketIn, maxNetworkRateName: maxInPacketName, }, - packetInTraceRow + row ); - packetInTraceRow.canvasRestore(context, this.trace); + row.canvasRestore(context, this.trace); }; - processRow.addChildTraceRow(packetInTraceRow); - let packetOutTraceRow = TraceRow.skeleton(); - let maxPacketOut = maxList[0].maxPacketOut; - let maxOutPacketName = this.networkMath(maxPacketOut); - packetOutTraceRow.rowParentId = `abilityMonitor`; - packetOutTraceRow.rowHidden = !processRow.expansion; - packetOutTraceRow.rowId = networkNameList[3]; - packetOutTraceRow.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; - packetOutTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - packetOutTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - packetOutTraceRow.style.height = '40px'; - packetOutTraceRow.style.width = `100%`; - packetOutTraceRow.setAttribute('children', ''); - packetOutTraceRow.name = 'Network ' + networkNameList[3]; - packetOutTraceRow.supplierFrame = (): Promise => - abilityBytesInTraceDataSender(packetOutTraceRow, 'AbilityPacketsOutTraceData').then( - (res): NetworkAbilityMonitorStruct[] => { - this.computeDur(res); - return res; - } + } + + private initPacketInRow( + row: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + row.rowParentId = key; + row.rowHidden = !parent.expansion; + row.rowId = networkNameList[2]; + row.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.style.height = '40px'; + row.style.width = '100%'; + row.setAttribute('children', ''); + row.name = `Network ${networkNameList[2]}`; + row.supplierFrame = (): Promise => + abilityBytesInTraceDataSender(row, 'AbilityPacketInTraceData').then((res): NetworkAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + row.focusHandler = (ev): void => { + this.trace?.displayTip( + row, + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, + `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct?.value || 0)}` ); - packetOutTraceRow.focusHandler = (ev): void => { - if (NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct) { - this.trace?.displayTip( - packetOutTraceRow, - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, - `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct!.value!)}` - ); - } }; - packetOutTraceRow.findHoverStruct = (): void => { - NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = packetOutTraceRow.getHoverStruct(); + row.findHoverStruct = (): void => { + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = row.getHoverStruct(); }; - packetOutTraceRow.onThreadHandler = (useCache): void => { + this.packetInRowThreadHandler(row, maxList); + } + + private packetOutRowThreadHandler(row: TraceRow, maxList: any[]): void { + let maxPacketOut = maxList[0].maxPacketOut; + let maxOutPacketName = this.networkMath(maxPacketOut); + row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; - if (packetOutTraceRow.currentContext) { - context = packetOutTraceRow.currentContext; + if (row.currentContext) { + context = row.currentContext; } else { - context = packetOutTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; } - packetOutTraceRow.canvasSave(context); + row.canvasSave(context); (renders['monitorNetwork'] as NetworkAbilityRender).renderMainThread( { context: context, useCache: useCache, - type: `monitorNetwork3`, + type: 'monitorNetwork3', maxNetworkRate: maxPacketOut, maxNetworkRateName: maxOutPacketName, }, - packetOutTraceRow + row ); - packetOutTraceRow.canvasRestore(context, this.trace); + row.canvasRestore(context, this.trace); + }; + } + + private initPacketOutRow( + row: TraceRow, + parent: TraceRow, + maxList: any[] + ): void { + row.rowParentId = key; + row.rowHidden = !parent.expansion; + row.rowId = networkNameList[3]; + row.rowType = TraceRow.ROW_TYPE_NETWORK_ABILITY; + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.style.height = '40px'; + row.style.width = '100%'; + row.setAttribute('children', ''); + row.name = `Network ${networkNameList[3]}`; + row.supplierFrame = (): Promise => + abilityBytesInTraceDataSender(row, 'AbilityPacketsOutTraceData').then((res): NetworkAbilityMonitorStruct[] => { + this.computeDur(res); + return res; + }); + row.focusHandler = (ev): void => { + if (NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct) { + this.trace?.displayTip( + row, + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct, + `${Utils.getBinaryByteWithUnit(NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct!.value!)}` + ); + } }; + row.findHoverStruct = (): void => { + NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = row.getHoverStruct(); + }; + this.packetOutRowThreadHandler(row, maxList); + } + private initNetworkAbility = async (processRow: TraceRow): Promise => { + let time = new Date().getTime(); + let maxList = await queryNetWorkMaxData(); + let bytesInTraceRow = TraceRow.skeleton(); + this.initBytesInRow(bytesInTraceRow, processRow, maxList); + processRow.addChildTraceRow(bytesInTraceRow); + + let bytesOutTraceRow = TraceRow.skeleton(); + this.initBytesOutRow(bytesOutTraceRow, processRow, maxList); + processRow.addChildTraceRow(bytesOutTraceRow); + let packetInTraceRow = TraceRow.skeleton(); + this.initPacketInRow(packetInTraceRow, processRow, maxList); + processRow.addChildTraceRow(packetInTraceRow); + let packetOutTraceRow = TraceRow.skeleton(); + this.initPacketOutRow(packetOutTraceRow, processRow, maxList); processRow.addChildTraceRow(packetOutTraceRow); let durTime = new Date().getTime() - time; info('The time to load the Ability Network is: ', durTime); @@ -1007,7 +1114,7 @@ export class SpAbilityMonitorChart { processRow: TraceRow ): TraceRow { let abilityMonitor = TraceRow.skeleton(); - abilityMonitor.rowParentId = 'abilityMonitor'; + abilityMonitor.rowParentId = key; abilityMonitor.rowHidden = !processRow.expansion; abilityMonitor.rowId = rowId; abilityMonitor.rowType = type; @@ -1021,7 +1128,7 @@ export class SpAbilityMonitorChart { abilityMonitor.focusHandler = (): void => { this.showTip(abilityMonitor); }; - abilityMonitor.findHoverStruct = () => { + abilityMonitor.findHoverStruct = (): void => { SnapshotStruct.hoverSnapshotStruct = abilityMonitor.getHoverStruct(); }; abilityMonitor.onThreadHandler = (useCache): void => { diff --git a/ide/src/trace/component/chart/SpAllAppStartups.ts b/ide/src/trace/component/chart/SpAllAppStartups.ts index c82e2f09fa18a0cd0cc79f134427d25e46da0544..c37b3a61e3d181bcc1472878f18d3a7f5b8f128e 100644 --- a/ide/src/trace/component/chart/SpAllAppStartups.ts +++ b/ide/src/trace/component/chart/SpAllAppStartups.ts @@ -17,7 +17,11 @@ import { SpSystemTrace } from '../SpSystemTrace'; import { TraceRow } from '../trace/base/TraceRow'; import { renders } from '../../database/ui-worker/ProcedureWorker'; import { CpuFreqStruct } from '../../database/ui-worker/ProcedureWorkerFreq'; -import { queryAppStartupProcessIds, queryProcessStartup, querySingleAppStartupsName } from '../../database/sql/ProcessThread.sql'; +import { + queryAppStartupProcessIds, + queryProcessStartup, + querySingleAppStartupsName, +} from '../../database/sql/ProcessThread.sql'; import { FlagsConfig } from '../SpFlags'; import { AllAppStartupStruct, AllAppStartupRender } from '../../database/ui-worker/ProcedureWorkerAllAppStartup'; @@ -33,7 +37,7 @@ export class SpAllAppStartupsChart { SpAllAppStartupsChart.trace = trace; } - async init() { + async init(): Promise { SpAllAppStartupsChart.APP_STARTUP_PID_ARR = []; let appStartUpPids = await queryAppStartupProcessIds(); appStartUpPids.forEach((it) => SpAllAppStartupsChart.APP_STARTUP_PID_ARR.push(it.pid)); @@ -41,29 +45,19 @@ export class SpAllAppStartupsChart { SpAllAppStartupsChart.allAppStartupsAva = []; for (let i = 0; i < SpAllAppStartupsChart.APP_STARTUP_PID_ARR.length; i++) { let tmpSingleApp: any[] = await queryProcessStartup(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!); - if (tmpSingleApp.length == 8) { + if (tmpSingleApp.length === 8) { let avilSingleName = await querySingleAppStartupsName(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]!); SpAllAppStartupsChart.allAppStartupsAva.push(SpAllAppStartupsChart.APP_STARTUP_PID_ARR[i]); SpAllAppStartupsChart.AllAppStartupsNameArr.push(avilSingleName![0].name); } } let loadAppStartup: boolean = FlagsConfig.getFlagsConfigEnableStatus('AppStartup'); - if (loadAppStartup && SpAllAppStartupsChart.allAppStartupsAva.length) await this.initFolder(); + if (loadAppStartup && SpAllAppStartupsChart.allAppStartupsAva.length) { + await this.initFolder(); + } } - async initFolder() { - let row: TraceRow = TraceRow.skeleton(); - row.setAttribute('hasStartup', 'true'); - row.rowId = `all-app-start-${SpAllAppStartupsChart.APP_STARTUP_PID_ARR![0]}`; - row.index = 0; - row.rowType = TraceRow.ROW_TYPE_ALL_APPSTARTUPS; - row.rowParentId = ''; - row.folder = false; - row.style.height = '40px'; - row.name = `All App Startups`; - row.addTemplateTypes('AppStartup'); - row.selectChangeHandler = SpAllAppStartupsChart.trace.selectChangeHandler; - row.favoriteChangeHandler = SpAllAppStartupsChart.trace.favoriteChangeHandler; + private supplier(row: TraceRow): void { row.supplier = async (): Promise> => { let sendRes: AllAppStartupStruct[] | PromiseLike = []; for (let i = 0; i < SpAllAppStartupsChart.allAppStartupsAva.length; i++) { @@ -81,7 +75,7 @@ export class SpAllAppStartupsChart { } } tmpResArr.forEach((item) => { - if (item.startTs == maxStartTs) { + if (item.startTs === maxStartTs) { endTs = Number(item.startTs) + Number(item.dur); singleDur = Number(endTs) - Number(minStartTs); } @@ -108,6 +102,22 @@ export class SpAllAppStartupsChart { } return sendRes; }; + } + + async initFolder(): Promise { + let row: TraceRow = TraceRow.skeleton(); + row.setAttribute('hasStartup', 'true'); + row.rowId = `all-app-start-${SpAllAppStartupsChart.APP_STARTUP_PID_ARR![0]}`; + row.index = 0; + row.rowType = TraceRow.ROW_TYPE_ALL_APPSTARTUPS; + row.rowParentId = ''; + row.folder = false; + row.style.height = '40px'; + row.name = 'All App Startups'; + row.addTemplateTypes('AppStartup'); + row.selectChangeHandler = SpAllAppStartupsChart.trace.selectChangeHandler; + row.favoriteChangeHandler = SpAllAppStartupsChart.trace.favoriteChangeHandler; + this.supplier(row); row.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; diff --git a/ide/src/trace/component/chart/SpArkTsChart.ts b/ide/src/trace/component/chart/SpArkTsChart.ts index 086f0312a1af1c72eeac28937b0a9934e1db7048..1a39e0c25350a1b01b770675062f13067fabb6de 100644 --- a/ide/src/trace/component/chart/SpArkTsChart.ts +++ b/ide/src/trace/component/chart/SpArkTsChart.ts @@ -14,7 +14,6 @@ */ import { SpSystemTrace } from '../SpSystemTrace'; import { TraceRow } from '../trace/base/TraceRow'; -import { info } from '../../../log/Log'; import { renders } from '../../database/ui-worker/ProcedureWorker'; import { type EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { type HeapTimelineRender, HeapTimelineStruct } from '../../database/ui-worker/ProcedureWorkerHeapTimeline'; @@ -22,16 +21,14 @@ import { HeapDataInterface, type ParseListener } from '../../../js-heap/HeapData import { LoadDatabase } from '../../../js-heap/LoadDatabase'; import { type FileInfo } from '../../../js-heap/model/UiStruct'; import { type HeapSnapshotRender, HeapSnapshotStruct } from '../../database/ui-worker/ProcedureWorkerHeapSnapshot'; -import { procedurePool } from '../../database/Procedure'; import { Utils } from '../trace/base/Utils'; import { type JsCpuProfilerChartFrame } from '../../bean/JsStruct'; import { type JsCpuProfilerRender, JsCpuProfilerStruct } from '../../database/ui-worker/ProcedureWorkerCpuProfiler'; import { ns2s } from '../../database/ui-worker/ProcedureWorkerCommon'; -import { - cpuProfilerDataSender -} from '../../database/data-trafic/ArkTsSender'; -import {queryJsCpuProfilerConfig, queryJsCpuProfilerData} from "../../database/sql/Cpu.sql"; -import {queryJsMemoryData} from "../../database/sql/Memory.sql"; +import { cpuProfilerDataSender } from '../../database/data-trafic/ArkTsSender'; +import { queryJsCpuProfilerConfig, queryJsCpuProfilerData } from '../../database/sql/Cpu.sql'; +import { queryJsMemoryData } from '../../database/sql/Memory.sql'; +import { type HeapSample } from '../../../js-heap/model/DatabaseStruct'; const TYPE_SNAPSHOT = 0; const TYPE_TIMELINE = 1; @@ -55,9 +52,59 @@ export class SpArkTsChart implements ParseListener { return this.allCombineDataMap; } + private cpuProfilerSupplierFrame(): void { + this.jsCpuProfilerRow!.supplierFrame = (): Promise> => { + return cpuProfilerDataSender(this.jsCpuProfilerRow!).then((res: any) => { + let maxHeight = res.maxDepth * 20; + this.jsCpuProfilerRow!.style.height = `${maxHeight}px`; + if (res.dataList.length > 0) { + this.allCombineDataMap = new Map(); + for (let data of res.dataList) { + this.allCombineDataMap.set(data.id, data); + SpSystemTrace.jsProfilerMap.set(data.id, data); + } + res.dataList.forEach((data: any) => { + data.children = []; + if (data.childrenIds.length > 0) { + for (let id of data.childrenIds) { + let child = SpSystemTrace.jsProfilerMap.get(Number(id)); + data.children.push(child); + } + } + data.name = SpSystemTrace.DATA_DICT.get(data.nameId) || LAMBDA_FUNCTION_NAME; + data.url = SpSystemTrace.DATA_DICT.get(data.urlId) || 'unknown'; + if (data.url && data.url !== 'unknown') { + let dirs = data.url.split('/'); + data.scriptName = dirs.pop() || ''; + } + }); + } + return res.dataList; + }); + }; + } + + private folderThreadHandler(): void { + this.folderRow!.onThreadHandler = (useCache): void => { + this.folderRow!.canvasSave(this.trace.canvasPanelCtx!); + if (this.folderRow!.expansion) { + this.trace.canvasPanelCtx?.clearRect(0, 0, this.folderRow!.frame.width, this.folderRow!.frame.height); + } else { + (renders.empty as EmptyRender).renderMainThread( + { + context: this.trace.canvasPanelCtx, + useCache: useCache, + type: '', + }, + this.folderRow! + ); + } + this.folderRow!.canvasRestore(this.trace.canvasPanelCtx!, this.trace); + }; + } + public async initFolder(): Promise { let jsConfig = await queryJsCpuProfilerConfig(); - let jsCpu = await queryJsCpuProfilerData(); let jsMemory = await queryJsMemoryData(); if (jsMemory.length > 0 || jsCpu.length > 0) { @@ -68,28 +115,13 @@ export class SpArkTsChart implements ParseListener { this.folderRow.style.height = '40px'; this.folderRow.rowParentId = ''; this.folderRow.folder = true; - this.folderRow.name = `Ark Ts ` + this.process; + this.folderRow.name = `Ark Ts ${this.process}`; this.folderRow.addTemplateTypes('ArkTs'); this.folderRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; this.folderRow.selectChangeHandler = this.trace.selectChangeHandler; this.folderRow.supplierFrame = (): Promise> => new Promise>((resolve) => resolve([])); - this.folderRow.onThreadHandler = (useCache): void => { - this.folderRow!.canvasSave(this.trace.canvasPanelCtx!); - if (this.folderRow!.expansion) { - this.trace.canvasPanelCtx?.clearRect(0, 0, this.folderRow!.frame.width, this.folderRow!.frame.height); - } else { - (renders.empty as EmptyRender).renderMainThread( - { - context: this.trace.canvasPanelCtx, - useCache: useCache, - type: ``, - }, - this.folderRow! - ); - } - this.folderRow!.canvasRestore(this.trace.canvasPanelCtx!, this.trace); - }; + this.folderThreadHandler(); this.trace.rowsEL?.appendChild(this.folderRow); if (this.folderRow && jsConfig[0].type !== -1 && jsMemory.length > 0) { this.folderRow.addTemplateTypes('Memory'); @@ -108,35 +140,7 @@ export class SpArkTsChart implements ParseListener { await this.loadJsDatabase.loadDatabase(this); } if (this.jsCpuProfilerRow && jsCpu.length > 0) { - this.jsCpuProfilerRow!.supplierFrame = (): Promise> => { - return cpuProfilerDataSender(this.jsCpuProfilerRow!).then((res: any) => { - let maxHeight = res.maxDepth * 20; - this.jsCpuProfilerRow!.style.height = `${maxHeight}px`; - if (res.dataList.length > 0) { - this.allCombineDataMap = new Map(); - for (let data of res.dataList) { - this.allCombineDataMap.set(data.id, data); - SpSystemTrace.jsProfilerMap.set(data.id, data); - } - res.dataList.forEach((data: any) => { - data.children = []; - if (data.childrenIds.length > 0) { - for (let id of data.childrenIds) { - let child = SpSystemTrace.jsProfilerMap.get(Number(id)); - data.children.push(child); - } - } - data.name = SpSystemTrace.DATA_DICT.get(data.nameId) || LAMBDA_FUNCTION_NAME; - data.url = SpSystemTrace.DATA_DICT.get(data.urlId) || 'unknown'; - if (data.url && data.url !== 'unknown') { - let dirs = data.url.split('/'); - data.scriptName = dirs.pop() || ''; - } - }); - } - return res.dataList; - }); - }; + this.cpuProfilerSupplierFrame(); } } } @@ -146,7 +150,7 @@ export class SpArkTsChart implements ParseListener { this.heapTimelineRow.rowParentId = this.process; this.heapTimelineRow.rowHidden = !this.folderRow!.expansion; this.heapTimelineRow.style.height = '40px'; - this.heapTimelineRow.name = `Heaptimeline`; + this.heapTimelineRow.name = 'Heaptimeline'; this.heapTimelineRow.folder = false; this.heapTimelineRow.rowType = TraceRow.ROW_TYPE_HEAP_TIMELINE; this.heapTimelineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; @@ -159,7 +163,7 @@ export class SpArkTsChart implements ParseListener { `Size: ${Utils.getBinaryByteWithUnit(HeapTimelineStruct.hoverHeapTimelineStruct?.size || 0)}` ); }; - this.heapTimelineRow!.findHoverStruct = () => { + this.heapTimelineRow!.findHoverStruct = (): void => { HeapTimelineStruct.hoverHeapTimelineStruct = this.heapTimelineRow!.getHoverStruct(); }; this.folderRow!.addChildTraceRow(this.heapTimelineRow!); @@ -170,9 +174,10 @@ export class SpArkTsChart implements ParseListener { this.heapSnapshotRow.rowParentId = this.process; this.heapSnapshotRow.rowHidden = !this.folderRow!.expansion; this.heapSnapshotRow.style.height = '40px'; - this.heapSnapshotRow.name = `Heapsnapshot`; - this.heapSnapshotRow.rowId = `heapsnapshot`; + this.heapSnapshotRow.name = 'Heapsnapshot'; + this.heapSnapshotRow.rowId = 'heapsnapshot'; this.heapSnapshotRow.folder = false; + this.heapSnapshotRow.rowType = TraceRow.ROW_TYPE_HEAP_SNAPSHOT; this.heapSnapshotRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; this.heapSnapshotRow.selectChangeHandler = this.trace.selectChangeHandler; @@ -185,12 +190,55 @@ export class SpArkTsChart implements ParseListener { Size: ${Utils.getBinaryByteWithUnit(HeapSnapshotStruct.hoverSnapshotStruct?.size || 0)}` ); }; - this.heapSnapshotRow!.findHoverStruct = () => { + this.heapSnapshotRow!.findHoverStruct = (): void => { HeapSnapshotStruct.hoverSnapshotStruct = this.heapSnapshotRow!.getHoverStruct(); }; this.folderRow!.addChildTraceRow(this.heapSnapshotRow); } + private heapLineThreadHandler(samples: HeapSample[]): void { + this.heapTimelineRow!.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D; + if (this.heapTimelineRow?.currentContext) { + context = this.heapTimelineRow!.currentContext; + } else { + context = this.heapTimelineRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + this.heapTimelineRow!.canvasSave(context); + (renders['heap-timeline'] as HeapTimelineRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'heap-timeline', + samples: samples, + }, + this.heapTimelineRow! + ); + this.heapTimelineRow!.canvasRestore(context, this.trace); + }; + } + + private heapSnapshotThreadHandler(): void { + this.heapSnapshotRow!.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D; + if (this.heapSnapshotRow?.currentContext) { + context = this.heapSnapshotRow!.currentContext; + } else { + context = this.heapSnapshotRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + this.heapSnapshotRow!.canvasSave(context); + (renders['heap-snapshot'] as HeapSnapshotRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'heap-snapshot', + }, + this.heapSnapshotRow! + ); + this.heapSnapshotRow!.canvasRestore(context, this.trace); + }; + } + public async parseDone(fileModule: Array): Promise { if (fileModule.length > 0) { let heapFile = HeapDataInterface.getInstance().getFileStructs(); @@ -198,48 +246,13 @@ export class SpArkTsChart implements ParseListener { this.trace.snapshotFile = file; if (file.type === TYPE_TIMELINE) { let samples = HeapDataInterface.getInstance().getSamples(file.id); - this.heapTimelineRow!.rowId = `heaptimeline` + file.id; + this.heapTimelineRow!.rowId = `heaptimeline${file.id}`; this.heapTimelineRow!.supplierFrame = (): Promise => new Promise((resolve) => resolve(samples)); - this.heapTimelineRow!.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (this.heapTimelineRow?.currentContext) { - context = this.heapTimelineRow!.currentContext; - } else { - context = this.heapTimelineRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - this.heapTimelineRow!.canvasSave(context); - (renders['heap-timeline'] as HeapTimelineRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `heap-timeline`, - samples: samples, - }, - this.heapTimelineRow! - ); - this.heapTimelineRow!.canvasRestore(context, this.trace); - }; + this.heapLineThreadHandler(samples); } else if (file.type === TYPE_SNAPSHOT) { this.heapSnapshotRow!.supplierFrame = (): Promise> => new Promise>((resolve) => resolve(heapFile)); - this.heapSnapshotRow!.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (this.heapSnapshotRow?.currentContext) { - context = this.heapSnapshotRow!.currentContext; - } else { - context = this.heapSnapshotRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - this.heapSnapshotRow!.canvasSave(context); - (renders['heap-snapshot'] as HeapSnapshotRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `heap-snapshot`, - }, - this.heapSnapshotRow! - ); - this.heapSnapshotRow!.canvasRestore(context, this.trace); - }; + this.heapSnapshotThreadHandler(); } } } @@ -270,7 +283,7 @@ export class SpArkTsChart implements ParseListener { ${JsCpuProfilerStruct.hoverJsCpuProfilerStruct?.url || 0}` ); }; - this.jsCpuProfilerRow!.findHoverStruct = () => { + this.jsCpuProfilerRow!.findHoverStruct = (): void => { JsCpuProfilerStruct.hoverJsCpuProfilerStruct = this.jsCpuProfilerRow!.getHoverStruct(); }; this.jsCpuProfilerRow.onThreadHandler = (useCache): void => { @@ -285,7 +298,7 @@ export class SpArkTsChart implements ParseListener { { context: context, useCache: useCache, - type: `js-cpu-profiler`, + type: 'js-cpu-profiler', }, this.jsCpuProfilerRow! ); diff --git a/ide/src/trace/component/chart/SpBpftraceChart.ts b/ide/src/trace/component/chart/SpBpftraceChart.ts index 19fdd265b9141989d0845e152f01f6231c420937..70b6e04f8c1f8b69258e78bf12ab36cb99833cc4 100644 --- a/ide/src/trace/component/chart/SpBpftraceChart.ts +++ b/ide/src/trace/component/chart/SpBpftraceChart.ts @@ -18,6 +18,7 @@ import { TraceRow } from '../trace/base/TraceRow'; import { renders } from '../../database/ui-worker/ProcedureWorker'; import { SampleStruct, SampleRender } from '../../database/ui-worker/ProcedureWorkerBpftrace'; import { queryStartTime } from '../../database/sql/SqlLite.sql'; +import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; export class SpBpftraceChart { private trace: SpSystemTrace; @@ -168,6 +169,10 @@ export class SpBpftraceChart { document.dispatchEvent( new CustomEvent('file-correct') ) + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'bpftrace', + action: 'bpftrace', + }); } catch (error) { document.dispatchEvent( new CustomEvent('file-error') diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index a89d811c713db2b4654f3c2e9d07b2dad30fc025..6c7ef0c58d01883626def53409716dfdec3bcac0 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -18,7 +18,7 @@ import { SpHiPerf } from './SpHiPerf'; import { SpCpuChart } from './SpCpuChart'; import { SpFreqChart } from './SpFreqChart'; import { SpFpsChart } from './SpFpsChart'; -import { info, log } from '../../../log/Log'; +import { info } from '../../../log/Log'; import { SpNativeMemoryChart } from './SpNativeMemoryChart'; import { SpAbilityMonitorChart } from './SpAbilityMonitorChart'; import { SpProcessChart } from './SpProcessChart'; @@ -46,13 +46,14 @@ import { SpSegmentationChart } from './SpSegmentationChart'; import { queryAppStartupProcessIds, queryDataDICT, - queryThreadAndProcessName + queryThreadAndProcessName, } from '../../database/sql/ProcessThread.sql'; import { queryTaskPoolCallStack, queryTotalTime } from '../../database/sql/SqlLite.sql'; import { getCpuUtilizationRate } from '../../database/sql/Cpu.sql'; import { queryMemoryConfig } from '../../database/sql/Memory.sql'; import { SpLtpoChart } from './SpLTPO'; import { SpBpftraceChart } from './SpBpftraceChart'; +import { sliceSender } from '../../database/data-trafic/SliceSender'; export class SpChartManager { static APP_STARTUP_PID_ARR: Array = []; @@ -106,9 +107,7 @@ export class SpChartManager { this.spSegmentationChart = new SpSegmentationChart(trace); this.spBpftraceChart = new SpBpftraceChart(trace); } - - async init(progress: Function) { - info('initData data parse end '); + async initPreprocessData(progress: Function): Promise { progress('load data dict', 50); SpSystemTrace.DATA_DICT.clear(); SpChartManager.APP_STARTUP_PID_ARR = []; @@ -128,14 +127,16 @@ export class SpChartManager { let ptArr = await queryThreadAndProcessName(); this.handleProcessThread(ptArr); info('initData timerShaftEL Data initialized'); + } + + async initCpu(progress: Function): Promise { progress('cpu', 70); - await this.cpu.init(); + let count = await sliceSender(); + await this.cpu.init(count.cpu); info('initData cpu Data initialized'); if (FlagsConfig.getFlagsConfigEnableStatus('Bpftrace')) { await this.spBpftraceChart.init(null); } - progress('process/thread state', 73); - await this.cpu.initProcessThreadStateData(progress); if (FlagsConfig.getFlagsConfigEnableStatus('SchedulingAnalysis')) { await this.cpu.initCpuIdle0Data(progress); await this.cpu.initSchedulingPTData(progress); @@ -148,67 +149,56 @@ export class SpChartManager { progress('cpu freq', 80); await this.freq.init(); info('initData Cpu Freq Data initialized'); + } + + async init(progress: Function): Promise { + info('initData data parse end '); + await this.initPreprocessData(progress); + await this.initCpu(progress); await this.logChart.init(); - info('initData logChart Data initialized'); await this.spHiSysEvent.init(); - info('initData HiSysEvent Data initialized'); progress('Clock init', 82); await this.clockChart.init(); - info('initData Clock Data initialized'); progress('Irq init', 84); await this.irqChart.init(); - info('initData Irq Data initialized'); progress('SpSegmentationChart inin', 84.5); await this.spSegmentationChart.init(); - info('initData Segmentation initialized'); await this.virtualMemChart.init(); - info('initData virtualMemChart initialized'); progress('fps', 85); await this.fps.init(); - info('initData FPS Data initialized'); progress('native memory', 87); await this.nativeMemory.initChart(); - info('initData Native Memory Data initialized'); progress('ability monitor', 88); await this.abilityMonitor.init(); - info('initData abilityMonitor Data initialized'); progress('hiSysevent', 88.2); await this.hiSyseventChart.init(); - info('initData Energy Data initialized'); progress('vm tracker', 88.4); await this.smapsChart.init(); - info('initData vm tracker Data initialized'); progress('sdk', 88.6); await this.sdkChart.init(); - info('initData sdk Data initialized'); progress('perf', 88.8); await this.perf!.init(); await perfDataQuery.initPerfCache(); - info('initData perf Data initialized'); progress('file system', 89); await this.fileSystem!.init(); - info('initData file system initialized'); progress('ark ts', 90); await this.arkTsChart.initFolder(); - info('initData ark ts initialized'); await this.spAllAppStartupsChart.init(); await this.SpLtpoChart.init(); await this.frameTimeChart.init(); - info('initData frameTimeLine initialized'); progress('process', 92); await this.process.initAsyncFuncData(); await this.process.initDeliverInputEvent(); await this.process.init(); - info('initData Process Data initialized'); progress('display', 95); } - async initSample(ev: File) { + async initSample(ev: File): Promise { await this.initSampleTime(); await this.spBpftraceChart.init(ev); } - async importSoFileUpdate() { + async importSoFileUpdate(): Promise { SpSystemTrace.DATA_DICT.clear(); let dict = await queryDataDICT(); dict.map((d) => SpSystemTrace.DATA_DICT.set(d['id'], d['data'])); @@ -219,7 +209,7 @@ export class SpChartManager { this.perf.resetAllChartData(); } - handleProcessThread(arr: { id: number; name: string; type: string }[]) { + handleProcessThread(arr: { id: number; name: string; type: string }[]): void { Utils.PROCESS_MAP.clear(); Utils.THREAD_MAP.clear(); for (let pt of arr) { @@ -231,7 +221,7 @@ export class SpChartManager { } } - initTotalTime = async () => { + initTotalTime = async (): Promise => { let res = await queryTotalTime(); if (this.trace.timerShaftEL) { let total = res[0].total; @@ -251,7 +241,7 @@ export class SpChartManager { } }; - initSampleTime = async () => { + initSampleTime = async (): Promise => { if (this.trace.timerShaftEL) { let total = 30_000_000_000; let startNS = 0; @@ -266,9 +256,11 @@ export class SpChartManager { } }; - initCpuRate = async () => { + initCpuRate = async (): Promise => { let rates = await getCpuUtilizationRate(0, this.trace.timerShaftEL?.totalNS || 0); - if (this.trace.timerShaftEL) this.trace.timerShaftEL.cpuUsage = rates; + if (this.trace.timerShaftEL) { + this.trace.timerShaftEL.cpuUsage = rates; + } info('Cpu UtilizationRate data size is: ', rates.length); }; @@ -286,9 +278,9 @@ export class SpChartManager { procedurePool.submitWithName( 'logic0', 'cache-data-dict', - {dataDict: SpSystemTrace.DATA_DICT}, + { dataDict: SpSystemTrace.DATA_DICT }, undefined, - (res: any) => { + (res: any): void => { resolve(); } ); @@ -296,11 +288,11 @@ export class SpChartManager { } } -export const FolderSupplier = () => { +export const folderSupplier = (): any => { return () => new Promise>((resolve) => resolve([])); }; -export const FolderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => { - return (useCache: boolean) => { +export const folderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => { + return (useCache: boolean): void => { row.canvasSave(trace.canvasPanelCtx!); if (row.expansion) { trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); @@ -309,7 +301,7 @@ export const FolderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => { context: trace.canvasPanelCtx, useCache: useCache, - type: ``, + type: '', }, row ); @@ -317,3 +309,30 @@ export const FolderThreadHandler = (row: TraceRow, trace: SpSystemTrace) => row.canvasRestore(trace.canvasPanelCtx!, trace); }; }; + +export function rowThreadHandler( + tag: string, + contextField: string, + arg: any, + row: TraceRow, + trace: SpSystemTrace +) { + return (useCache: boolean) => { + let context: CanvasRenderingContext2D = getRowContext(row, trace); + row.canvasSave(context); + arg.useCache = useCache; + if (contextField) { + arg[contextField] = context; + } + (renders[tag] as any).renderMainThread(arg, row); + row.canvasRestore(context, trace); + }; +} + +export const getRowContext = (row: TraceRow, trace: SpSystemTrace): CanvasRenderingContext2D => { + if (row.currentContext) { + return row.currentContext; + } else { + return row.collect ? trace.canvasFavoritePanelCtx! : trace.canvasPanelCtx!; + } +}; diff --git a/ide/src/trace/component/chart/SpClockChart.ts b/ide/src/trace/component/chart/SpClockChart.ts index 8ad47f6d1e62d885a2b5e8f657ec6cc89c21aa26..70dd584f2d9bd57bd62d5337d9513b71b938d73c 100644 --- a/ide/src/trace/component/chart/SpClockChart.ts +++ b/ide/src/trace/component/chart/SpClockChart.ts @@ -22,7 +22,7 @@ import { ColorUtils } from '../trace/base/ColorUtils'; import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { Utils } from '../trace/base/Utils'; import { clockDataSender } from '../../database/data-trafic/ClockDataSender'; -import {queryClockData} from "../../database/sql/Clock.sql"; +import { queryClockData } from '../../database/sql/Clock.sql'; export class SpClockChart { private trace: SpSystemTrace; @@ -31,15 +31,92 @@ export class SpClockChart { this.trace = trace; } - async init() { + async init(): Promise { let folder = await this.initFolder(); await this.initData(folder); } - async initData(folder: TraceRow) { + private clockSupplierFrame( + traceRow: TraceRow, + it: { + name: string; + num: number; + srcname: string; + }, + isState: boolean, + isScreenState: boolean, + maxValue: number + ): void { + traceRow.supplierFrame = (): Promise => { + let promiseData = null; + if (it.name.endsWith(' Frequency')) { + promiseData = clockDataSender(it.srcname, 'clockFrequency', traceRow); + } else if (isState) { + promiseData = clockDataSender(it.srcname, 'clockState', traceRow); + } else if (isScreenState) { + promiseData = clockDataSender('', 'screenState', traceRow); + } + if (promiseData === null) { + return new Promise>((resolve) => resolve([])); + } else { + return promiseData.then((resultClock: Array) => { + for (let j = 0; j < resultClock.length; j++) { + resultClock[j].type = 'measure'; + if ((resultClock[j].value || 0) > maxValue) { + maxValue = resultClock[j].value || 0; + } + if (j > 0) { + resultClock[j].delta = (resultClock[j].value || 0) - (resultClock[j - 1].value || 0); + } else { + resultClock[j].delta = 0; + } + } + return resultClock; + }); + } + }; + } + + private clockThreadHandler( + traceRow: TraceRow, + it: { + name: string; + num: number; + srcname: string; + }, + isState: boolean, + isScreenState: boolean, + maxValue: number, + clockId: number + ): void { + traceRow.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D; + if (traceRow.currentContext) { + context = traceRow.currentContext; + } else { + context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + traceRow.canvasSave(context); + (renders['clock'] as ClockRender).renderMainThread( + { + context: context, + useCache: useCache, + type: it.name, + maxValue: maxValue === 0 ? 1 : maxValue, + index: clockId, + maxName: + isState || isScreenState ? maxValue.toString() : Utils.getFrequencyWithUnit(maxValue / 1000).maxFreqName, + }, + traceRow + ); + traceRow.canvasRestore(context, this.trace); + }; + } + + async initData(folder: TraceRow): Promise { let clockStartTime = new Date().getTime(); let clockList = await queryClockData(); - if (clockList.length == 0) { + if (clockList.length === 0) { return; } info('clockList data size is: ', clockList!.length); @@ -60,34 +137,7 @@ export class SpClockChart { traceRow.setAttribute('children', ''); traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; - traceRow.supplierFrame = () => { - let promiseData = null; - if (it.name.endsWith(' Frequency')) { - promiseData = clockDataSender(it.srcname, 'clockFrequency', traceRow); - } else if (isState) { - promiseData = clockDataSender(it.srcname, 'clockState', traceRow); - } else if (isScreenState) { - promiseData = clockDataSender('', 'screenState', traceRow); - } - if (promiseData == null) { - return new Promise>((resolve) => resolve([])); - } else { - return promiseData.then((resultClock: Array) => { - for (let j = 0; j < resultClock.length; j++) { - resultClock[j].type = 'measure'; - if ((resultClock[j].value || 0) > maxValue) { - maxValue = resultClock[j].value || 0; - } - if (j > 0) { - resultClock[j].delta = (resultClock[j].value || 0) - (resultClock[j - 1].value || 0); - } else { - resultClock[j].delta = 0; - } - } - return resultClock; - }); - } - }; + this.clockSupplierFrame(traceRow, it, isState, isScreenState, maxValue); traceRow.getCacheData = (args: any): Promise> | undefined => { if (it.name.endsWith(' Frequency')) { return clockDataSender(it.srcname, 'clockFrequency', traceRow, args); @@ -97,38 +147,17 @@ export class SpClockChart { return clockDataSender('', 'screenState', traceRow, args); } }; - traceRow.focusHandler = (ev) => { + traceRow.focusHandler = (ev): void => { this.trace?.displayTip( traceRow, ClockStruct.hoverClockStruct, `${ColorUtils.formatNumberComma(ClockStruct.hoverClockStruct?.value!)}` ); }; - traceRow.findHoverStruct = () => { + traceRow.findHoverStruct = (): void => { ClockStruct.hoverClockStruct = traceRow.getHoverStruct(); }; - traceRow.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (traceRow.currentContext) { - context = traceRow.currentContext; - } else { - context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - traceRow.canvasSave(context); - (renders['clock'] as ClockRender).renderMainThread( - { - context: context, - useCache: useCache, - type: it.name, - maxValue: maxValue === 0 ? 1 : maxValue, - index: i, - maxName: - isState || isScreenState ? maxValue.toString() : Utils.getFrequencyWithUnit(maxValue / 1000).maxFreqName, - }, - traceRow - ); - traceRow.canvasRestore(context, this.trace); - }; + this.clockThreadHandler(traceRow, it, isState, isScreenState, maxValue, i); folder.addChildTraceRow(traceRow); } let durTime = new Date().getTime() - clockStartTime; @@ -137,17 +166,17 @@ export class SpClockChart { async initFolder(): Promise> { let clockFolder = TraceRow.skeleton(); - clockFolder.rowId = `Clocks`; + clockFolder.rowId = 'Clocks'; clockFolder.index = 0; clockFolder.rowType = TraceRow.ROW_TYPE_CLOCK_GROUP; clockFolder.rowParentId = ''; clockFolder.style.height = '40px'; clockFolder.folder = true; - clockFolder.name = `Clocks`; /* & I/O Latency */ + clockFolder.name = 'Clocks'; clockFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; clockFolder.selectChangeHandler = this.trace.selectChangeHandler; - clockFolder.supplier = () => new Promise>((resolve) => resolve([])); - clockFolder.onThreadHandler = (useCache) => { + clockFolder.supplier = (): Promise => new Promise>((resolve) => resolve([])); + clockFolder.onThreadHandler = (useCache): void => { clockFolder.canvasSave(this.trace.canvasPanelCtx!); if (clockFolder.expansion) { this.trace.canvasPanelCtx?.clearRect(0, 0, clockFolder.frame.width, clockFolder.frame.height); @@ -156,7 +185,7 @@ export class SpClockChart { { context: this.trace.canvasPanelCtx, useCache: useCache, - type: ``, + type: '', }, clockFolder ); diff --git a/ide/src/trace/component/chart/SpCpuChart.ts b/ide/src/trace/component/chart/SpCpuChart.ts index c00df099dc17c7ae98f8b828ec78b41c79979021..aeb6de6a54052598e46208003988e1abd43bfa1f 100644 --- a/ide/src/trace/component/chart/SpCpuChart.ts +++ b/ide/src/trace/component/chart/SpCpuChart.ts @@ -21,9 +21,7 @@ import { CpuRender, CpuStruct } from '../../database/ui-worker/cpu/ProcedureWork import { renders } from '../../database/ui-worker/ProcedureWorker'; import { Utils } from '../trace/base/Utils'; import { cpuDataSender } from '../../database/data-trafic/CpuDataSender'; -import { TraficEnum } from '../../database/data-trafic/utils/QueryEnum'; -import {cpuList} from "../../database/data-trafic/utils/AllMemoryCache"; -import {queryCpuCount, queryCpuDataCount, queryCpuMax, queryCpuSchedSlice} from "../../database/sql/Cpu.sql"; +import { queryCpuCount, queryCpuMax, queryCpuSchedSlice } from '../../database/sql/Cpu.sql'; export class SpCpuChart { private trace: SpSystemTrace; @@ -32,7 +30,53 @@ export class SpCpuChart { this.trace = trace; } - async init() { + private cpuSupplierFrame(traceRow: TraceRow, cpuId: number): void { + traceRow.supplierFrame = async (): Promise => { + const res = await cpuDataSender(cpuId, traceRow); + const filterList = SpSystemTrace.keyPathList.filter((item) => { + return item.cpu === cpuId; + }); + res.push(...filterList); + res.forEach((it, i, arr) => { + let p = Utils.PROCESS_MAP.get(it.processId!); + let t = Utils.THREAD_MAP.get(it.tid!); + let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); + if (slice) { + it.end_state = slice.endState; + it.priority = slice.priority; + } + it.processName = p; + it.processCmdLine = p; + it.name = t; + it.type = 'thread'; + }); + return res; + }; + } + + private cpuThreadHandler(traceRow: TraceRow, i1: number): void { + traceRow.onThreadHandler = (useCache: boolean, buf: ArrayBuffer | undefined | null): void => { + let context: CanvasRenderingContext2D; + if (traceRow.currentContext) { + context = traceRow.currentContext; + } else { + context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + traceRow.canvasSave(context); + (renders['cpu-data'] as CpuRender).renderMainThread( + { + ctx: context, + useCache: useCache, + type: `cpu-data-${i1}`, + translateY: traceRow.translateY, + }, + traceRow + ); + traceRow.canvasRestore(context, this.trace); + }; + } + + async init(cpuDataCount?: Map): Promise { let CpuStartTime = new Date().getTime(); let array = await queryCpuMax(); let cpuCountResult = await queryCpuCount(); @@ -41,7 +85,6 @@ export class SpCpuChart { } else { (window as any).cpuCount = 0; } - let dataCount: { count: number; cpu: number }[] = (await queryCpuDataCount()) as { count: number; cpu: number }[]; let cpuSchedSlice = await queryCpuSchedSlice(); this.initSchedSliceData(cpuSchedSlice); info('Cpu trace row data size is: ', array.length); @@ -49,7 +92,7 @@ export class SpCpuChart { let cpuMax = array[0].cpu; CpuStruct.cpuCount = cpuMax + 1; for (let i1 = 0; i1 < CpuStruct.cpuCount; i1++) { - if (dataCount.find((it) => it.cpu === i1 && it.count > 0)) { + if (cpuDataCount && (cpuDataCount.get(i1) || 0) > 0) { const cpuId = i1; let traceRow = TraceRow.skeleton(); traceRow.rowId = `${cpuId}`; @@ -59,29 +102,8 @@ export class SpCpuChart { traceRow.name = `Cpu ${cpuId}`; traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; traceRow.selectChangeHandler = this.trace.selectChangeHandler; - traceRow.supplierFrame = () => { - return cpuDataSender(cpuId, traceRow).then((res) => { - const filterList = SpSystemTrace.keyPathList.filter((item) => { - return item.cpu === cpuId; - }); - res.push(...filterList); - res.forEach((it, i, arr) => { - let p = Utils.PROCESS_MAP.get(it.processId!); - let t = Utils.THREAD_MAP.get(it.tid!); - let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`); - if (slice) { - it.end_state = slice.endState; - it.priority = slice.priority; - } - it.processName = p; - it.processCmdLine = p; - it.name = t; - it.type = 'thread'; - }); - return res; - }); - }; - traceRow.focusHandler = () => { + this.cpuSupplierFrame(traceRow, cpuId); + traceRow.focusHandler = (): void => { this.trace?.displayTip( traceRow, CpuStruct.hoverCpuStruct, @@ -92,28 +114,10 @@ export class SpCpuChart { }]` ); }; - traceRow.findHoverStruct = () => { + traceRow.findHoverStruct = (): void => { CpuStruct.hoverCpuStruct = traceRow.getHoverStruct(); }; - traceRow.onThreadHandler = (useCache: boolean, buf: ArrayBuffer | undefined | null) => { - let context: CanvasRenderingContext2D; - if (traceRow.currentContext) { - context = traceRow.currentContext; - } else { - context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - traceRow.canvasSave(context); - (renders['cpu-data'] as CpuRender).renderMainThread( - { - ctx: context, - useCache: useCache, - type: `cpu-data-${i1}`, - translateY: traceRow.translateY, - }, - traceRow - ); - traceRow.canvasRestore(context, this.trace); - }; + this.cpuThreadHandler(traceRow, i1); this.trace.rowsEL?.appendChild(traceRow); } } @@ -122,7 +126,7 @@ export class SpCpuChart { info('The time to load the Cpu data is: ', CpuDurTime); } - initProcessThreadStateData = async (progress: Function) => { + initProcessThreadStateData = async (progress: Function): Promise => { let time = new Date().getTime(); progress('StateProcessThread', 93); procedurePool.submitWithName('logic0', 'spt-init', {}, undefined, (res: any) => {}); @@ -130,7 +134,7 @@ export class SpCpuChart { info('The time to load the first ProcessThreadState data is: ', durTime); }; - initCpuIdle0Data = async (progress: Function) => { + initCpuIdle0Data = async (progress: Function): Promise => { let time = new Date().getTime(); progress('CPU Idle', 94); procedurePool.submitWithName( @@ -147,14 +151,14 @@ export class SpCpuChart { info('The time to load the first CPU Idle0 data is: ', durTime); }; - initSchedSliceData(arr: any[]) { + initSchedSliceData(arr: any[]): void { Utils.SCHED_SLICE_MAP.clear(); arr.forEach((value) => { Utils.SCHED_SLICE_MAP.set(`${value.itid}-${value.ts}`, { endState: value.endState, priority: value.priority }); }); } - initSchedulingPTData = async (progress: Function) => { + initSchedulingPTData = async (progress: Function): Promise => { let time = new Date().getTime(); progress('CPU Idle', 94); procedurePool.submitWithName('logic0', 'scheduling-getProcessAndThread', {}, undefined, (res: any) => {}); @@ -162,7 +166,7 @@ export class SpCpuChart { info('The time to load the first CPU Idle0 data is: ', durTime); }; - initSchedulingFreqData = async (progress: Function) => { + initSchedulingFreqData = async (progress: Function): Promise => { let time = new Date().getTime(); progress('CPU Scheduling Freq', 94); procedurePool.submitWithName('logic0', 'scheduling-initFreqData', {}, undefined, (res: any) => {}); diff --git a/ide/src/trace/component/chart/SpEBPFChart.ts b/ide/src/trace/component/chart/SpEBPFChart.ts index 7527a52a0e696bcda1fd89706b8b7f4280e456b0..4d0e772967aef3c0ac2d05cd3a12309b42ccd23d 100644 --- a/ide/src/trace/component/chart/SpEBPFChart.ts +++ b/ide/src/trace/component/chart/SpEBPFChart.ts @@ -32,7 +32,7 @@ export class SpEBPFChart { this.trace = trace; } - async init() { + async init(): Promise { let sys = await hasFileSysData(); if (sys.length > 0) { let fsCount = sys[0]['fsCount'] ?? 0; @@ -56,7 +56,7 @@ export class SpEBPFChart { } } - async initFileCallchain() { + async initFileCallchain(): Promise { return new Promise((resolve, reject) => { procedurePool.submitWithName('logic0', 'fileSystem-init', null, undefined, (res: any) => { resolve(res); @@ -66,18 +66,18 @@ export class SpEBPFChart { async initFolder(): Promise> { let fsFolder = TraceRow.skeleton(); - fsFolder.rowId = `FileSystem`; + fsFolder.rowId = 'FileSystem'; fsFolder.index = 0; fsFolder.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM_GROUP; fsFolder.rowParentId = ''; fsFolder.style.height = '40px'; fsFolder.folder = true; - fsFolder.name = `EBPF`; /* & I/O Latency */ + fsFolder.name = 'EBPF'; /* & I/O Latency */ fsFolder.addTemplateTypes('HiEBpf'); fsFolder.favoriteChangeHandler = this.trace.favoriteChangeHandler; fsFolder.selectChangeHandler = this.trace.selectChangeHandler; - fsFolder.supplierFrame = () => new Promise>((resolve) => resolve([])); - fsFolder.onThreadHandler = (useCache) => { + fsFolder.supplierFrame = (): Promise> => new Promise>((resolve) => resolve([])); + fsFolder.onThreadHandler = (useCache): void => { fsFolder.canvasSave(this.trace.canvasPanelCtx!); if (fsFolder.expansion) { this.trace.canvasPanelCtx?.clearRect(0, 0, fsFolder.frame.width, fsFolder.frame.height); @@ -86,7 +86,7 @@ export class SpEBPFChart { { context: this.trace.canvasPanelCtx, useCache: useCache, - type: ``, + type: '', }, fsFolder ); @@ -97,28 +97,27 @@ export class SpEBPFChart { return fsFolder; } - async initLogicalRead(folder: TraceRow) { + async initLogicalRead(folder: TraceRow): Promise { let logicalReadRow = TraceRow.skeleton(); - logicalReadRow.rowId = `FileSystemLogicalRead`; + logicalReadRow.rowId = 'FileSystemLogicalRead'; logicalReadRow.index = 1; logicalReadRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; logicalReadRow.rowParentId = folder.rowId; logicalReadRow.rowHidden = !folder.expansion; logicalReadRow.style.height = '40px'; logicalReadRow.setAttribute('children', ''); - logicalReadRow.name = `FileSystem Logical Read`; - logicalReadRow.supplierFrame = () => { - return fileSystemSender(2, TraceRow.range?.scale || 50, logicalReadRow).then((res: Array) => { - return res; - }); + logicalReadRow.name = 'FileSystem Logical Read'; + logicalReadRow.supplierFrame = async (): Promise => { + const res = await fileSystemSender(2, TraceRow.range?.scale || 50, logicalReadRow); + return res; }; logicalReadRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; logicalReadRow.selectChangeHandler = this.trace.selectChangeHandler; - logicalReadRow.focusHandler = () => this.focusHandler(logicalReadRow); - logicalReadRow.findHoverStruct = () => { + logicalReadRow.focusHandler = (): void => this.focusHandler(logicalReadRow); + logicalReadRow.findHoverStruct = (): void => { EBPFChartStruct.hoverEBPFStruct = logicalReadRow.getHoverStruct(false); }; - logicalReadRow.onThreadHandler = (useCache) => { + logicalReadRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (logicalReadRow.currentContext) { context = logicalReadRow.currentContext; @@ -140,28 +139,27 @@ export class SpEBPFChart { folder.addChildTraceRow(logicalReadRow); } - async initLogicalWrite(folder: TraceRow) { + async initLogicalWrite(folder: TraceRow): Promise { let logicalWriteRow = TraceRow.skeleton(); - logicalWriteRow.rowId = `FileSystemLogicalWrite`; + logicalWriteRow.rowId = 'FileSystemLogicalWrite'; logicalWriteRow.index = 2; logicalWriteRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; logicalWriteRow.rowParentId = folder.rowId; logicalWriteRow.rowHidden = !folder.expansion; logicalWriteRow.style.height = '40px'; logicalWriteRow.setAttribute('children', ''); - logicalWriteRow.name = `FileSystem Logical Write`; - logicalWriteRow.supplierFrame = () => { - return fileSystemSender(3, TraceRow.range?.scale || 50, logicalWriteRow).then((res: Array) => { - return res; - }); + logicalWriteRow.name = 'FileSystem Logical Write'; + logicalWriteRow.supplierFrame = async (): Promise => { + const res = await fileSystemSender(3, TraceRow.range?.scale || 50, logicalWriteRow); + return res; }; logicalWriteRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; logicalWriteRow.selectChangeHandler = this.trace.selectChangeHandler; - logicalWriteRow.focusHandler = () => this.focusHandler(logicalWriteRow); - logicalWriteRow.findHoverStruct = () => { + logicalWriteRow.focusHandler = (): void => this.focusHandler(logicalWriteRow); + logicalWriteRow.findHoverStruct = (): void => { EBPFChartStruct.hoverEBPFStruct = logicalWriteRow.getHoverStruct(false); }; - logicalWriteRow.onThreadHandler = (useCache) => { + logicalWriteRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (logicalWriteRow.currentContext) { context = logicalWriteRow.currentContext; @@ -183,31 +181,28 @@ export class SpEBPFChart { folder.addChildTraceRow(logicalWriteRow); } - async initDiskIOLatency(folder: TraceRow) { + async initDiskIOLatency(folder: TraceRow): Promise { let diskIoRow = TraceRow.skeleton(); - diskIoRow.rowId = `FileSystemDiskIOLatency`; + diskIoRow.rowId = 'FileSystemDiskIOLatency'; diskIoRow.index = 4; diskIoRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; diskIoRow.rowParentId = folder.rowId; diskIoRow.rowHidden = !folder.expansion; diskIoRow.style.height = '40px'; - diskIoRow.style.width = `100%`; + diskIoRow.style.width = '100%'; diskIoRow.setAttribute('children', ''); - diskIoRow.name = `Disk I/O Latency`; - diskIoRow.supplierFrame = () => { - return diskIoSender(true, 0, [1, 2, 3, 4], TraceRow.range?.scale || 50, diskIoRow).then( - (res: Array) => { - return res; - } - ); + diskIoRow.name = 'Disk I/O Latency'; + diskIoRow.supplierFrame = async (): Promise => { + const res = await diskIoSender(true, 0, [1, 2, 3, 4], TraceRow.range?.scale || 50, diskIoRow); + return res; }; diskIoRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; diskIoRow.selectChangeHandler = this.trace.selectChangeHandler; - diskIoRow.focusHandler = () => this.focusHandler(diskIoRow); - diskIoRow.findHoverStruct = () => { + diskIoRow.focusHandler = (): void => this.focusHandler(diskIoRow); + diskIoRow.findHoverStruct = (): void => { EBPFChartStruct.hoverEBPFStruct = diskIoRow.getHoverStruct(false); }; - diskIoRow.onThreadHandler = (useCache) => { + diskIoRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (diskIoRow.currentContext) { context = diskIoRow.currentContext; @@ -229,123 +224,126 @@ export class SpEBPFChart { folder.addChildTraceRow(diskIoRow); } - async initProcessDiskIOLatency(folder: TraceRow) { + initProcessDiskIOLatencyRead(i: number, folder: TraceRow, process: any): TraceRow { + let rowRead = TraceRow.skeleton(); + rowRead.index = 5 + 2 * i; + rowRead.rowId = `FileSystemDiskIOLatency-read-${process['ipid']}`; + rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; + rowRead.rowParentId = folder.rowId; + rowRead.rowHidden = !folder.expansion; + rowRead.style.height = '40px'; + rowRead.style.width = '100%'; + rowRead.setAttribute('children', ''); + rowRead.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Read Latency`; + rowRead.supplierFrame = async (): Promise => { + const res = await diskIoSender(false, process['ipid'], [1, 3], TraceRow.range?.scale || 50, rowRead); + return res; + }; + rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler; + rowRead.selectChangeHandler = this.trace.selectChangeHandler; + rowRead.focusHandler = (): void => this.focusHandler(rowRead); + rowRead.findHoverStruct = (): void => { + EBPFChartStruct.hoverEBPFStruct = rowRead.getHoverStruct(false); + }; + rowRead.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D; + if (rowRead.currentContext) { + context = rowRead.currentContext; + } else { + context = rowRead.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + rowRead.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process['pid']}`, + chartColor: ColorUtils.MD_PALETTE[0], + }, + rowRead + ); + rowRead.canvasRestore(context, this.trace); + }; + return rowRead; + } + + private initProcessDiskIOLatencyWrite(i: number, folder: TraceRow, process: any): TraceRow { + let rowWrite = TraceRow.skeleton(); + rowWrite.index = 5 + 2 * i + 1; + rowWrite.rowId = `FileSystemDiskIOLatency-write-${process['ipid']}`; + rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; + rowWrite.rowParentId = folder.rowId; + rowWrite.rowHidden = !folder.expansion; + rowWrite.style.height = '40px'; + rowWrite.style.width = '100%'; + rowWrite.setAttribute('children', ''); + rowWrite.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Write Latency`; + rowWrite.supplierFrame = async (): Promise => { + const res = await diskIoSender(false, process['ipid'], [2, 4], TraceRow.range?.scale || 50, rowWrite); + return res; + }; + rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler; + rowWrite.selectChangeHandler = this.trace.selectChangeHandler; + rowWrite.focusHandler = (): void => this.focusHandler(rowWrite); + rowWrite.findHoverStruct = (): void => { + EBPFChartStruct.hoverEBPFStruct = rowWrite.getHoverStruct(false); + }; + rowWrite.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D; + if (rowWrite.currentContext) { + context = rowWrite.currentContext; + } else { + context = rowWrite.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + } + rowWrite.canvasSave(context); + (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread( + { + context: context, + useCache: useCache, + type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process['pid']}`, + chartColor: ColorUtils.MD_PALETTE[8], + }, + rowWrite + ); + rowWrite.canvasRestore(context, this.trace); + }; + return rowWrite; + } + + async initProcessDiskIOLatency(folder: TraceRow):Promise { let processes = (await getDiskIOProcess()) || []; for (let i = 0, len = processes.length; i < len; i++) { let process = processes[i]; - let rowRead = TraceRow.skeleton(); - rowRead.index = 5 + 2 * i; - rowRead.rowId = `FileSystemDiskIOLatency-read-${process['ipid']}`; - rowRead.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; - rowRead.rowParentId = folder.rowId; - rowRead.rowHidden = !folder.expansion; - rowRead.style.height = '40px'; - rowRead.style.width = `100%`; - rowRead.setAttribute('children', ''); - rowRead.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Read Latency`; - rowRead.supplierFrame = () => { - return diskIoSender(false, process['ipid'], [1, 3], TraceRow.range?.scale || 50, rowRead).then( - (res: Array) => { - return res; - } - ); - }; - rowRead.favoriteChangeHandler = this.trace.favoriteChangeHandler; - rowRead.selectChangeHandler = this.trace.selectChangeHandler; - rowRead.focusHandler = () => this.focusHandler(rowRead); - rowRead.findHoverStruct = () => { - EBPFChartStruct.hoverEBPFStruct = rowRead.getHoverStruct(false); - }; - rowRead.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (rowRead.currentContext) { - context = rowRead.currentContext; - } else { - context = rowRead.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - rowRead.canvasSave(context); - (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-read-${process['pid']}`, - chartColor: ColorUtils.MD_PALETTE[0], - }, - rowRead - ); - rowRead.canvasRestore(context, this.trace); - }; + const rowRead = this.initProcessDiskIOLatencyRead(i, folder, process); folder.addChildTraceRow(rowRead); - let rowWrite = TraceRow.skeleton(); - rowWrite.index = 5 + 2 * i + 1; - rowWrite.rowId = `FileSystemDiskIOLatency-write-${process['ipid']}`; - rowWrite.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; - rowWrite.rowParentId = folder.rowId; - rowWrite.rowHidden = !folder.expansion; - rowWrite.style.height = '40px'; - rowWrite.style.width = `100%`; - rowWrite.setAttribute('children', ''); - rowWrite.name = `${process['name'] ?? 'Process'}(${process['pid']}) Max Write Latency`; - rowWrite.supplierFrame = () => { - return diskIoSender(false, process['ipid'], [2, 4], TraceRow.range?.scale || 50, rowWrite).then( - (res: Array) => { - return res; - } - ); - }; - rowWrite.favoriteChangeHandler = this.trace.favoriteChangeHandler; - rowWrite.selectChangeHandler = this.trace.selectChangeHandler; - rowWrite.focusHandler = () => this.focusHandler(rowWrite); - rowWrite.findHoverStruct = () => { - EBPFChartStruct.hoverEBPFStruct = rowWrite.getHoverStruct(false); - }; - rowWrite.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (rowWrite.currentContext) { - context = rowWrite.currentContext; - } else { - context = rowWrite.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - rowWrite.canvasSave(context); - (renders[TraceRow.ROW_TYPE_FILE_SYSTEM] as EBPFRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `${TraceRow.ROW_TYPE_FILE_SYSTEM}-disk-io-process-write-${process['pid']}`, - chartColor: ColorUtils.MD_PALETTE[8], - }, - rowWrite - ); - rowWrite.canvasRestore(context, this.trace); - }; + const rowWrite = this.initProcessDiskIOLatencyWrite(i, folder, process); folder.addChildTraceRow(rowWrite); } } - async initVirtualMemoryTrace(folder: TraceRow) { + async initVirtualMemoryTrace(folder: TraceRow): Promise { let vmTraceRow = TraceRow.skeleton(); - vmTraceRow.rowId = `FileSystemVirtualMemory`; + vmTraceRow.rowId = 'FileSystemVirtualMemory'; vmTraceRow.index = 3; vmTraceRow.rowType = TraceRow.ROW_TYPE_FILE_SYSTEM; vmTraceRow.rowParentId = folder.rowId; vmTraceRow.rowHidden = !folder.expansion; vmTraceRow.rangeSelect = true; vmTraceRow.style.height = '40px'; - vmTraceRow.style.width = `100%`; + vmTraceRow.style.width = '100%'; vmTraceRow.setAttribute('children', ''); - vmTraceRow.name = `Page Fault Trace`; - vmTraceRow.supplierFrame = () => { - return fileSysVMSender(TraceRow.range?.scale || 50, vmTraceRow).then((res: Array) => { - return res; - }); + vmTraceRow.name = 'Page Fault Trace'; + vmTraceRow.supplierFrame = async (): Promise => { + const res = await fileSysVMSender(TraceRow.range?.scale || 50, vmTraceRow); + return res; }; vmTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; vmTraceRow.selectChangeHandler = this.trace.selectChangeHandler; - vmTraceRow.focusHandler = () => this.focusHandler(vmTraceRow); - vmTraceRow.findHoverStruct = () => { + vmTraceRow.focusHandler = (): void => this.focusHandler(vmTraceRow); + vmTraceRow.findHoverStruct = (): void => { EBPFChartStruct.hoverEBPFStruct = vmTraceRow.getHoverStruct(false, false, 'size'); }; - vmTraceRow.onThreadHandler = (useCache) => { + vmTraceRow.onThreadHandler = (useCache): void => { let context: CanvasRenderingContext2D; if (vmTraceRow.currentContext) { context = vmTraceRow.currentContext; @@ -367,7 +365,7 @@ export class SpEBPFChart { folder.addChildTraceRow(vmTraceRow); } - focusHandler(row: TraceRow) { + focusHandler(row: TraceRow): void { let num = 0; let tip = ''; if (EBPFChartStruct.hoverEBPFStruct) { diff --git a/ide/src/trace/component/chart/SpFrameTimeChart.ts b/ide/src/trace/component/chart/SpFrameTimeChart.ts index 680f8a958fe06109351cae725bd6938521f789bb..b7872e65b82cb83d1a11b97e394caeb2036eaa47 100644 --- a/ide/src/trace/component/chart/SpFrameTimeChart.ts +++ b/ide/src/trace/component/chart/SpFrameTimeChart.ts @@ -28,16 +28,21 @@ import { type AnimationRanges, type DeviceStruct } from '../../bean/FrameCompone import { type EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { TreeItemData } from '../../../base-ui/tree/LitTree'; import { QueryEnum } from '../../database/data-trafic/utils/QueryEnum'; -import { frameAnimationSender, frameDynamicSender, frameSpacingSender } from '../../database/data-trafic/FrameDynamicEffectSender'; +import { + frameAnimationSender, + frameDynamicSender, + frameSpacingSender, +} from '../../database/data-trafic/FrameDynamicEffectSender'; import { frameJanksSender } from '../../database/data-trafic/FrameJanksSender'; import { queryAnimationIdAndNameData, queryAnimationTimeRangeData, queryDynamicIdAndNameData, queryFrameApp, - queryFrameTimeData, queryPhysicalData -} from "../../database/sql/SqlLite.sql"; -import {queryAllProcessNames} from "../../database/sql/ProcessThread.sql"; + queryFrameTimeData, + queryPhysicalData, +} from '../../database/sql/SqlLite.sql'; +import { queryAllProcessNames } from '../../database/sql/ProcessThread.sql'; export class SpFrameTimeChart { private trace: SpSystemTrace; @@ -104,6 +109,28 @@ export class SpFrameTimeChart { return frameTimeLineRow; } + private expectedChartSupplierFrame(expectedTimeLineRow: TraceRow): void { + expectedTimeLineRow.supplierFrame = async (): Promise => { + const res = await frameJanksSender(QueryEnum.FrameExpectedData, expectedTimeLineRow); + let maxDepth: number = 1; + let unitHeight: number = 20; + res.forEach((item) => { + if (item.depth! >= maxDepth) { + maxDepth = item.depth! + 1; + } + item.frame_type = 'frameTime'; + item.cmdline = this.pidToProcessNameMap.get(item.pid!); + item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); + }); + if (expectedTimeLineRow && !expectedTimeLineRow.isComplete && res.length > 0) { + let maxHeight: number = maxDepth * unitHeight; + expectedTimeLineRow.style.height = `${maxHeight}px`; + expectedTimeLineRow.setAttribute('height', `${maxHeight}`); + } + return res; + }; + } + async initExpectedChart(frameTimeLineRow: TraceRow): Promise { let expectedTimeLineRow = TraceRow.skeleton(); expectedTimeLineRow.rowId = 'expected frameTime'; @@ -114,26 +141,7 @@ export class SpFrameTimeChart { expectedTimeLineRow.name = 'Expected Timeline'; expectedTimeLineRow.addTemplateTypes('FrameTimeline'); expectedTimeLineRow.setAttribute('children', ''); - expectedTimeLineRow.supplierFrame = () => { - return frameJanksSender(QueryEnum.FrameExpectedData, expectedTimeLineRow).then((res) => { - let maxDepth: number = 1; - let unitHeight: number = 20; - res.forEach((item) => { - if (item.depth! >= maxDepth) { - maxDepth = item.depth! + 1; - } - item.frame_type = 'frameTime'; - item.cmdline = this.pidToProcessNameMap.get(item.pid!); - item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); - }); - if (expectedTimeLineRow && !expectedTimeLineRow.isComplete && res.length > 0) { - let maxHeight: number = maxDepth * unitHeight; - expectedTimeLineRow.style.height = `${maxHeight}px`; - expectedTimeLineRow.setAttribute('height', `${maxHeight}`); - } - return res; - }); - }; + this.expectedChartSupplierFrame(expectedTimeLineRow); expectedTimeLineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; expectedTimeLineRow.selectChangeHandler = this.trace.selectChangeHandler; expectedTimeLineRow.onThreadHandler = (useCache: boolean): void => { @@ -157,6 +165,29 @@ export class SpFrameTimeChart { frameTimeLineRow.addChildTraceRow(expectedTimeLineRow); } + private actualChartSupplierFrame(row: TraceRow): void { + row.supplierFrame = async (): Promise => { + const res = await frameJanksSender(QueryEnum.FrameActualData, row); + let maxDepth: number = 1; + let unitHeight: number = 20; + res.forEach((item) => { + if (item.depth! >= maxDepth) { + maxDepth = item.depth! + 1; + } + item.frame_type = 'frameTime'; + item.cmdline = this.pidToProcessNameMap.get(item.pid!); + item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); + item.type = '0'; + }); + if (row && !row.isComplete && res.length > 0) { + let maxHeight: number = maxDepth * unitHeight; + row.style.height = `${maxHeight}px`; + row.setAttribute('height', `${maxHeight}`); + } + return res; + }; + } + async initActualChart(frameTimeLineRow: TraceRow): Promise { let actualTimeLineRow = TraceRow.skeleton(); actualTimeLineRow.rowId = 'actual frameTime'; @@ -167,27 +198,7 @@ export class SpFrameTimeChart { actualTimeLineRow.name = 'Actual Timeline'; actualTimeLineRow.addTemplateTypes('FrameTimeline'); actualTimeLineRow.setAttribute('children', ''); - actualTimeLineRow.supplierFrame = () => { - return frameJanksSender(QueryEnum.FrameActualData, actualTimeLineRow).then((res) => { - let maxDepth: number = 1; - let unitHeight: number = 20; - res.forEach((item) => { - if (item.depth! >= maxDepth) { - maxDepth = item.depth! + 1; - } - item.frame_type = 'frameTime'; - item.cmdline = this.pidToProcessNameMap.get(item.pid!); - item.rs_name = this.idToProcessNameMap.get(Number(item.rs_name)!); - item.type = '0'; - }); - if (actualTimeLineRow && !actualTimeLineRow.isComplete && res.length > 0) { - let maxHeight: number = maxDepth * unitHeight; - actualTimeLineRow.style.height = `${maxHeight}px`; - actualTimeLineRow.setAttribute('height', `${maxHeight}`); - } - return res; - }); - }; + this.actualChartSupplierFrame(actualTimeLineRow); actualTimeLineRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; actualTimeLineRow.selectChangeHandler = this.trace.selectChangeHandler; actualTimeLineRow.onThreadHandler = (useCache: boolean): void => { @@ -240,9 +251,9 @@ export class SpFrameTimeChart { if (secondRow !== null) { processRow.addChildTraceRowAfter(frameChart, secondRow); } else if (firstRow !== null) { - processRow.addChildTraceRowAfter(frameChart, firstRow) + processRow.addChildTraceRowAfter(frameChart, firstRow); } else { - processRow.addChildTraceRowSpecifyLocation(frameChart, 0) + processRow.addChildTraceRowSpecifyLocation(frameChart, 0); } let appNameList = await queryDynamicIdAndNameData(); appNameList.forEach((item) => { @@ -250,7 +261,7 @@ export class SpFrameTimeChart { }); let animationRanges = await this.initAnimationChart(processRow, firstRow, secondRow); await this.initDynamicCurveChart(appNameMap, frameChart, currentName, animationRanges); - await this.initFrameSpacing(appNameMap, nameArr, frameChart, currentName, animationRanges); + await this.initFrameSpacing(appNameMap, frameChart, currentName, animationRanges); } } } @@ -298,6 +309,54 @@ export class SpFrameTimeChart { return frameChart; } + private animationChartSupplierFrame( + row: TraceRow, + animationIdNameMap: Map, + animationIdInfoMap: Map + ): void { + const unitIndex: number = 1; + const unitHeight: number = 20; + row.supplierFrame = async (): Promise => { + const result = await frameAnimationSender(row); + let maxDepth = 0; + result.forEach((item) => { + if (`${item.status}` === '1') { + item.status = 'Completion delay'; + } else if (`${item.status}` === '0') { + item.status = 'Response delay'; + } + if (item.depth > maxDepth) { + maxDepth = item.depth; + } + if (animationIdNameMap.has(item.animationId!)) { + item.name = animationIdNameMap.get(item.animationId!); + item.frameInfo = item.status === 'Completion delay' ? animationIdInfoMap.get(item.animationId!) : '0'; + } + }); + let maxHeight: number = (maxDepth + unitIndex) * unitHeight; + row.style.height = `${maxHeight}px`; + row.setAttribute('height', `${maxHeight}`); + return result; + }; + } + private animationThreadHandler(row: TraceRow): void { + row.onThreadHandler = (useCache): void => { + let context: CanvasRenderingContext2D = row!.collect + ? this.trace.canvasFavoritePanelCtx! + : this.trace.canvasPanelCtx!; + row!.canvasSave(context); + (renders.frameAnimation as FrameAnimationRender).renderMainThread( + { + context: context, + useCache: useCache, + type: 'frameAnimation', + }, + row! + ); + row!.canvasRestore(context, this.trace); + }; + } + async initAnimationChart( processRow: TraceRow, firstRow: TraceRow, @@ -305,8 +364,7 @@ export class SpFrameTimeChart { ): Promise { let animationRanges: AnimationRanges[] = []; let frameAnimationRow = TraceRow.skeleton(); - let unitIndex: number = 1; - let unitHeight: number = 20; + frameAnimationRow.rowId = 'Animation'; frameAnimationRow.rowType = TraceRow.ROW_TYPE_FRAME_ANIMATION; frameAnimationRow.rowHidden = !processRow.expansion; @@ -331,54 +389,40 @@ export class SpFrameTimeChart { animationIdNameMap.set(item.id, item.name); animationIdInfoMap.set(item.id, item.info); }); - frameAnimationRow.supplierFrame = () => { - return frameAnimationSender(frameAnimationRow).then((result) => { - let maxDepth = 0; - result.forEach((item) => { - if (item.status == '1') { - item.status = 'Completion delay'; - } else { - item.status = 'Response delay'; - } - if (item.depth > maxDepth) { - maxDepth = item.depth; - } - if (animationIdNameMap.has(item.animationId!)) { - item.name = animationIdNameMap.get(item.animationId!); - item.frameInfo = item.status == 'Completion delay' ? animationIdInfoMap.get(item.animationId!) : '0'; - } - }); - let maxHeight: number = (maxDepth + unitIndex) * unitHeight; - frameAnimationRow.style.height = `${maxHeight}px`; - frameAnimationRow.setAttribute('height', `${maxHeight}`); - return result; - }); - }; + this.animationChartSupplierFrame(frameAnimationRow, animationIdNameMap, animationIdInfoMap); frameAnimationRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; frameAnimationRow.selectChangeHandler = this.trace.selectChangeHandler; - frameAnimationRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D = frameAnimationRow!.collect + this.animationThreadHandler(frameAnimationRow); + if (firstRow !== null) { + processRow.addChildTraceRowBefore(frameAnimationRow, firstRow); + } else if (secondRow !== null) { + processRow.addChildTraceRowBefore(frameAnimationRow, secondRow); + } else { + processRow.addChildTraceRowSpecifyLocation(frameAnimationRow, 0); + } + return animationRanges; + } + + private dynamicCurveChartThreadHandler( + dynamicCurveRow: TraceRow, + animationRanges: AnimationRanges[] + ): void { + dynamicCurveRow.onThreadHandler = (useCache: boolean): void => { + let context: CanvasRenderingContext2D = dynamicCurveRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - frameAnimationRow!.canvasSave(context); - (renders.frameAnimation as FrameAnimationRender).renderMainThread( + dynamicCurveRow!.canvasSave(context); + (renders.frameDynamicCurve as FrameDynamicRender).renderMainThread( { context: context, useCache: useCache, - type: 'frameAnimation', + type: 'dynamicEffectCurve', + animationRanges: animationRanges, }, - frameAnimationRow! + dynamicCurveRow! ); - frameAnimationRow!.canvasRestore(context, this.trace); + dynamicCurveRow!.canvasRestore(context, this.trace); }; - if (firstRow !== null) { - processRow.addChildTraceRowBefore(frameAnimationRow, firstRow); - } else if (secondRow !== null) { - processRow.addChildTraceRowBefore(frameAnimationRow, secondRow) - } else { - processRow.addChildTraceRowSpecifyLocation(frameAnimationRow, 0) - } - return animationRanges; } async initDynamicCurveChart( @@ -408,39 +452,44 @@ export class SpFrameTimeChart { dynamicCurveRow.setAttribute('children', ''); dynamicCurveRow.setAttribute('model-type', systemConfigList[0].name); dynamicCurveRow.setAttribute('model-name', name); - dynamicCurveRow.supplierFrame = () => { - return frameDynamicSender(dynamicCurveRow).then((result) => { - result.forEach((dataItem) => { - if (appNameMap.has(dataItem.id!)) { - dataItem.appName = appNameMap.get(dataItem.id!); - } - }); - return result; + dynamicCurveRow.supplierFrame = async (): Promise => { + const result = await frameDynamicSender(dynamicCurveRow); + result.forEach((dataItem) => { + if (appNameMap.has(dataItem.id!)) { + dataItem.appName = appNameMap.get(dataItem.id!); + } }); + return result; }; dynamicCurveRow.selectChangeHandler = this.trace.selectChangeHandler; - dynamicCurveRow.onThreadHandler = (useCache: boolean): void => { - let context: CanvasRenderingContext2D = dynamicCurveRow!.collect - ? this.trace.canvasFavoritePanelCtx! - : this.trace.canvasPanelCtx!; - dynamicCurveRow!.canvasSave(context); - (renders.frameDynamicCurve as FrameDynamicRender).renderMainThread( + this.dynamicCurveChartThreadHandler(dynamicCurveRow, animationRanges); + frameChart.addChildTraceRow(dynamicCurveRow); + } + + private FrameSpacingThreadHandler( + frameSpacingRow: TraceRow, + animationRanges: AnimationRanges[], + rate: number + ): void { + frameSpacingRow.onThreadHandler = (useCache: boolean): void => { + let context = frameSpacingRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + frameSpacingRow!.canvasSave(context); + (renders.frameSpacing as FrameSpacingRender).renderMainThread( { context: context, useCache: useCache, - type: 'dynamicEffectCurve', + type: 'frame_spacing_slice', + frameRate: rate, animationRanges: animationRanges, }, - dynamicCurveRow! + frameSpacingRow! ); - dynamicCurveRow!.canvasRestore(context, this.trace); + frameSpacingRow!.canvasRestore(context, this.trace); }; - frameChart.addChildTraceRow(dynamicCurveRow); } async initFrameSpacing( appNameMap: Map, - nameArr: { name: string }[], frameChart: TraceRow, name: string, animationRanges: AnimationRanges[] @@ -463,35 +512,20 @@ export class SpFrameTimeChart { let physicalConfigHeight = Number(this.flagConfig!.physicalHeight); let physicalWidth = physicalConfigWidth !== 0 ? physicalConfigWidth : deviceStruct.physicalWidth; let physicalHeight = physicalConfigHeight !== 0 ? physicalConfigHeight : deviceStruct.physicalHeight; - frameSpacingRow.supplierFrame = () => { - return frameSpacingSender(physicalWidth, physicalHeight, frameSpacingRow).then((result) => { - result.forEach((dataItem) => { - if (appNameMap.has(dataItem.id!)) { - dataItem.nameId = appNameMap.get(dataItem.id!); - } - dataItem.physicalWidth = physicalWidth; - dataItem.physicalHeight = physicalHeight; - }); - return result; + frameSpacingRow.supplierFrame = async (): Promise => { + const result = await frameSpacingSender(physicalWidth, physicalHeight, frameSpacingRow); + result.forEach((dataItem) => { + if (appNameMap.has(dataItem.id!)) { + dataItem.nameId = appNameMap.get(dataItem.id!); + } + dataItem.physicalWidth = physicalWidth; + dataItem.physicalHeight = physicalHeight; }); + return result; }; frameSpacingRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; frameSpacingRow.selectChangeHandler = this.trace.selectChangeHandler; - frameSpacingRow.onThreadHandler = (useCache: boolean): void => { - let context = frameSpacingRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - frameSpacingRow!.canvasSave(context); - (renders.frameSpacing as FrameSpacingRender).renderMainThread( - { - context: context, - useCache: useCache, - type: 'frame_spacing_slice', - frameRate: deviceStruct.physicalFrameRate, - animationRanges: animationRanges, - }, - frameSpacingRow! - ); - frameSpacingRow!.canvasRestore(context, this.trace); - }; + this.FrameSpacingThreadHandler(frameSpacingRow, animationRanges, deviceStruct.physicalFrameRate); frameChart.addChildTraceRow(frameSpacingRow); } @@ -526,15 +560,7 @@ export class SpFrameTimeChart { }; } - private frameNoExpandTimeOut( - event: CustomEventInit<{ - expansion: boolean; - rowType: string; - rowId: string; - rowParentId: string; - }>, - frameTimeLineRow: TraceRow - ): number { + private frameNoExpandTimeOut(event: CustomEventInit, frameTimeLineRow: TraceRow): number { if (JankStruct!.selectJankStruct) { JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); } diff --git a/ide/src/trace/component/chart/SpFreqChart.ts b/ide/src/trace/component/chart/SpFreqChart.ts index 72f2488b966fa576757fe71b9081d07718ab60f5..453846f5d40c83fdfaad47616cff5504ce0ab134 100644 --- a/ide/src/trace/component/chart/SpFreqChart.ts +++ b/ide/src/trace/component/chart/SpFreqChart.ts @@ -18,10 +18,9 @@ import { info } from '../../../log/Log'; import { TraceRow } from '../trace/base/TraceRow'; import { ColorUtils } from '../trace/base/ColorUtils'; import { CpuFreqLimitRender, CpuFreqLimitsStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; -import { renders } from '../../database/ui-worker/ProcedureWorker'; import { CpuFreqStruct, FreqRender } from '../../database/ui-worker/ProcedureWorkerFreq'; import { CpuStateRender, CpuStateStruct } from '../../database/ui-worker/cpu/ProcedureWorkerCpuState'; -import { FolderSupplier, FolderThreadHandler } from './SpChartManager'; +import { folderSupplier, folderThreadHandler, getRowContext, rowThreadHandler } from './SpChartManager'; import { Utils } from '../trace/base/Utils'; import { cpuFreqDataSender } from '../../database/data-trafic/cpu/CpuFreqDataSender'; import { cpuStateSender } from '../../database/data-trafic/cpu/CpuStateSender'; @@ -31,8 +30,10 @@ import { getCpuLimitFreqMax, queryCpuFreq, queryCpuMaxFreq, - queryCpuStateFilter -} from "../../database/sql/Cpu.sql"; + queryCpuStateFilter, +} from '../../database/sql/Cpu.sql'; +import { promises } from 'dns'; + export class SpFreqChart { private trace: SpSystemTrace; private folderRow: TraceRow | undefined; @@ -43,220 +44,178 @@ export class SpFreqChart { this.trace = trace; } - async init() { + async init(): Promise { let freqList = await queryCpuFreq(); let cpuStateFilterIds = await queryCpuStateFilter(); + this.trace.stateRowsId = cpuStateFilterIds; let cpuFreqLimits = await getCpuLimitFreqId(); let cpuFreqLimitsMax = await getCpuLimitFreqMax(cpuFreqLimits.map((limit) => limit.maxFilterId).join(',')); if (freqList.length > 0) { - this.folderRow = TraceRow.skeleton(); + this.folderRow = this.createFolderRow(); this.folderRow.rowId = 'Cpu Frequency'; - this.folderRow.rowParentId = ''; this.folderRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_ALL; - this.folderRow.style.height = '40px'; - this.folderRow.style.width = '100%'; this.folderRow.name = 'Cpu Frequency'; - this.folderRow.folder = true; - this.folderRow.rowHidden = this.folderRow!.expansion; - this.folderRow.setAttribute('children', ''); - this.folderRow.supplier = FolderSupplier(); - this.folderRow.onThreadHandler = FolderThreadHandler(this.folderRow, this.trace); this.trace.rowsEL?.appendChild(this.folderRow); - info('Cpu Freq data size is: ', freqList!.length); - let freqMaxList = await queryCpuMaxFreq(); - CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; - let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq); - CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; - CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; - this.trace.stateRowsId = cpuStateFilterIds; - for (let i = 0; i < freqList.length; i++) { - const it = freqList[i]; - let traceRow = TraceRow.skeleton(); - traceRow.rowId = `${it.filterId}`; - traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ; - traceRow.rowParentId = ''; - traceRow.style.height = '40px'; - traceRow.name = `Cpu ${it.cpu} Frequency`; - traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - traceRow.selectChangeHandler = this.trace.selectChangeHandler; - traceRow.supplierFrame = () => { - return cpuFreqDataSender(it.cpu, traceRow); //queryCpuFreqData - }; - traceRow.focusHandler = (ev) => { - this.trace?.displayTip( - traceRow, - CpuFreqStruct.hoverCpuFreqStruct, - `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz` - ); - }; - traceRow.findHoverStruct = () => { - CpuFreqStruct.hoverCpuFreqStruct = traceRow.getHoverStruct(true,false, 'value'); - }; - traceRow.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (traceRow.currentContext) { - context = traceRow.currentContext; - } else { - context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - traceRow.canvasSave(context); - (renders['freq'] as FreqRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `freq${it.cpu}`, - }, - traceRow - ); - traceRow.canvasRestore(context, this.trace); - }; - this.trace.rowsEL?.appendChild(traceRow); - this.folderRow!.addChildTraceRow(traceRow); - } + await this.addFreqRows(freqList); } if (cpuStateFilterIds.length > 0) { - this.folderRowState = TraceRow.skeleton(); + this.folderRowState = this.createFolderRow(); this.folderRowState.rowId = 'Cpu State'; this.folderRowState.rowType = TraceRow.ROW_TYPE_CPU_STATE_ALL; - this.folderRowState.style.height = '40px'; - this.folderRowState.folder = true; - this.folderRowState.style.width = '100%'; - this.folderRowState.rowParentId = ''; this.folderRowState.name = 'Cpu State'; - this.folderRowState.rowHidden = this.folderRowState!.expansion; - this.folderRowState.setAttribute('children', ''); - this.folderRowState.supplier = FolderSupplier(); - this.folderRowState.onThreadHandler = FolderThreadHandler(this.folderRowState, this.trace); this.trace.rowsEL?.appendChild(this.folderRowState); - - for (let it of cpuStateFilterIds) { - let cpuStateRow = TraceRow.skeleton(); - cpuStateRow.rowId = `${it.filterId}`; - cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE; - cpuStateRow.rowParentId = ''; - cpuStateRow.style.height = '40px'; - cpuStateRow.name = `Cpu ${it.cpu} State`; - cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; - cpuStateRow.isHover = true; - cpuStateRow.supplierFrame = () => { - return cpuStateSender(it.filterId, cpuStateRow).then((rs) => { - rs.forEach((t) => { - t.cpu = it.cpu; - }); - return rs; - }); - }; - cpuStateRow.focusHandler = (ev) => { - this.trace.displayTip( - cpuStateRow, - CpuStateStruct.hoverStateStruct, - `State: ${CpuStateStruct.hoverStateStruct?.value}` - ); - }; - cpuStateRow.findHoverStruct = () => { - CpuStateStruct.hoverStateStruct = cpuStateRow.getHoverStruct(); - }; - cpuStateRow.onThreadHandler = (useCache: boolean) => { - let context: CanvasRenderingContext2D; - if (cpuStateRow.currentContext) { - context = cpuStateRow.currentContext; - } else { - context = cpuStateRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - cpuStateRow.canvasSave(context); - (renders['cpu-state'] as CpuStateRender).renderMainThread( - { - cpuStateContext: context, - useCache: useCache, - type: `cpu-state-${it.cpu}`, - cpu: it.cpu, - }, - cpuStateRow - ); - cpuStateRow.canvasRestore(context, this.trace); - }; - this.folderRowState!.addChildTraceRow(cpuStateRow); - } + this.addStateRows(cpuStateFilterIds); } if (cpuFreqLimits.length > 0) { - this.folderRowLimit = TraceRow.skeleton(); + this.folderRowLimit = this.createFolderRow(); this.folderRowLimit.rowId = 'Cpu Freq Limit'; this.folderRowLimit.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMITALL; - this.folderRowLimit.style.height = '40px'; - this.folderRowLimit.rowParentId = ''; - this.folderRowLimit.folder = true; this.folderRowLimit.name = 'Cpu Freq Limit'; - this.folderRowLimit.rowHidden = this.folderRowLimit!.expansion; - this.folderRowLimit.setAttribute('children', ''); - this.folderRowLimit.supplier = FolderSupplier(); - this.folderRowLimit.onThreadHandler = FolderThreadHandler(this.folderRowLimit, this.trace); this.trace.rowsEL?.appendChild(this.folderRowLimit); + this.addFreqLimitRows(cpuFreqLimits, cpuFreqLimitsMax); + } + } + + createFolderRow(): TraceRow { + let folder = new TraceRow(); + folder.rowParentId = ''; + folder.folder = true; + folder.style.height = '40px'; + folder.rowHidden = folder.expansion; + folder.setAttribute('children', ''); + folder.supplier = folderSupplier(); + folder.onThreadHandler = folderThreadHandler(folder, this.trace); + return folder; + } + + async addFreqRows(freqList: Array): Promise { + let freqMaxList = await queryCpuMaxFreq(); + CpuFreqStruct.maxFreq = freqMaxList[0].maxFreq; + let maxFreqObj = Utils.getFrequencyWithUnit(freqMaxList[0].maxFreq); + CpuFreqStruct.maxFreq = maxFreqObj.maxFreq; + CpuFreqStruct.maxFreqName = maxFreqObj.maxFreqName; + for (let i = 0; i < freqList.length; i++) { + const it = freqList[i]; + let traceRow = TraceRow.skeleton(); + traceRow.rowId = `${it.filterId}`; + traceRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ; + traceRow.rowParentId = ''; + traceRow.style.height = '40px'; + traceRow.name = `Cpu ${it.cpu} Frequency`; + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplierFrame = (): Promise => cpuFreqDataSender(it.cpu, traceRow); //queryCpuFreqData + traceRow.focusHandler = (ev): void => { + this.trace?.displayTip( + traceRow, + CpuFreqStruct.hoverCpuFreqStruct, + `${ColorUtils.formatNumberComma(CpuFreqStruct.hoverCpuFreqStruct?.value!)} kHz` + ); + }; + traceRow.findHoverStruct = (): void => { + CpuFreqStruct.hoverCpuFreqStruct = traceRow.getHoverStruct(true, false, 'value'); + }; + traceRow.onThreadHandler = rowThreadHandler( + 'freq', + 'context', + { + type: `freq${it.cpu}`, + }, + traceRow, + this.trace + ); + this.folderRow!.addChildTraceRow(traceRow); + } + } + + addStateRows(cpuStateFilterIds: Array): void { + for (let it of cpuStateFilterIds) { + let cpuStateRow = TraceRow.skeleton(); + cpuStateRow.rowId = `${it.filterId}`; + cpuStateRow.rowType = TraceRow.ROW_TYPE_CPU_STATE; + cpuStateRow.rowParentId = ''; + cpuStateRow.style.height = '40px'; + cpuStateRow.name = `Cpu ${it.cpu} State`; + cpuStateRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cpuStateRow.selectChangeHandler = this.trace.selectChangeHandler; + cpuStateRow.supplierFrame = async (): Promise => { + let rs = await cpuStateSender(it.filterId, cpuStateRow); + rs.forEach((t) => (t.cpu = it.cpu)); + return rs; + }; + cpuStateRow.focusHandler = (ev): void => { + this.trace.displayTip( + cpuStateRow, + CpuStateStruct.hoverStateStruct, + `State: ${CpuStateStruct.hoverStateStruct?.value}` + ); + }; + cpuStateRow.findHoverStruct = (): void => { + CpuStateStruct.hoverStateStruct = cpuStateRow.getHoverStruct(); + }; + cpuStateRow.onThreadHandler = rowThreadHandler( + 'cpu-state', + 'cpuStateContext', + { + type: `cpu-state-${it.cpu}`, + cpu: it.cpu, + }, + cpuStateRow, + this.trace + ); + this.folderRowState!.addChildTraceRow(cpuStateRow); + } + } - for (let limit of cpuFreqLimits) { - let findMax = Utils.getFrequencyWithUnit( - cpuFreqLimitsMax.find((maxLimit) => { - return maxLimit.filterId == limit.maxFilterId; - })?.maxValue || 0 + addFreqLimitRows(cpuFreqLimits: Array, cpuFreqLimitsMax: Array): void { + for (let limit of cpuFreqLimits) { + let findMax = Utils.getFrequencyWithUnit( + cpuFreqLimitsMax.find((maxLimit) => maxLimit.filterId === limit.maxFilterId)?.maxValue || 0 + ); + let cpuFreqLimitRow = TraceRow.skeleton(); + cpuFreqLimitRow.rowId = `${limit.cpu}`; + cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT; + cpuFreqLimitRow.rowParentId = ''; + cpuFreqLimitRow.style.height = '40px'; + cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`; + cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; + cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`); + cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`); + cpuFreqLimitRow.setAttribute('cpu', `${limit.cpu}`); + cpuFreqLimitRow.supplierFrame = async (): Promise => { + const res = await cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow); + res.forEach((item) => (item.cpu = limit.cpu)); + return res; + }; + cpuFreqLimitRow.focusHandler = (ev): void => { + this.trace.displayTip( + cpuFreqLimitRow, + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct, + `Max Freq: ${ColorUtils.formatNumberComma( + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max || 0 + )} kHzMin Freq: ${ColorUtils.formatNumberComma( + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min || 0 + )} kHz` ); - let cpuFreqLimitRow = TraceRow.skeleton(); - cpuFreqLimitRow.rowId = `${limit.cpu}`; - cpuFreqLimitRow.rowType = TraceRow.ROW_TYPE_CPU_FREQ_LIMIT; - cpuFreqLimitRow.rowParentId = ''; - cpuFreqLimitRow.style.height = '40px'; - cpuFreqLimitRow.name = `Cpu ${limit.cpu} Freq Limit`; - cpuFreqLimitRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - cpuFreqLimitRow.selectChangeHandler = this.trace.selectChangeHandler; - cpuFreqLimitRow.setAttribute('maxFilterId', `${limit.maxFilterId}`); - cpuFreqLimitRow.setAttribute('minFilterId', `${limit.minFilterId}`); - cpuFreqLimitRow.setAttribute('cpu', `${limit.cpu}`); - cpuFreqLimitRow.isHover = true; - cpuFreqLimitRow.supplierFrame = () => { - return cpuFreqLimitSender(limit.maxFilterId, limit.minFilterId, limit.cpu, cpuFreqLimitRow).then((res) => { - res.forEach((item) => { - item.cpu = limit.cpu; - }); - return res; - }); - }; - cpuFreqLimitRow.focusHandler = (ev) => { - this.trace.displayTip( - cpuFreqLimitRow, - CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct, - `Max Freq: ${ColorUtils.formatNumberComma( - CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.max || 0 - )} kHzMin Freq: ${ColorUtils.formatNumberComma( - CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct?.min || 0 - )} kHz` - ); - }; - cpuFreqLimitRow.findHoverStruct = () => { - CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = cpuFreqLimitRow.getHoverStruct(); - }; - cpuFreqLimitRow.onThreadHandler = (useCache: boolean) => { - let context: CanvasRenderingContext2D; - if (cpuFreqLimitRow.currentContext) { - context = cpuFreqLimitRow.currentContext; - } else { - context = cpuFreqLimitRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - cpuFreqLimitRow.canvasSave(context); - (renders['cpu-limit-freq'] as CpuFreqLimitRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `cpu-limit-freq-${limit.cpu}`, - cpu: limit.cpu, - maxFreq: findMax?.maxFreq || 0, - maxFreqName: findMax?.maxFreqName || '', - }, - cpuFreqLimitRow - ); - cpuFreqLimitRow.canvasRestore(context, this.trace); - }; - this.folderRowLimit!.addChildTraceRow(cpuFreqLimitRow); - } + }; + cpuFreqLimitRow.findHoverStruct = (): void => { + CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = cpuFreqLimitRow.getHoverStruct(); + }; + cpuFreqLimitRow.onThreadHandler = rowThreadHandler( + 'cpu-limit-freq', + 'context', + { + type: `cpu-limit-freq-${limit.cpu}`, + cpu: limit.cpu, + maxFreq: findMax?.maxFreq || 0, + maxFreqName: findMax?.maxFreqName || '', + }, + cpuFreqLimitRow, + this.trace + ); + this.folderRowLimit!.addChildTraceRow(cpuFreqLimitRow); } } } diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 86381388810c5c28f6ebe1704180fe09e97dae7c..48fd64cb9b3e7b5b5952f8dae72d3dda57f588e5 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -27,12 +27,8 @@ import { HiPerfProcessStruct } from '../../database/ui-worker/hiperf/ProcedureWo import { info } from '../../../log/Log'; import { HiPerfEventStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent'; import { perfDataQuery } from './PerfDataQuery'; -import { renders } from '../../database/ui-worker/ProcedureWorker'; -import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { type HiPerfReportStruct } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport'; -import { SpChartManager } from './SpChartManager'; -import { procedurePool } from '../../database/Procedure'; -import { HiPerfChartFrame } from '../../bean/PerfStruct'; +import { folderThreadHandler, getRowContext, rowThreadHandler, SpChartManager } from './SpChartManager'; import { HiperfCpuRender2 } from '../../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2'; import { hiperfCpuDataSender } from '../../database/data-trafic/hiperf/HiperfCpuDataSender'; import { hiperfProcessDataSender } from '../../database/data-trafic/hiperf/HiperfProcessDataSender'; @@ -50,6 +46,7 @@ import { queryPerfEventType, queryPerfThread, } from '../../database/sql/Perf.sql'; +import { renders } from '../../database/ui-worker/ProcedureWorker'; export interface ResultData { existA: boolean | null | undefined; @@ -59,8 +56,6 @@ export interface ResultData { export class SpHiPerf { static selectCpuStruct: HiPerfCpuStruct | undefined; - static selectProcessStruct: HiPerfProcessStruct | undefined; - static selectThreadStruct: HiPerfThreadStruct | undefined; static stringResult: ResultData | undefined; private cpuData: Array | undefined; @@ -74,13 +69,12 @@ export class SpHiPerf { private callChartType: number = 0; private callChartId: number = 0; private eventTypeId: number = -2; - private stackChartMaxDepth: number = 1; constructor(trace: SpSystemTrace) { this.trace = trace; } - async init() { + async init(): Promise { await this.initCmdLine(); this.eventTypeList = await queryPerfEventType(); this.rowList = []; @@ -102,10 +96,10 @@ export class SpHiPerf { info('HiPerf Data initialized'); } - getStringResult(s: string = '') { + getStringResult(s: string = ''): void { let list = s.split(' '); - let sA = list.findIndex((item) => item == '-a'); - let sF = list.findIndex((item) => item == '-f'); + let sA = list.findIndex((item) => item === '-a'); + let sF = list.findIndex((item) => item === '-f'); SpHiPerf.stringResult = { existA: sA !== -1, existF: sF !== -1, @@ -113,7 +107,7 @@ export class SpHiPerf { }; } - async initCmdLine() { + async initCmdLine(): Promise { let perfCmdLines = await queryPerfCmdline(); if (perfCmdLines.length > 0) { this.getStringResult(perfCmdLines[0].report_value); @@ -126,10 +120,10 @@ export class SpHiPerf { } } - async initFolder() { + async initFolder(): Promise { let row = TraceRow.skeleton(); row.setAttribute('disabled-check', ''); - row.rowId = `HiPerf`; + row.rowId = 'HiPerf'; row.index = 0; row.rowType = TraceRow.ROW_TYPE_HIPERF; row.rowParentId = ''; @@ -138,6 +132,27 @@ export class SpHiPerf { row.addRowSettingPop(); row.rowSetting = 'enable'; row.rowSettingPopoverDirection = 'bottomLeft'; + row.style.height = '40px'; + this.folderRowSettingConfig(row); + if (SpHiPerf.stringResult?.existA === true) { + row.name = 'HiPerf (All)'; + } else { + let names = Reflect.ownKeys(this.group) + .map((pid: any) => { + let array = this.group[pid] as Array; + let process = array.filter((th) => th.pid === th.tid)[0]; + return process.processName; + }) + .join(','); + row.name = `HiPerf (${names})`; + } + row.supplier = (): Promise> => new Promise>((resolve) => resolve([])); + row.onThreadHandler = folderThreadHandler(row, this.trace); + this.rowFolder = row; + this.trace.rowsEL?.appendChild(row); + } + + folderRowSettingConfig(row: TraceRow): void { row.rowSettingList = [ { key: '-2', @@ -151,7 +166,7 @@ export class SpHiPerf { }; }), ]; - row.onRowSettingChangeHandler = (value) => { + row.onRowSettingChangeHandler = (value): void => { let drawType = parseInt(value[0]); if (this.eventTypeId !== drawType) { this.eventTypeId = drawType; @@ -172,45 +187,13 @@ export class SpHiPerf { this.trace.refreshCanvas(false); } }; - row.style.height = '40px'; - if (SpHiPerf.stringResult?.existA === true) { - row.name = `HiPerf (All)`; - } else { - let names = Reflect.ownKeys(this.group) - .map((pid: any) => { - let array = this.group[pid] as Array; - let process = array.filter((th) => th.pid === th.tid)[0]; - return process.processName; - }) - .join(','); - row.name = `HiPerf (${names})`; - } - row.supplier = () => new Promise>((resolve) => resolve([])); - row.onThreadHandler = (useCache) => { - row.canvasSave(this.trace.canvasPanelCtx!); - if (row.expansion) { - this.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); - } else { - (renders['empty'] as EmptyRender).renderMainThread( - { - context: this.trace.canvasPanelCtx, - useCache: useCache, - type: ``, - }, - row - ); - } - row.canvasRestore(this.trace.canvasPanelCtx!, this.trace); - }; - this.rowFolder = row; - this.trace.rowsEL?.appendChild(row); } - async initCallChart() { + async initCallChart(): Promise { await hiperfCallStackCacheSender(); await hiperfCallChartDataCacheSender(); let perfCallCutRow = TraceRow.skeleton(); - perfCallCutRow.rowId = `HiPerf-callchart`; + perfCallCutRow.rowId = 'HiPerf-callchart'; perfCallCutRow.index = 0; perfCallCutRow.rowType = TraceRow.ROW_TYPE_PERF_CALLCHART; perfCallCutRow.enableCollapseChart(); @@ -225,54 +208,57 @@ export class SpHiPerf { perfCallCutRow.selectChangeHandler = this.trace.selectChangeHandler; this.rowFolder.addChildTraceRow(perfCallCutRow); perfCallCutRow.focusHandler = (): void => { - let hoverStruct = HiPerfCallChartStruct.hoverPerfCallCutStruct; - if (hoverStruct) { - let callName = hoverStruct.name; - callName = callName.replace(//g, '>'); - this.trace?.displayTip( - perfCallCutRow!, - hoverStruct, - `Name: - ${callName}
- Lib: - ${perfDataQuery.getLibName(hoverStruct!.fileId, hoverStruct!.symbolId)}
- Self Time: - ${Utils.getProbablyTime(hoverStruct.selfDur || 0)}
- Duration: - ${Utils.getProbablyTime(hoverStruct.totalTime)}
- Event Count: - ${hoverStruct.eventCount || ''}
` - ); - } + this.callChartRowFocusHandler(perfCallCutRow); }; - perfCallCutRow.supplierFrame = () => { - return hiperfCallChartDataSender(perfCallCutRow, { + perfCallCutRow.supplierFrame = async (): Promise => { + const res = await hiperfCallChartDataSender(perfCallCutRow, { startTime: window.recordStartNS, eventTypeId: this.eventTypeId, type: this.callChartType, id: this.callChartId, - }).then((res) => { - let maxHeight = res.maxDepth * 20; - perfCallCutRow.funcMaxHeight = maxHeight; - if (perfCallCutRow.funcExpand) { - perfCallCutRow!.style.height = `${maxHeight}px`; - if (perfCallCutRow.collect) { - window.publish(window.SmartEvent.UI.RowHeightChange, { - expand: true, - value: perfCallCutRow.funcMaxHeight - 20, - }); - } - } - return res.dataList; }); + let maxHeight = res.maxDepth * 20; + perfCallCutRow.funcMaxHeight = maxHeight; + if (perfCallCutRow.funcExpand) { + perfCallCutRow!.style.height = `${maxHeight}px`; + if (perfCallCutRow.collect) { + window.publish(window.SmartEvent.UI.RowHeightChange, { + expand: true, + value: perfCallCutRow.funcMaxHeight - 20, + }); + } + } + return res.dataList; }; - perfCallCutRow.findHoverStruct = () => { + perfCallCutRow.findHoverStruct = (): void => { HiPerfCallChartStruct.hoverPerfCallCutStruct = perfCallCutRow.getHoverStruct(); }; await this.setCallTotalRow(perfCallCutRow, this.cpuData, this.perfThreads); } - async setCallTotalRow(row: TraceRow, cpuData: any = Array, threadData: any = Array) { + callChartRowFocusHandler(perfCallCutRow: TraceRow): void { + let hoverStruct = HiPerfCallChartStruct.hoverPerfCallCutStruct; + if (hoverStruct) { + let callName = hoverStruct.name; + callName = callName.replace(//g, '>'); + this.trace?.displayTip( + perfCallCutRow!, + hoverStruct, + `Name: + ${callName}
+ Lib: + ${perfDataQuery.getLibName(hoverStruct!.fileId, hoverStruct!.symbolId)}
+ Self Time: + ${Utils.getProbablyTime(hoverStruct.selfDur || 0)}
+ Duration: + ${Utils.getProbablyTime(hoverStruct.totalTime)}
+ Event Count: + ${hoverStruct.eventCount || ''}
` + ); + } + } + + async setCallTotalRow(row: TraceRow, cpuData: any = Array, threadData: any = Array): Promise { let pt: Map = threadData.reduce((map: Map, current: any) => { const key = `${current.processName || 'Process'}(${current.pid})`; const thread = { @@ -298,6 +284,13 @@ export class SpHiPerf { row.addTemplateTypes('hiperf-callchart'); row.addRowSettingPop(); row.rowSetting = 'enable'; + this.setCallChartRowSetting(row, cpuData, pt); + row.onThreadHandler = rowThreadHandler('HiPerf-callchart', 'context', { + type: 'HiPerf-callchart', + }, row, this.trace); + } + + setCallChartRowSetting(row: TraceRow, cpuData: Array, pt: Map): void { row.rowSettingList = [ ...cpuData.reverse().map( ( @@ -340,41 +333,23 @@ export class SpHiPerf { row.drawFrame(); } }; - row.onThreadHandler = (useCache: any) => { - let context: CanvasRenderingContext2D; - if (row.currentContext) { - context = row.currentContext; - } else { - context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - row.canvasSave(context); - (renders['HiPerf-callchart'] as HiPerfCallChartRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `HiPerf-callchart`, - }, - row - ); - row.canvasRestore(context, this.trace); - }; } - async initCpuMerge() { + async initCpuMerge(): Promise { let cpuMergeRow = TraceRow.skeleton(); - cpuMergeRow.rowId = `HiPerf-cpu-merge`; + cpuMergeRow.rowId = 'HiPerf-cpu-merge'; cpuMergeRow.index = 0; cpuMergeRow.rowType = TraceRow.ROW_TYPE_HIPERF_CPU; cpuMergeRow.rowParentId = 'HiPerf'; cpuMergeRow.rowHidden = !this.rowFolder.expansion; cpuMergeRow.folder = false; cpuMergeRow.drawType = -2; - cpuMergeRow.name = `HiPerf`; + cpuMergeRow.name = 'HiPerf'; cpuMergeRow.style.height = '40px'; cpuMergeRow.setAttribute('children', ''); cpuMergeRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; cpuMergeRow.selectChangeHandler = this.trace.selectChangeHandler; - cpuMergeRow.supplierFrame = () => { + cpuMergeRow.supplierFrame = (): Promise => { return hiperfCpuDataSender( -1, cpuMergeRow.drawType, @@ -384,37 +359,35 @@ export class SpHiPerf { cpuMergeRow ); }; - cpuMergeRow.focusHandler = () => this.hoverTip(cpuMergeRow, HiPerfCpuStruct.hoverStruct); - cpuMergeRow.findHoverStruct = () => { + cpuMergeRow.focusHandler = (): void => this.hoverTip(cpuMergeRow, HiPerfCpuStruct.hoverStruct); + cpuMergeRow.findHoverStruct = (): void => { HiPerfCpuStruct.hoverStruct = cpuMergeRow.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); }; - cpuMergeRow.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (cpuMergeRow.currentContext) { - context = cpuMergeRow.currentContext; - } else { - context = cpuMergeRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - cpuMergeRow.canvasSave(context); - (renders['HiPerf-Cpu-2'] as HiperfCpuRender2).renderMainThread( - { - context: context, - useCache: useCache, - scale: TraceRow.range?.scale || 50, - type: `HiPerf-Cpu-Merge`, - maxCpu: this.maxCpuId + 1, - intervalPerf: SpHiPerf.stringResult?.fValue || 1, - range: TraceRow.range, - }, - cpuMergeRow - ); - cpuMergeRow.canvasRestore(context, this.trace); - }; + cpuMergeRow.onThreadHandler = this.rowThreadHandler('HiPerf-Cpu-2', 'context', { + type: 'HiPerf-Cpu-Merge', + maxCpu: this.maxCpuId + 1, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + }, cpuMergeRow, this.trace); this.rowFolder.addChildTraceRow(cpuMergeRow); this.rowList?.push(cpuMergeRow); } - async initCpu() { + rowThreadHandler(tag: string, contextField: string, arg: any, row: TraceRow, trace: SpSystemTrace) { + return (useCache: boolean): void => { + let context: CanvasRenderingContext2D = getRowContext(row, trace); + row.canvasSave(context); + arg.useCache = useCache; + arg.scale = TraceRow.range?.scale || 50; + arg.range = TraceRow.range; + if (contextField) { + arg[contextField] = context; + } + (renders[tag] as any).renderMainThread(arg, row); + row.canvasRestore(context, trace); + }; + } + + async initCpu(): Promise { for (let i = 0; i <= this.maxCpuId; i++) { let perfCpuRow = TraceRow.skeleton(); perfCpuRow.rowId = `HiPerf-cpu-${i}`; @@ -429,7 +402,7 @@ export class SpHiPerf { perfCpuRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; perfCpuRow.selectChangeHandler = this.trace.selectChangeHandler; perfCpuRow.style.height = '40px'; - perfCpuRow.supplierFrame = () => { + perfCpuRow.supplierFrame = (): Promise => { return hiperfCpuDataSender( i, perfCpuRow.drawType, @@ -439,203 +412,104 @@ export class SpHiPerf { perfCpuRow ); }; - perfCpuRow.focusHandler = () => this.hoverTip(perfCpuRow, HiPerfCpuStruct.hoverStruct); - perfCpuRow.findHoverStruct = () => { + perfCpuRow.focusHandler = (): void => this.hoverTip(perfCpuRow, HiPerfCpuStruct.hoverStruct); + perfCpuRow.findHoverStruct = (): void => { HiPerfCpuStruct.hoverStruct = perfCpuRow.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); }; - perfCpuRow.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (perfCpuRow.currentContext) { - context = perfCpuRow.currentContext; - } else { - context = perfCpuRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - perfCpuRow.canvasSave(context); - (renders['HiPerf-Cpu-2'] as HiperfCpuRender2).renderMainThread( - { - context: context, - useCache: useCache, - scale: TraceRow.range?.scale || 50, - type: `HiPerf-Cpu-${i}`, - maxCpu: this.maxCpuId + 1, - intervalPerf: SpHiPerf.stringResult?.fValue || 1, - range: TraceRow.range, - }, - perfCpuRow - ); - perfCpuRow.canvasRestore(context, this.trace); - }; + perfCpuRow.onThreadHandler = this.rowThreadHandler('HiPerf-Cpu-2', 'context', { + type: `HiPerf-Cpu-${i}`, + maxCpu: this.maxCpuId + 1, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + }, perfCpuRow, this.trace); this.rowFolder.addChildTraceRow(perfCpuRow); this.rowList?.push(perfCpuRow); } } - async initProcess() { - Reflect.ownKeys(this.group) - .filter((it) => { - return true; - }) - .forEach((key, index) => { - let array = this.group[key] as Array; - let process = array.filter((th) => th.pid === th.tid)[0]; - let row = TraceRow.skeleton(); - row.rowId = `${process.pid}-Perf-Process`; - row.index = index; - row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS; - row.rowParentId = 'HiPerf'; - row.rowHidden = !this.rowFolder.expansion; - row.folder = true; - row.drawType = -2; - if (SpChartManager.APP_STARTUP_PID_ARR.find((pid) => pid === process.pid) !== undefined) { - row.addTemplateTypes('AppStartup'); - } - row.addTemplateTypes('HiPerf'); - row.name = `${process.processName || 'Process'} [${process.pid}]`; - row.folderPaddingLeft = 6; - row.style.height = '40px'; - row.favoriteChangeHandler = this.trace.favoriteChangeHandler; - row.selectChangeHandler = this.trace.selectChangeHandler; - row.supplierFrame = () => { - return hiperfProcessDataSender( - process.pid, - row.drawType, - this.maxCpuId + 1, - SpHiPerf.stringResult?.fValue || 1, - TraceRow.range?.scale || 50, - row - ); - }; - row.focusHandler = () => this.hoverTip(row, HiPerfProcessStruct.hoverStruct); - row.findHoverStruct = () => { - HiPerfProcessStruct.hoverStruct = row.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); - }; - row.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (row.currentContext) { - context = row.currentContext; - } else { - context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - row.canvasSave(context); - if (row.expansion) { - this.trace.canvasPanelCtx?.clearRect(0, 0, row.frame.width, row.frame.height); - } else { - (renders['HiPerf-Process-2'] as HiperfProcessRender2).renderMainThread( - { - context: context, - useCache: useCache, - scale: TraceRow.range?.scale || 50, - type: `HiPerf-Process-${row.index}`, - intervalPerf: SpHiPerf.stringResult?.fValue || 1, - range: TraceRow.range, - }, - row - ); - } - row.canvasRestore(context, this.trace); - }; - this.rowFolder.addChildTraceRow(row); - this.rowList?.push(row); - array.forEach((thObj, thIdx) => { - let thread = TraceRow.skeleton(); - thread.rowId = `${thObj.tid}-Perf-Thread`; - thread.index = thIdx; - thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD; - thread.rowParentId = row.rowId; - thread.rowHidden = !row.expansion; - thread.folder = false; - thread.drawType = -2; - thread.name = `${thObj.threadName || 'Thread'} [${thObj.tid}]`; - thread.setAttribute('children', ''); - thread.folderPaddingLeft = 0; - thread.style.height = '40px'; - thread.favoriteChangeHandler = this.trace.favoriteChangeHandler; - thread.selectChangeHandler = this.trace.selectChangeHandler; - thread.supplierFrame = () => { - return hiperfThreadDataSender( - thObj.tid, - thread.drawType, - this.maxCpuId + 1, - SpHiPerf.stringResult?.fValue || 1, - TraceRow.range?.scale || 50, - thread - ); - }; - thread.focusHandler = () => this.hoverTip(thread, HiPerfThreadStruct.hoverStruct); - thread.findHoverStruct = () => { - HiPerfThreadStruct.hoverStruct = thread.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); - }; - thread.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (thread.currentContext) { - context = thread.currentContext; - } else { - context = thread.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - thread.canvasSave(context); - (renders['HiPerf-Thread-2'] as HiperfThreadRender2).renderMainThread( - { - context: context, - useCache: useCache, - scale: TraceRow.range?.scale || 50, - type: `HiPerf-Thread-${row.index}-${thread.index}`, - intervalPerf: SpHiPerf.stringResult?.fValue || 1, - range: TraceRow.range, - }, - thread - ); - thread.canvasRestore(context, this.trace); - }; - row.addChildTraceRow(thread); - this.rowList?.push(thread); - }); - }); - } - - async getHiPerfChartData(type: number, id: number, eventTypeId: number, row: TraceRow) { - let source: Array = []; - this.stackChartMaxDepth = 1; - await new Promise((resolve) => { - procedurePool.submitWithName( - 'logic0', - 'perf-callstack-chart', - [type, id, eventTypeId, (window as any).totalNS], - undefined, - (res: any) => { - this.getAllCombineData(res, source); - let maxHeight = this.stackChartMaxDepth * 20; - row.funcMaxHeight = maxHeight; - if (row.funcExpand) { - row!.style.height = `${maxHeight}px`; - if (row.collect) { - window.publish(window.SmartEvent.UI.RowHeightChange, { - expand: true, - value: row.funcMaxHeight - 20, - }); - } - } - resolve(source); - } - ); + async initProcess(): Promise { + Reflect.ownKeys(this.group).forEach((key, index) => { + let array = this.group[key] as Array; + let process = array.filter((th) => th.pid === th.tid)[0]; + let row = TraceRow.skeleton(); + row.rowId = `${process.pid}-Perf-Process`; + row.index = index; + row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS; + row.rowParentId = 'HiPerf'; + row.rowHidden = !this.rowFolder.expansion; + row.folder = true; + row.drawType = -2; + if (SpChartManager.APP_STARTUP_PID_ARR.find((pid) => pid === process.pid) !== undefined) { + row.addTemplateTypes('AppStartup'); + } + row.addTemplateTypes('HiPerf'); + row.name = `${process.processName || 'Process'} [${process.pid}]`; + row.folderPaddingLeft = 6; + row.style.height = '40px'; + row.favoriteChangeHandler = this.trace.favoriteChangeHandler; + row.selectChangeHandler = this.trace.selectChangeHandler; + row.supplierFrame = (): Promise => { + return hiperfProcessDataSender(process.pid, + row.drawType, + this.maxCpuId + 1, + SpHiPerf.stringResult?.fValue || 1, + TraceRow.range?.scale || 50, + row + ); + }; + row.focusHandler = (): void => this.hoverTip(row, HiPerfProcessStruct.hoverStruct); + row.findHoverStruct = (): void => { + HiPerfProcessStruct.hoverStruct = row.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); + }; + row.onThreadHandler = this.rowThreadHandler('HiPerf-Process-2', 'context', { + type: `HiPerf-Process-${row.index}`, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + }, row, this.trace); + this.rowFolder.addChildTraceRow(row); + this.rowList?.push(row); + this.addHiPerfThreadRow(array, row); }); - return source; } - getAllCombineData(combineData: Array, allCombineData: Array): void { - for (let data of combineData) { - if (data.name != 'name') { - allCombineData.push(data); - } - if (data.depth + 1 > this.stackChartMaxDepth) { - this.stackChartMaxDepth = data.depth + 1; - } - if (data.children && data.children.length > 0) { - this.getAllCombineData(data.children, allCombineData); - } - } + addHiPerfThreadRow(array: PerfThread[], row: TraceRow): void { + array.forEach((thObj, thIdx) => { + let thread = TraceRow.skeleton(); + thread.rowId = `${thObj.tid}-Perf-Thread`; + thread.index = thIdx; + thread.rowType = TraceRow.ROW_TYPE_HIPERF_THREAD; + thread.rowParentId = row.rowId; + thread.rowHidden = !row.expansion; + thread.folder = false; + thread.drawType = -2; + thread.name = `${thObj.threadName || 'Thread'} [${thObj.tid}]`; + thread.setAttribute('children', ''); + thread.folderPaddingLeft = 0; + thread.style.height = '40px'; + thread.favoriteChangeHandler = this.trace.favoriteChangeHandler; + thread.selectChangeHandler = this.trace.selectChangeHandler; + thread.supplierFrame = (): Promise => { + return hiperfThreadDataSender( + thObj.tid, + thread.drawType, + this.maxCpuId + 1, + SpHiPerf.stringResult?.fValue || 1, + TraceRow.range?.scale || 50, + thread + ); + }; + thread.focusHandler = (): void => this.hoverTip(thread, HiPerfThreadStruct.hoverStruct); + thread.findHoverStruct = (): void => { + HiPerfThreadStruct.hoverStruct = thread.getHoverStruct(false, (TraceRow.range?.scale || 50) <= 30_000_000); + }; + thread.onThreadHandler = this.rowThreadHandler('HiPerf-Thread-2', 'context', { + type: `HiPerf-Thread-${row.index}-${thread.index}`, + intervalPerf: SpHiPerf.stringResult?.fValue || 1, + }, thread, this.trace); + row.addChildTraceRow(thread); + this.rowList?.push(thread); + }); } - resetChartData(row: TraceRow) { + resetChartData(row: TraceRow): void { row.dataList = []; row.dataList2 = []; row.dataListCache = []; @@ -655,7 +529,7 @@ export class SpHiPerf { | HiPerfReportStruct | HiPerfCpuStruct | undefined - ) { + ): void { let tip = ''; let groupBy10MS = (TraceRow.range?.scale || 50) > 30_000_000; if (struct) { @@ -676,9 +550,8 @@ export class SpHiPerf { let perfCall = perfDataQuery.callChainMap.get(struct.callchain_id || 0); if (perfCall) { let perfName; - typeof perfCall.name === 'number' - ? (perfName = SpSystemTrace.DATA_DICT.get(parseInt(perfCall.name))) - : (perfName = perfCall.name); + typeof perfCall.name === 'number' ? (perfName = SpSystemTrace.DATA_DICT.get(parseInt(perfCall.name))) : + (perfName = perfCall.name); tip = `${perfCall ? perfName : ''} (${perfCall ? perfCall.depth : '0'} other frames)`; } } diff --git a/ide/src/trace/component/chart/SpIrqChart.ts b/ide/src/trace/component/chart/SpIrqChart.ts index eb237f96325325641c10dd921303322bf0bd8fc8..c56d65db3c53af162636dd489cc57daf0c26c245 100644 --- a/ide/src/trace/component/chart/SpIrqChart.ts +++ b/ide/src/trace/component/chart/SpIrqChart.ts @@ -20,7 +20,8 @@ import { renders } from '../../database/ui-worker/ProcedureWorker'; import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { IrqRender, IrqStruct } from '../../database/ui-worker/ProcedureWorkerIrq'; import { irqDataSender } from '../../database/data-trafic/IrqDataSender'; -import {queryAllIrqNames, queryIrqList} from "../../database/sql/Irq.sql"; +import { queryAllIrqNames, queryIrqList } from '../../database/sql/Irq.sql'; +import { getRowContext, rowThreadHandler } from './SpChartManager'; export class SpIrqChart { private trace: SpSystemTrace; @@ -50,67 +51,47 @@ export class SpIrqChart { this.trace.rowsEL?.appendChild(folder); for (let i = 0; i < irqList.length; i++) { const it = irqList[i]; - let traceRow = TraceRow.skeleton(); - traceRow.rowId = it.name + it.cpu; - traceRow.rowType = TraceRow.ROW_TYPE_IRQ; - traceRow.rowParentId = folder.rowId; - traceRow.style.height = '40px'; - traceRow.name = `${it.name} Cpu ${it.cpu}`; - traceRow.rowHidden = !folder.expansion; - traceRow.setAttribute('children', ''); - traceRow.setAttribute('callId', `${it.cpu}`); - traceRow.setAttribute('cat', `${it.name}`); - traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - traceRow.selectChangeHandler = this.trace.selectChangeHandler; - traceRow.supplierFrame = () => { - return irqDataSender(it.cpu, it.name, traceRow).then((irqs) => { - if (irqs.length > 0) { - irqs.forEach((irq, index) => { - if (it.name === 'irq') { - irqs[index].name = this.irqNameMap.get(irqs[index].id!)!.ipiName || ''; - } else { - irqs[index].name = this.irqNameMap.get(irqs[index].id!)!.name || ''; - } - }); - } - return irqs; - }); - }; - traceRow.focusHandler = (ev) => { - this.trace?.displayTip( - traceRow, - IrqStruct.hoverIrqStruct, - `${IrqStruct.hoverIrqStruct?.name || ''}` - ); - }; - traceRow.findHoverStruct = () => { - IrqStruct.hoverIrqStruct = traceRow.getHoverStruct(); - }; - traceRow.onThreadHandler = (useCache) => { - let context: CanvasRenderingContext2D; - if (traceRow.currentContext) { - context = traceRow.currentContext; - } else { - context = traceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - traceRow.canvasSave(context); - (renders['irq'] as IrqRender).renderMainThread( - { - context: context, - useCache: useCache, - type: it.name, - index: i, - }, - traceRow - ); - traceRow.canvasRestore(context, this.trace); - }; - folder.addChildTraceRow(traceRow); + this.addIrqRow(it, i, folder); } let durTime = new Date().getTime() - irqStartTime; info('The time to load the ClockData is: ', durTime); } + addIrqRow(it: any, index: number, folder: TraceRow) { + let traceRow = TraceRow.skeleton(); + traceRow.rowId = it.name + it.cpu; + traceRow.rowType = TraceRow.ROW_TYPE_IRQ; + traceRow.rowParentId = folder.rowId; + traceRow.style.height = '40px'; + traceRow.name = `${it.name} Cpu ${it.cpu}`; + traceRow.rowHidden = !folder.expansion; + traceRow.setAttribute('children', ''); + traceRow.setAttribute('callId', `${it.cpu}`); + traceRow.setAttribute('cat', `${it.name}`); + traceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + traceRow.selectChangeHandler = this.trace.selectChangeHandler; + traceRow.supplierFrame = () => { + return irqDataSender(it.cpu, it.name, traceRow).then((irqs) => { + irqs.forEach((irq) => { + let irqData = this.irqNameMap.get(irq.id!); + irq.name = (it.name === 'irq' ? irqData?.ipiName : irqData?.name) || ''; + }); + return irqs; + }); + }; + traceRow.focusHandler = (ev) => { + this.trace?.displayTip(traceRow, IrqStruct.hoverIrqStruct, `${IrqStruct.hoverIrqStruct?.name || ''}`); + }; + traceRow.findHoverStruct = () => { + IrqStruct.hoverIrqStruct = traceRow.getHoverStruct(); + }; + traceRow.onThreadHandler = rowThreadHandler('irq', 'context', { + type: it.name, + index: index, + }, traceRow, this.trace); + folder.addChildTraceRow(traceRow); + } + async initFolder(): Promise> { let irqFolder = TraceRow.skeleton(); irqFolder.rowId = `Irqs`; diff --git a/ide/src/trace/component/chart/SpLTPO.ts b/ide/src/trace/component/chart/SpLTPO.ts index d73efcc88dba6e9f76aea74a40abd95f75ee42f8..bc6038b3dbf6b3fdce004dafc7c8455856c56f25 100644 --- a/ide/src/trace/component/chart/SpLTPO.ts +++ b/ide/src/trace/component/chart/SpLTPO.ts @@ -28,6 +28,7 @@ import { import { LtpoRender, LtpoStruct } from '../../database/ui-worker/ProcedureWorkerLTPO' import { HitchTimeStruct, hitchTimeRender } from '../../database/ui-worker/ProcedureWorkerHitchTime'; import { lostFrameSender } from '../../database/data-trafic/LostFrameSender'; +import { fps } from '../../database/ui-worker/ProcedureWorkerFPS'; export class SpLtpoChart { private readonly trace: SpSystemTrace | undefined; @@ -77,7 +78,7 @@ export class SpLtpoChart { let fanceIndex = 0; while (fpsIndex < SpLtpoChart.fpsnameList!.length) { if (SpLtpoChart.fanceNameList[fanceIndex] && SpLtpoChart.fpsnameList[fpsIndex]) { - if (SpLtpoChart.fanceNameList[fanceIndex].ts! > SpLtpoChart.fpsnameList[fpsIndex].ts! && + if (SpLtpoChart.fanceNameList[fanceIndex].ts! > SpLtpoChart.fpsnameList[fpsIndex].ts! && SpLtpoChart.fanceNameList[fanceIndex].ts! < SpLtpoChart.fpsnameList[fpsIndex].ts! + SpLtpoChart.fpsnameList[fpsIndex].dur!) { fpsIndex++; fanceIndex++; @@ -253,12 +254,12 @@ export class SpLtpoChart { cutTimeSum += 1000 / tempFps; SpLtpoChart.tempRsNowTimeList[nowTimeIndex - 1].cutTime = cutTimeSum; SpLtpoChart.tempRsNowTimeList.splice(nowTimeIndex, 1); - } else if (!SpLtpoChart.tempRsNowTimeList[nowTimeIndex].signaled) { + } else { nowTimeIndex++; cutTimeSum = 0; tempFps = 0; } - } else if (SpLtpoChart.skipDataList[skipIndex].ts! < SpLtpoChart.tempRsNowTimeList[nowTimeIndex].ts!) { + } else if (SpLtpoChart.skipDataList[skipIndex].ts! <= SpLtpoChart.tempRsNowTimeList[nowTimeIndex].ts!) { if (nowTimeIndex > 0) { cutTimeSum += tempFps ? (1000 / tempFps) : (1000 / SpLtpoChart.tempRsNowTimeList[nowTimeIndex - 1].fps!); } @@ -295,17 +296,30 @@ export class SpLtpoChart { let sendDataArr: LtpoStruct[] = []; let ltpoDataIndex = 0; let tempRsNowTimeIndex = 0; + let presentIndex = 0; + let ltpoIndex = 0; //当有present缺失时: this.deleteUselessFence(presentArr, ltpoDataArr); - if (presentArr!.length && presentArr!.length === ltpoDataArr!.length) { - for (let i = 0; i < presentArr!.length; i++) { - ltpoDataArr[i].startTs = Number(presentArr[i].startTime) - (window as any).recordStartNS; - ltpoDataArr[i].dur = presentArr[i].dur; - ltpoDataArr[i].nextStartTs = presentArr[i + 1] ? Number(presentArr[i + 1].startTime) - (window as any).recordStartNS : ''; - ltpoDataArr[i].nextDur = presentArr[i + 1] ? presentArr[i + 1].dur : 0; + while (presentIndex < presentArr.length) { + if (presentArr[presentIndex] && ltpoDataArr[ltpoIndex]) { + if ((presentArr[presentIndex].startTime! + presentArr[presentIndex].dur! - (window as any).recordStartNS) === TraceRow.range!.totalNS) { + presentArr.splice(presentIndex, 1) + } + if (presentArr[presentIndex].presentId === ltpoDataArr[ltpoIndex].fanceId) { + ltpoDataArr[ltpoIndex].startTs = Number(presentArr[presentIndex].startTime) - (window as any).recordStartNS; + ltpoDataArr[ltpoIndex].dur = presentArr[presentIndex].dur; + ltpoDataArr[ltpoIndex].nextStartTs = presentArr[presentIndex + 1] ? Number(presentArr[presentIndex + 1].startTime) - (window as any).recordStartNS : ''; + ltpoDataArr[ltpoIndex].nextDur = presentArr[presentIndex + 1] ? presentArr[presentIndex + 1].dur : 0; + presentIndex++; + ltpoIndex++; + } else if (presentArr[presentIndex].presentId! < ltpoDataArr[ltpoIndex].fanceId!) { + presentArr.splice(presentIndex, 1); + } else if (presentArr[presentIndex].presentId! > ltpoDataArr[ltpoIndex].fanceId!) { + ltpoDataArr.splice(ltpoIndex, 1); + } + } else { + break; } - } else { - return sendDataArr; } while (ltpoDataIndex < ltpoDataArr.length) { let sendStartTs: number | undefined = 0; @@ -363,17 +377,21 @@ export class SpLtpoChart { //当有present缺失时: let presentIndex = 0; let fpsIndex = 0; - while (presentIndex < presentArr.length) {//遍历present,把ltpoDataArr中不包含present中presentFance的item舍弃掉 - if (Number(presentArr[presentIndex].presentId) < Number(ltpoDataArr[fpsIndex].fanceId)) { - presentArr.splice(presentIndex, 1); - } else if (Number(presentArr[presentIndex].presentId) > Number(ltpoDataArr[fpsIndex].fanceId)) { - ltpoDataArr.splice(fpsIndex, 1); - } else { - if (presentIndex === presentArr.length - 1 && fpsIndex < ltpoDataArr.length - 1) {//此时present已经遍历到最后一项,如果ltpoDataArr还没有遍历到最后一项,就把后面的舍弃掉 - ltpoDataArr.splice(fpsIndex); + while (fpsIndex < ltpoDataArr.length) {//遍历present,把ltpoDataArr中不包含present中presentFance的item舍弃掉 + if (presentArr[presentIndex] && ltpoDataArr[fpsIndex]) { + if (Number(presentArr[presentIndex].presentId) < Number(ltpoDataArr[fpsIndex].fanceId)) { + presentArr.splice(presentIndex, 1); + } else if (Number(presentArr[presentIndex].presentId) > Number(ltpoDataArr[fpsIndex].fanceId)) { + ltpoDataArr.splice(fpsIndex, 1); + } else { + if (presentIndex === presentArr.length - 1 && fpsIndex < ltpoDataArr.length - 1) {//此时present已经遍历到最后一项,如果ltpoDataArr还没有遍历到最后一项,就把后面的舍弃掉 + ltpoDataArr.splice(fpsIndex); + } + presentIndex++; + fpsIndex++; } - presentIndex++; - fpsIndex++; + } else { + return; } }; } @@ -382,12 +400,17 @@ export class SpLtpoChart { if (num < 0) { return 0; } else { - let tempNum = Number(num.toString().split('.')[1].charAt(0)); - if (tempNum > 6) { - return Math.ceil(num); + if (!num.toString().split('.')[1]) { + return num; } else { - return Math.floor(num); + let tempNum = Number(num.toString().split('.')[1].charAt(0)); + if (tempNum > 6) { + return Math.ceil(num); + } else { + return Math.floor(num); + } } + } } diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index 9bf06a9f34527c2645f7a9b7ffac58a053459a4b..4224bd749f8db0bf8c269b084b057c697eb7c538 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -17,14 +17,13 @@ import { SpSystemTrace } from '../SpSystemTrace'; import { Utils } from '../trace/base/Utils'; import { info } from '../../../log/Log'; import { TraceRow } from '../trace/base/TraceRow'; -import { renders } from '../../database/ui-worker/ProcedureWorker'; import { ProcessRender, ProcessStruct } from '../../database/ui-worker/ProcedureWorkerProcess'; import { ThreadRender, ThreadStruct } from '../../database/ui-worker/ProcedureWorkerThread'; import { FuncRender, FuncStruct } from '../../database/ui-worker/ProcedureWorkerFunc'; import { MemRender, ProcessMemStruct } from '../../database/ui-worker/ProcedureWorkerMem'; -import { FolderSupplier, FolderThreadHandler, SpChartManager } from './SpChartManager'; +import {folderSupplier, folderThreadHandler, getRowContext, rowThreadHandler, SpChartManager} from './SpChartManager'; import { JankRender, JankStruct } from '../../database/ui-worker/ProcedureWorkerJank'; -import { isFrameContainPoint, ns2xByTimeShaft } from '../../database/ui-worker/ProcedureWorkerCommon'; +import {isFrameContainPoint, ns2xByTimeShaft, PairPoint} from '../../database/ui-worker/ProcedureWorkerCommon'; import { AppStartupRender, AppStartupStruct } from '../../database/ui-worker/ProcedureWorkerAppStartup'; import { SoRender, SoStruct } from '../../database/ui-worker/ProcedureWorkerSoInit'; import { FlagsConfig } from '../SpFlags'; @@ -41,8 +40,6 @@ import { getMaxDepthByTid, queryAllFuncNames, queryProcessAsyncFunc } from '../. import { queryMemFilterIdMaxValue } from '../../database/sql/Memory.sql'; import { queryAllSoInitNames, queryAllSrcSlices, queryEventCountMap } from '../../database/sql/SqlLite.sql'; import { - queryAllProcessNames, - queryAllThreadName, queryProcess, queryProcessByTable, queryProcessContentCount, @@ -74,10 +71,9 @@ export class SpProcessChart { private funcNameMap: Map = new Map(); private filterIdMaxValue: Map = new Map(); private soInitNameMap: Map = new Map(); - private processNameMap: Map = new Map(); - private threadNameMap: Map = new Map(); private processSrcSliceMap: Map = new Map(); private renderRow: TraceRow | null = null; + private loadAppStartup: boolean = false; constructor(trace: SpSystemTrace) { this.trace = trace; } @@ -99,8 +95,8 @@ export class SpProcessChart { row.folder = true; row.style.height = '40px'; row.name = 'DeliverInputEvent'; - row.supplier = FolderSupplier(); - row.onThreadHandler = FolderThreadHandler(row, this.trace); + row.supplier = folderSupplier(); + row.onThreadHandler = folderThreadHandler(row, this.trace); let asyncFuncGroup = Utils.groupBy( this.processAsyncFuncArray.filter((it) => it.funName === 'deliverInputEvent'), @@ -112,78 +108,103 @@ export class SpProcessChart { Reflect.ownKeys(asyncFuncGroup).map((key: any) => { let asyncFuncGroups: Array = asyncFuncGroup[key]; if (asyncFuncGroups.length > 0) { - let funcRow = TraceRow.skeleton(); - funcRow.rowId = `${asyncFuncGroups[0].funName}-${key}`; - funcRow.asyncFuncName = asyncFuncGroups[0].funName; - funcRow.asyncFuncNamePID = key; - funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 - funcRow.rowParentId = `${row.rowId}`; - funcRow.rowHidden = !row.expansion; - funcRow.style.width = '100%'; - funcRow.name = `${asyncFuncGroups[0].funName} ${key}`; - funcRow.setAttribute('children', ''); - funcRow.supplierFrame = () => { - return processDeliverInputEventDataSender(key, funcRow!).then((res: Array) => { - let isIntersect = (left: any, right: any): boolean => - Math.max(left.startTs + left.dur, right.startTs + right.dur) - Math.min(left.startTs, right.startTs) < - left.dur + right.dur; - let depths: any = []; - let createDepth = (currentDepth: number, index: number): void => { - if (depths[currentDepth] == undefined || !isIntersect(depths[currentDepth], res[index])) { - res[index].depth = currentDepth; - depths[currentDepth] = res[index]; - } else { - createDepth(++currentDepth, index); - } - }; - res.forEach((it, i) => { - res[i].funName = this.funcNameMap.get(res[i].id!); - res[i].threadName = this.threadNameMap.get(res[i].tid!); - if (it.dur == -1 || it.dur === null || it.dur === undefined) { - it.dur = (TraceRow.range?.endNS || 0) - it.startTs; - it.flag = 'Did not end'; - } - createDepth(0, i); - }); - if (funcRow && !funcRow.isComplete) { - let max = Math.max(...asyncFuncGroups.map((it) => it.depth || 0)) + 1; - let maxHeight = max * 18 + 6; - funcRow.style.height = `${maxHeight}px`; - funcRow.setAttribute('height', `${maxHeight}`); - } - return res; - }); - }; - funcRow.findHoverStruct = (): void => { - FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); - } - funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - funcRow.selectChangeHandler = this.trace.selectChangeHandler; - funcRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (funcRow.currentContext) { - context = funcRow.currentContext; - } else { - context = funcRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - funcRow.canvasSave(context); - (renders['func'] as FuncRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `func-${asyncFuncGroups[0].funName}-${key}`, - }, - funcRow - ); - funcRow.canvasRestore(context, this.trace); - }; - row.addChildTraceRow(funcRow); + row.addChildTraceRow(this.createDeliverInputEventRow(row, key, asyncFuncGroups)); } }); }; + private createDeliverInputEventRow(parentRow: TraceRow, key: number,asyncFuncGroups: Array): TraceRow { + let funcRow = TraceRow.skeleton(); + funcRow.rowId = `${asyncFuncGroups[0].funName}-${key}`; + funcRow.asyncFuncName = asyncFuncGroups[0].funName; + funcRow.asyncFuncNamePID = key; + funcRow.rowType = TraceRow.ROW_TYPE_FUNC; + funcRow.enableCollapseChart(); //允许折叠泳道图 + funcRow.rowParentId = `${parentRow.rowId}`; + funcRow.rowHidden = !parentRow.expansion; + funcRow.style.width = '100%'; + funcRow.name = `${asyncFuncGroups[0].funName} ${key}`; + funcRow.setAttribute('children', ''); + funcRow.supplierFrame = () => { + return processDeliverInputEventDataSender(key, funcRow!).then((res: Array) => { + this.deliverInputEventSendCallback(res, funcRow, asyncFuncGroups); + return res; + }); + }; + funcRow.findHoverStruct = (): void => { + FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); + } + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.onThreadHandler = rowThreadHandler('func', 'context', { + type: `func-${asyncFuncGroups[0].funName}-${key}`, + }, funcRow, this.trace); + return funcRow; + } + private deliverInputEventSendCallback(res: Array, funcRow: TraceRow, asyncFuncGroups: Array): void { + let isIntersect = (left: any, right: any): boolean => + Math.max(left.startTs + left.dur, right.startTs + right.dur) - Math.min(left.startTs, right.startTs) < + left.dur + right.dur; + let depths: any = []; + let createDepth = (currentDepth: number, index: number): void => { + if (depths[currentDepth] == undefined || !isIntersect(depths[currentDepth], res[index])) { + res[index].depth = currentDepth; + depths[currentDepth] = res[index]; + } else { + createDepth(++currentDepth, index); + } + }; + res.forEach((it, i) => { + res[i].funName = this.funcNameMap.get(res[i].id!); + res[i].threadName = Utils.THREAD_MAP.get(res[i].tid!); + if (it.dur == -1 || it.dur === null || it.dur === undefined) { + it.dur = (TraceRow.range?.endNS || 0) - it.startTs; + it.flag = 'Did not end'; + } + createDepth(0, i); + }); + if (funcRow && !funcRow.isComplete) { + let max = Math.max(...asyncFuncGroups.map((it) => it.depth || 0)) + 1; + let maxHeight = max * 18 + 6; + funcRow.style.height = `${maxHeight}px`; + funcRow.setAttribute('height', `${maxHeight}`); + } + } + + + async init(): Promise { + await this.prepareData(); + if ( + this.eventCountMap['print'] == 0 && + this.eventCountMap['tracing_mark_write'] == 0 && + this.eventCountMap['sched_switch'] == 0 + ) { + return; + } + let time = new Date().getTime(); + let processes = await queryProcess(); + let processFromTable = await queryProcessByTable(); + let processList = Utils.removeDuplicates(processes, processFromTable, 'pid'); + let allJankProcessData = await queryAllJankProcess(); + let allJankProcess: Array = []; + if (allJankProcessData.length > 0) { + allJankProcessData.forEach((name, index) => { + allJankProcess.push(name.pid!); + }); + } + let allTaskPoolPid: Array<{ pid: number }> = []; + if (FlagsConfig.getFlagsConfigEnableStatus('TaskPool')) { + allTaskPoolPid = await queryTaskPoolProcessIds(); + } + let renderServiceProcess = await queryRsProcess(); + info('ProcessList Data size is: ', processList!.length); + await this.initProcessRow(processList, allTaskPoolPid, allJankProcess, renderServiceProcess); + let durTime = new Date().getTime() - time; + info('The time to load the Process data is: ', durTime); + } + + private async prepareData(): Promise { let maxValues = await queryMemFilterIdMaxValue(); maxValues.forEach((it) => { this.filterIdMaxValue.set(it.filterId, it.maxValue); @@ -196,19 +217,10 @@ export class SpProcessChart { soInitNamesArray.forEach((it) => { this.soInitNameMap.set(it.id, it.name); }); - let processNamesArray = await queryAllProcessNames(); - processNamesArray.forEach((it) => { - this.processNameMap.set(it.pid, it.name); - }); - let renderServiceProcess = await queryRsProcess(); let processSrcSliceArray = await queryAllSrcSlices(); processSrcSliceArray.forEach((it) => { this.processSrcSliceMap.set(it.id, it.src); }); - let threadNameArray = await queryAllThreadName(); - threadNameArray.forEach((it) => { - this.threadNameMap.set(it.tid, it.name); - }); let threadFuncMaxDepthArray = await getMaxDepthByTid(); info('Gets the maximum tier per thread , tid and maxDepth'); threadFuncMaxDepthArray.forEach((it) => { @@ -223,47 +235,28 @@ export class SpProcessChart { this.processFuncDataCountMap.set(it.pid, it.slice_count); this.processMemDataCountMap.set(it.pid, it.mem_count); }); - let queryProcessThreadResult = await queryProcessThreads(); - let queryProcessThreadsByTableResult = await queryProcessThreadsByTable(); this.processMem = await queryProcessMem(); - let loadAppStartup: boolean = FlagsConfig.getFlagsConfigEnableStatus('AppStartup'); - if (loadAppStartup) { + info('The amount of initialized process memory data is : ', this.processMem!.length); + this.loadAppStartup = FlagsConfig.getFlagsConfigEnableStatus('AppStartup'); + info('Prepare App startup data '); + if (this.loadAppStartup) { this.startupProcessArr = await queryStartupPidArray(); this.processSoMaxDepth = await queryProcessSoMaxDepth(); } - info('The amount of initialized process memory data is : ', this.processMem!.length); let eventCountList: Array = await queryEventCountMap(); this.eventCountMap = eventCountList.reduce((pre, current) => { pre[`${current.eventName}`] = current.count; return pre; }, {}); + let queryProcessThreadResult = await queryProcessThreads(); + let queryProcessThreadsByTableResult = await queryProcessThreadsByTable(); this.processThreads = Utils.removeDuplicates(queryProcessThreadResult, queryProcessThreadsByTableResult, 'tid'); info('The amount of initialized process threads data is : ', this.processThreads!.length); - if ( - this.eventCountMap['print'] == 0 && - this.eventCountMap['tracing_mark_write'] == 0 && - this.eventCountMap['sched_switch'] == 0 - ) { - return; - } - let time = new Date().getTime(); - let processes = await queryProcess(); - let processFromTable = await queryProcessByTable(); - let processList = Utils.removeDuplicates(processes, processFromTable, 'pid'); - let allJankProcessData = await queryAllJankProcess(); - let allJankProcess: Array = []; - if (allJankProcessData.length > 0) { - allJankProcessData.forEach((name, index) => { - allJankProcess.push(name.pid!); - }); - } - let allTaskPoolPid: Array<{ pid: number }> = []; - if (FlagsConfig.getFlagsConfigEnableStatus('TaskPool')) { - allTaskPoolPid = await queryTaskPoolProcessIds(); - } - info('ProcessList Data size is: ', processList!.length); - for (let i = 0; i < processList.length; i++) { - const it = processList[i]; + } + + private async initProcessRow(pArr: Array, allTaskPoolPid: Array<{ pid: number }>, jankArr: Array, rsProcess: Array) { + for (let i = 0; i < pArr.length; i++) { + const it = pArr[i]; if ( (this.processThreadDataCountMap.get(it.pid) || 0) == 0 && (this.processThreadCountMap.get(it.pid) || 0) == 0 && @@ -272,53 +265,12 @@ export class SpProcessChart { ) { continue; } - let processRow = TraceRow.skeleton(); - processRow.rowId = `${it.pid}`; - processRow.index = i; - processRow.rowType = TraceRow.ROW_TYPE_PROCESS; - processRow.rowParentId = ''; - processRow.style.height = '40px'; - processRow.folder = true; - if ( - SpChartManager.APP_STARTUP_PID_ARR.find((pid) => pid === it.pid) !== undefined || - it.processName === 'render_service' - ) { - processRow.addTemplateTypes('AppStartup'); - } - if (allTaskPoolPid.find((process) => process.pid === it.pid) !== undefined) { - processRow.addTemplateTypes('TaskPool'); - } - processRow.name = `${it.processName || 'Process'} ${it.pid}`; - processRow.supplierFrame = (): Promise> => { - return processDataSender(it.pid || -1, processRow); - }; - processRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - processRow.selectChangeHandler = this.trace.selectChangeHandler; - processRow.onThreadHandler = (useCache): void => { - processRow.canvasSave(this.trace.canvasPanelCtx!); - if (processRow.expansion) { - this.trace.canvasPanelCtx?.clearRect(0, 0, processRow.frame.width, processRow.frame.height); - } else { - (renders['process'] as ProcessRender).renderMainThread( - { - context: this.trace.canvasPanelCtx, - pid: it.pid, - useCache: useCache, - type: `process ${processRow.index} ${it.processName}`, - }, - processRow - ); - } - processRow.canvasRestore(this.trace.canvasPanelCtx!, this.trace); - }; + let processRow = this.createProcessRow(i, it, allTaskPoolPid); this.trace.rowsEL?.appendChild(processRow); - - /** - * App Startup row - */ + /* App Startup row*/ let startupRow: TraceRow | undefined = undefined; let soRow: TraceRow | undefined = undefined; - if (loadAppStartup) { + if (this.loadAppStartup) { if (this.startupProcessArr.find((sp) => sp.pid === it.pid)) { startupRow = this.addStartUpRow(processRow); } @@ -327,289 +279,14 @@ export class SpProcessChart { soRow = this.addSoInitRow(processRow, maxSoDepth.maxDepth); } } - - /** - * Janks Frames - */ + /* Janks Frames */ let actualRow: TraceRow | null = null; let expectedRow: TraceRow | null = null; - if (allJankProcess.indexOf(it.pid) > -1) { - expectedRow = TraceRow.skeleton(); - expectedRow.asyncFuncName = it.processName; - expectedRow.asyncFuncNamePID = it.pid; - expectedRow.rowType = TraceRow.ROW_TYPE_JANK; - expectedRow.rowParentId = `${it.pid}`; - expectedRow.rowHidden = !processRow.expansion; - expectedRow.style.width = '100%'; - expectedRow.name = 'Expected Timeline'; - expectedRow.addTemplateTypes('FrameTimeline'); - expectedRow.setAttribute('children', ''); - expectedRow.supplierFrame = () => { - return processExpectedDataSender(it.pid, expectedRow!).then((res) => { - let maxDepth: number = 1; - let unitHeight: number = 20; - for (let j = 0; j < res.length; j++) { - let expectedItem = res[j]; - if (expectedItem.depth! >= maxDepth) { - maxDepth = expectedItem.depth! + 1; - } - expectedItem.cmdline = this.processNameMap.get(res[j].pid!); - if (res[j].pid! === renderServiceProcess[0].pid) { - expectedItem.cmdline = 'render_service'; - expectedItem.frame_type = expectedItem.cmdline; - } else { - expectedItem.frame_type = 'app'; - } - } - if (expectedRow && !expectedRow.isComplete && res.length > 0) { - let maxHeight: number = maxDepth * unitHeight; - expectedRow.style.height = `${maxHeight}px`; - expectedRow.setAttribute('height', `${maxHeight}`); - if (res[0]) { - let timeLineType = res[0].type; - expectedRow.rowId = `${timeLineType}-${it.pid}`; - expectedRow.setAttribute('frame_type', res[0].frame_type || ''); - } - } - return res; - }); - }; - expectedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - expectedRow.selectChangeHandler = this.trace.selectChangeHandler; - expectedRow.onThreadHandler = (useCache): void => { - let context = expectedRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - expectedRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( - { - context: context, - useCache: useCache, - type: 'expected_frame_timeline_slice', - }, - expectedRow! - ); - expectedRow!.canvasRestore(context, this.trace); - }; - processRow.addChildTraceRow(expectedRow); - actualRow = TraceRow.skeleton(); - actualRow.rowType = TraceRow.ROW_TYPE_JANK; - actualRow.rowParentId = `${it.pid}`; - actualRow.rowHidden = !processRow.expansion; - actualRow.style.width = '100%'; - actualRow.name = 'Actual Timeline'; - actualRow.addTemplateTypes('FrameTimeline'); - actualRow.setAttribute('children', ''); - actualRow.supplierFrame = () => { - return processActualDataSender(it.pid, actualRow!).then((res) => { - let maxDepth: number = 1; - let unitHeight: number = 20; - for (let j = 0; j < res.length; j++) { - let actualItem = res[j]; - if (actualItem.depth! >= maxDepth) { - maxDepth = actualItem.depth! + 1; - } - actualItem.src_slice = this.processSrcSliceMap.get(res[j].id!); - actualItem.cmdline = this.processNameMap.get(res[j].pid!); - if (res[j].pid! === renderServiceProcess[0].pid) { - actualItem.cmdline = 'render_service'; - actualItem.frame_type = actualItem.cmdline; - } else { - actualItem.frame_type = 'app'; - } - } - if (actualRow && !actualRow.isComplete && res.length > 0) { - let maxHeight: number = maxDepth * unitHeight; - actualRow.style.height = `${maxHeight}px`; - actualRow.setAttribute('height', `${maxHeight}`); - if (res[0]) { - let timeLineType = res[0].type; - actualRow.rowId = `${timeLineType}-${it.pid}`; - actualRow.setAttribute('frame_type', res[0].frame_type || ''); - actualRow.dataList = res; - } - } - return res; - }); - }; - actualRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - actualRow.selectChangeHandler = this.trace.selectChangeHandler; - actualRow.onThreadHandler = (useCache): void => { - let context = actualRow!.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - actualRow!.canvasSave(context); - (renders['jank'] as JankRender).renderMainThread( - { - context: context, - useCache: useCache, - type: 'actual_frame_timeline_slice', - }, - actualRow! - ); - actualRow!.canvasRestore(context, this.trace); - }; - processRow.addChildTraceRow(actualRow); + if (jankArr.indexOf(it.pid) > -1) { + expectedRow = this.addExpectedRow(it, processRow, rsProcess); + actualRow = this.addActualRow(it, processRow, rsProcess); } - let offsetYTimeOut: any = undefined; - processRow.addEventListener('expansion-change', (e: any) => { - JankStruct.delJankLineFlag = false; - if (offsetYTimeOut) { - clearTimeout(offsetYTimeOut); - } - if (JankStruct.selectJankStruct !== null && JankStruct.selectJankStruct !== undefined) { - if (e.detail.expansion) { - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes.forEach((linkNodeItem) => { - JankStruct.selectJankStructList?.forEach((selectProcessStruct: any) => { - if (e.detail.rowId == selectProcessStruct.pid) { - JankStruct.selectJankStruct = selectProcessStruct; - JankStruct.hoverJankStruct = selectProcessStruct; - } - }); - if (linkNodeItem[0].rowEL.collect) { - linkNodeItem[0].rowEL.translateY = linkNodeItem[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkNodeItem[0].rowEL.translateY = linkNodeItem[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkNodeItem[0].y = linkNodeItem[0].rowEL!.translateY! + linkNodeItem[0].offsetY; - if (linkNodeItem[1].rowEL.collect) { - linkNodeItem[1].rowEL.translateY = linkNodeItem[1].rowEL.getBoundingClientRect().top - 195; - } else { - linkNodeItem[1].rowEL.translateY = linkNodeItem[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkNodeItem[1].y = linkNodeItem[1].rowEL!.translateY! + linkNodeItem[1].offsetY; - if (actualRow) { - if (linkNodeItem[0].rowEL.rowId == e.detail.rowId) { - linkNodeItem[0].x = ns2xByTimeShaft(linkNodeItem[0].ns, this.trace.timerShaftEL!); - linkNodeItem[0].y = actualRow!.translateY! + linkNodeItem[0].offsetY * 2; - linkNodeItem[0].offsetY = linkNodeItem[0].offsetY * 2; - linkNodeItem[0].rowEL = actualRow!; - } else if (linkNodeItem[1].rowEL.rowId == e.detail.rowId) { - linkNodeItem[1].x = ns2xByTimeShaft(linkNodeItem[1].ns, this.trace.timerShaftEL!); - linkNodeItem[1].y = actualRow!.translateY! + linkNodeItem[1].offsetY * 2; - linkNodeItem[1].offsetY = linkNodeItem[1].offsetY * 2; - linkNodeItem[1].rowEL = actualRow!; - } - } - }); - }, 300); - } else { - if (JankStruct!.selectJankStruct) { - JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); - } - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes?.forEach((linkProcessItem) => { - if (linkProcessItem[0].rowEL.collect) { - linkProcessItem[0].rowEL.translateY = linkProcessItem[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkProcessItem[0].rowEL.translateY = - linkProcessItem[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkProcessItem[0].y = linkProcessItem[0].rowEL!.translateY! + linkProcessItem[0].offsetY; - if (linkProcessItem[1].rowEL.collect) { - linkProcessItem[1].rowEL.translateY = linkProcessItem[1].rowEL.getBoundingClientRect().top - 195; - } else { - linkProcessItem[1].rowEL.translateY = - linkProcessItem[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkProcessItem[1].y = linkProcessItem[1].rowEL!.translateY! + linkProcessItem[1].offsetY; - if (linkProcessItem[0].rowEL.rowParentId == e.detail.rowId) { - if (!linkProcessItem[0].rowEL.collect) { - linkProcessItem[0].x = ns2xByTimeShaft(linkProcessItem[0].ns, this.trace.timerShaftEL!); - linkProcessItem[0].y = processRow!.translateY! + linkProcessItem[0].offsetY / 2; - linkProcessItem[0].offsetY = linkProcessItem[0].offsetY / 2; - linkProcessItem[0].rowEL = processRow!; - } - } else if (linkProcessItem[1].rowEL.rowParentId == e.detail.rowId) { - if (!linkProcessItem[1].rowEL.collect) { - linkProcessItem[1].x = ns2xByTimeShaft(linkProcessItem[1].ns, this.trace.timerShaftEL!); - linkProcessItem[1].y = processRow!.translateY! + linkProcessItem[1].offsetY / 2; - linkProcessItem[1].offsetY = linkProcessItem[1].offsetY / 2; - linkProcessItem[1].rowEL = processRow!; - } - } - }); - }, 300); - } - } else { - if (e.detail.expansion) { - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes.forEach((linkNodeItem) => { - ThreadStruct.selectThreadStructList?.forEach((selectProcessStruct: any) => { - if (e.detail.rowId == selectProcessStruct.pid) { - ThreadStruct.selectThreadStruct = selectProcessStruct; - ThreadStruct.hoverThreadStruct = selectProcessStruct; - } - }); - if (linkNodeItem[0].rowEL.expansion && linkNodeItem[0].backrowEL) { - linkNodeItem[0].rowEL = linkNodeItem[0].backrowEL; - if (linkNodeItem[0].rowEL.collect) { - linkNodeItem[0].rowEL.translateY = linkNodeItem[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkNodeItem[0].rowEL.translateY = - linkNodeItem[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkNodeItem[0].x = ns2xByTimeShaft(linkNodeItem[0].ns, this.trace.timerShaftEL!); - linkNodeItem[0].offsetY = linkNodeItem[0].offsetY * 2; - linkNodeItem[0].y = linkNodeItem[0].rowEL.translateY + linkNodeItem[0].offsetY; - } - if (linkNodeItem[1].rowEL.expansion && linkNodeItem[1].backrowEL) { - linkNodeItem[1].rowEL = linkNodeItem[1].backrowEL; - if (linkNodeItem[1].rowEL.collect) { - linkNodeItem[1].rowEL.translateY = linkNodeItem[1].rowEL.getBoundingClientRect().top - 195; - } else { - linkNodeItem[1].rowEL.translateY = - linkNodeItem[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkNodeItem[1].x = ns2xByTimeShaft(linkNodeItem[1].ns, this.trace.timerShaftEL!); - linkNodeItem[1].offsetY = linkNodeItem[1].offsetY * 2; - linkNodeItem[1].y = linkNodeItem[1].rowEL!.translateY! + linkNodeItem[1].offsetY; - } - }); - }, 300); - } else { - if (ThreadStruct!.selectThreadStruct) { - ThreadStruct.selectThreadStructList?.push(ThreadStruct!.selectThreadStruct); - } - offsetYTimeOut = setTimeout(() => { - this.trace.linkNodes?.forEach((linkProcessItem) => { - if (linkProcessItem[0].rowEL.collect) { - linkProcessItem[0].rowEL.translateY = linkProcessItem[0].rowEL.getBoundingClientRect().top - 195; - } else { - linkProcessItem[0].rowEL.translateY = - linkProcessItem[0].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkProcessItem[0].y = processRow!.translateY + linkProcessItem[0].offsetY; //11 - if (linkProcessItem[1].rowEL.collect) { - linkProcessItem[1].rowEL.translateY = linkProcessItem[1].rowEL.getBoundingClientRect().top - 195; - } else { - linkProcessItem[1].rowEL.translateY = - linkProcessItem[1].rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; - } - linkProcessItem[1].y = linkProcessItem[1].rowEL!.translateY + linkProcessItem[1].offsetY; - if (linkProcessItem[0].rowEL.rowParentId == e.detail.rowId) { - if (!linkProcessItem[0].rowEL.collect) { - linkProcessItem[0].x = ns2xByTimeShaft(linkProcessItem[0].ns, this.trace.timerShaftEL!); - linkProcessItem[0].y = processRow!.translateY! + linkProcessItem[0].offsetY / 2; - linkProcessItem[0].offsetY = linkProcessItem[0].offsetY / 2; - linkProcessItem[0].rowEL = processRow!; - } - } - if (linkProcessItem[1].rowEL.rowParentId == e.detail.rowId) { - if (!linkProcessItem[1].rowEL.collect) { - linkProcessItem[1].x = ns2xByTimeShaft(linkProcessItem[1].ns, this.trace.timerShaftEL!); - linkProcessItem[1].y = processRow!.translateY! + linkProcessItem[1].offsetY / 2; - linkProcessItem[1].offsetY = linkProcessItem[1].offsetY / 2; - linkProcessItem[1].rowEL = processRow!; - } - } - JankStruct.selectJankStructList = []; - }); - }, 300); - } - } - let refreshTimeOut = setTimeout(() => { - this.trace.refreshCanvas(true); - clearTimeout(refreshTimeOut); - }, 360); - }); + this.addProcessRowListener(processRow, actualRow); this.renderRow = null; if (it.processName === 'render_service') { this.addThreadList(it, processRow, expectedRow, actualRow, soRow, startupRow); @@ -622,8 +299,253 @@ export class SpProcessChart { } await this.trace.chartManager?.frameTimeChart.initAnimatedScenesChart(processRow, it, expectedRow!, actualRow!); } - let durTime = new Date().getTime() - time; - info('The time to load the Process data is: ', durTime); + } + + private createProcessRow(index: number, process: any, allTaskPoolPid: Array<{ pid: number }>) { + let processRow = TraceRow.skeleton(); + processRow.rowId = `${process.pid}`; + processRow.index = index; + processRow.rowType = TraceRow.ROW_TYPE_PROCESS; + processRow.rowParentId = ''; + processRow.style.height = '40px'; + processRow.folder = true; + if ( + SpChartManager.APP_STARTUP_PID_ARR.find((pid) => pid === process.pid) !== undefined || + process.processName === 'render_service' + ) { + processRow.addTemplateTypes('AppStartup'); + } + if (allTaskPoolPid.find((process) => process.pid === process.pid) !== undefined) { + processRow.addTemplateTypes('TaskPool'); + } + processRow.name = `${process.processName || 'Process'} ${process.pid}`; + processRow.supplierFrame = (): Promise> => { + return processDataSender(process.pid || -1, processRow); + }; + processRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + processRow.selectChangeHandler = this.trace.selectChangeHandler; + processRow.onThreadHandler = rowThreadHandler('process', 'context', { + pid: process.pid, + type: `process ${processRow.index} ${process.processName}` + }, processRow, this.trace); + return processRow; + } + + addProcessRowListener(processRow: TraceRow, actualRow: TraceRow | null) { + let offsetYTimeOut: any = undefined; + processRow.addEventListener('expansion-change', (e: any) => { + JankStruct.delJankLineFlag = false; + if (offsetYTimeOut) { + clearTimeout(offsetYTimeOut); + } + if (JankStruct.selectJankStruct !== null && JankStruct.selectJankStruct !== undefined) { + if (e.detail.expansion) { + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes.forEach((linkNodeItem) => this.handler1(e, linkNodeItem, actualRow)); + }, 300); + } else { + if (JankStruct!.selectJankStruct) { + JankStruct.selectJankStructList?.push(JankStruct!.selectJankStruct); + } + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes?.forEach((linkProcessItem) => this.handler2(e, linkProcessItem, processRow)); + }, 300); + } + } else { + if (e.detail.expansion) { + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes.forEach((linkNodeItem) => this.handler3(e, linkNodeItem)); + }, 300); + } else { + if (ThreadStruct!.selectThreadStruct) { + ThreadStruct.selectThreadStructList?.push(ThreadStruct!.selectThreadStruct); + } + offsetYTimeOut = setTimeout(() => { + this.trace.linkNodes?.forEach((linkProcessItem) => { + this.handler4(e, linkProcessItem, processRow); + JankStruct.selectJankStructList = []; + }); + }, 300); + } + } + let refreshTimeOut = setTimeout(() => { + this.trace.refreshCanvas(true); + clearTimeout(refreshTimeOut); + }, 360); + }); + } + + handler1(e: any, linkItem: PairPoint[], actualRow: TraceRow | null) { + JankStruct.selectJankStructList?.forEach((selectProcessStruct: any) => { + if (e.detail.rowId == selectProcessStruct.pid) { + JankStruct.selectJankStruct = selectProcessStruct; + JankStruct.hoverJankStruct = selectProcessStruct; + } + }); + this.updatePairPointTranslateY(linkItem[0]); + linkItem[0].y = linkItem[0].rowEL!.translateY! + linkItem[0].offsetY; + this.updatePairPointTranslateY(linkItem[1]); + linkItem[1].y = linkItem[1].rowEL!.translateY! + linkItem[1].offsetY; + if (actualRow) { + if (linkItem[0].rowEL.rowId == e.detail.rowId) { + linkItem[0].x = ns2xByTimeShaft(linkItem[0].ns, this.trace.timerShaftEL!); + linkItem[0].y = actualRow!.translateY! + linkItem[0].offsetY * 2; + linkItem[0].offsetY = linkItem[0].offsetY * 2; + linkItem[0].rowEL = actualRow!; + } else if (linkItem[1].rowEL.rowId == e.detail.rowId) { + linkItem[1].x = ns2xByTimeShaft(linkItem[1].ns, this.trace.timerShaftEL!); + linkItem[1].y = actualRow!.translateY! + linkItem[1].offsetY * 2; + linkItem[1].offsetY = linkItem[1].offsetY * 2; + linkItem[1].rowEL = actualRow!; + } + } + } + + handler2(e: any, linkItem: PairPoint[], processRow: TraceRow) { + this.updatePairPointTranslateY(linkItem[0]); + linkItem[0].y = linkItem[0].rowEL!.translateY! + linkItem[0].offsetY; + this.updatePairPointTranslateY(linkItem[1]); + linkItem[1].y = linkItem[1].rowEL!.translateY! + linkItem[1].offsetY; + if (linkItem[0].rowEL.rowParentId == e.detail.rowId) { + this.updatePairPoint(linkItem[0], processRow); + } else if (linkItem[1].rowEL.rowParentId == e.detail.rowId) { + this.updatePairPoint(linkItem[1], processRow); + } + } + + handler3(e: any, linkItem: PairPoint[]) { + ThreadStruct.selectThreadStructList?.forEach((selectProcessStruct: any) => { + if (e.detail.rowId == selectProcessStruct.pid) { + ThreadStruct.selectThreadStruct = selectProcessStruct; + ThreadStruct.hoverThreadStruct = selectProcessStruct; + } + }); + if (linkItem[0].rowEL.expansion && linkItem[0].backrowEL) { + this.updatePairPointTranslateY(linkItem[0]); + linkItem[0].x = ns2xByTimeShaft(linkItem[0].ns, this.trace.timerShaftEL!); + linkItem[0].y = linkItem[0].rowEL.translateY + linkItem[0].offsetY; + linkItem[0].offsetY = linkItem[0].offsetY * 2; + linkItem[0].rowEL = linkItem[0].backrowEL; + } + if (linkItem[1].rowEL.expansion && linkItem[1].backrowEL) { + this.updatePairPointTranslateY(linkItem[1]); + linkItem[1].x = ns2xByTimeShaft(linkItem[1].ns, this.trace.timerShaftEL!); + linkItem[1].y = linkItem[1].rowEL!.translateY! + linkItem[1].offsetY; + linkItem[1].offsetY = linkItem[1].offsetY * 2; + linkItem[1].rowEL = linkItem[1].backrowEL; + } + } + + handler4(e: any, linkItem: PairPoint[], processRow: TraceRow) { + this.updatePairPointTranslateY(linkItem[0]); + linkItem[0].y = processRow!.translateY + linkItem[0].offsetY; + this.updatePairPointTranslateY(linkItem[1]); + linkItem[1].y = linkItem[1].rowEL!.translateY + linkItem[1].offsetY; + if (linkItem[0].rowEL.rowParentId == e.detail.rowId) { + this.updatePairPoint(linkItem[0], processRow); + } + if (linkItem[1].rowEL.rowParentId == e.detail.rowId) { + this.updatePairPoint(linkItem[1], processRow); + } + } + + updatePairPointTranslateY(pair: PairPoint) { + if (pair.rowEL.collect) { + pair.rowEL.translateY = pair.rowEL.getBoundingClientRect().top - 195; + } else { + pair.rowEL.translateY = pair.rowEL.offsetTop - this.trace.rowsPaneEL!.scrollTop; + } + } + + updatePairPoint(pair: PairPoint, processRow: TraceRow) { + if (!pair.rowEL.collect) { + pair.x = ns2xByTimeShaft(pair.ns, this.trace.timerShaftEL!); + pair.y = processRow!.translateY! + pair.offsetY / 2; + pair.offsetY = pair.offsetY / 2; + pair.rowEL = processRow!; + } + } + + addExpectedRow(process: any, processRow: TraceRow, renderServiceProcess: Array): TraceRow { + let expectedRow = TraceRow.skeleton(); + expectedRow.asyncFuncName = process.processName; + expectedRow.asyncFuncNamePID = process.pid; + expectedRow.rowType = TraceRow.ROW_TYPE_JANK; + expectedRow.rowParentId = `${process.pid}`; + expectedRow.rowHidden = !processRow.expansion; + expectedRow.style.width = '100%'; + expectedRow.name = 'Expected Timeline'; + expectedRow.addTemplateTypes('FrameTimeline'); + expectedRow.setAttribute('children', ''); + expectedRow.supplierFrame = async () => { + let res = await processExpectedDataSender(process.pid, expectedRow!); + this.jankSenderCallback(res, 'expected', process, expectedRow, renderServiceProcess); + return res; + }; + expectedRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + expectedRow.selectChangeHandler = this.trace.selectChangeHandler; + expectedRow.onThreadHandler = rowThreadHandler('jank', 'context', { + type: 'expected_frame_timeline_slice', + }, expectedRow, this.trace); + processRow.addChildTraceRow(expectedRow); + return expectedRow; + } + + addActualRow(process: any, processRow: TraceRow, renderServiceProcess: Array): TraceRow { + let actualRow = TraceRow.skeleton(); + actualRow.rowType = TraceRow.ROW_TYPE_JANK; + actualRow.rowParentId = `${process.pid}`; + actualRow.rowHidden = !processRow.expansion; + actualRow.style.width = '100%'; + actualRow.name = 'Actual Timeline'; + actualRow.addTemplateTypes('FrameTimeline'); + actualRow.setAttribute('children', ''); + actualRow.supplierFrame = async () => { + let res = await processActualDataSender(process.pid, actualRow!); + this.jankSenderCallback(res, 'actual', process, actualRow, renderServiceProcess); + return res; + }; + actualRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + actualRow.selectChangeHandler = this.trace.selectChangeHandler; + actualRow.onThreadHandler = rowThreadHandler('jank', 'context', { + type: 'actual_frame_timeline_slice', + }, actualRow, this.trace); + processRow.addChildTraceRow(actualRow); + return actualRow; + } + + jankSenderCallback(res: JankStruct[], type: string, process: any, row: TraceRow, renderServiceProcess: Array) { + let maxDepth: number = 1; + let unitHeight: number = 20; + for (let j = 0; j < res.length; j++) { + let struct = res[j]; + if (struct.depth! >= maxDepth) { + maxDepth = struct.depth! + 1; + } + if (type === 'actual') { + struct.src_slice = this.processSrcSliceMap.get(res[j].id!); + } + struct.cmdline = Utils.PROCESS_MAP.get(res[j].pid!); + if (res[j].pid! === renderServiceProcess[0].pid) { + struct.cmdline = 'render_service'; + struct.frame_type = struct.cmdline; + } else { + struct.frame_type = 'app'; + } + } + if (row && !row.isComplete && res.length > 0) { + let maxHeight: number = maxDepth * unitHeight; + row.style.height = `${maxHeight}px`; + row.setAttribute('height', `${maxHeight}`); + if (res[0]) { + let timeLineType = res[0].type; + row.rowId = `${timeLineType}-${process.pid}`; + row.setAttribute('frame_type', res[0].frame_type || ''); + if (type === 'actual') { + row.dataList = res; + } + } + } } addStartUpRow(processRow: TraceRow): TraceRow { @@ -655,24 +577,9 @@ export class SpProcessChart { } return res; }); - startupRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (startupRow.currentContext) { - context = startupRow.currentContext; - } else { - context = startupRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - startupRow.canvasSave(context); - (renders['app-start-up'] as AppStartupRender).renderMainThread( - { - appStartupContext: context, - useCache: useCache, - type: `app-startup ${processRow.rowId}`, - }, - startupRow - ); - startupRow.canvasRestore(context, this.trace); - }; + startupRow.onThreadHandler = rowThreadHandler('app-start-up', 'appStartupContext', { + type: `app-startup ${processRow.rowId}`, + }, startupRow, this.trace); processRow.addChildTraceRow(startupRow); return startupRow; } @@ -708,24 +615,9 @@ export class SpProcessChart { }); return res; }); - soRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (soRow.currentContext) { - context = soRow.currentContext; - } else { - context = soRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - soRow.canvasSave(context); - (renders['app-so-init'] as SoRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `static-init ${processRow.rowId}`, - }, - soRow - ); - soRow.canvasRestore(context, this.trace); - }; + soRow.onThreadHandler = rowThreadHandler('app-so-init', 'context', { + type: `static-init ${processRow.rowId}`, + }, soRow, this.trace); processRow.addChildTraceRow(soRow); return soRow; } @@ -765,162 +657,158 @@ export class SpProcessChart { threadRow.setAttribute('children', ''); threadRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; threadRow.selectChangeHandler = this.trace.selectChangeHandler; - threadRow.findHoverStruct = (): void => { - let arr = threadRow.dataListCache.filter( - (re) => re.frame && isFrameContainPoint(re.frame, threadRow.hoverX, threadRow.hoverY, true, false) - ); - let runItem = arr.find(it => it.state === 'Running'); - if (runItem) { - ThreadStruct.hoverThreadStruct = runItem; + threadRow.findHoverStruct = (): void => this.threadRowFindHoverStruct(threadRow); + threadRow.supplierFrame = async (): Promise> => { + const res = await threadDataSender(thread.tid || 0, it.pid || 0, threadRow); + if (res === true) { + return []; } else { - let otherItem = arr.find(it => it.state !== 'S'); - if (otherItem) { - ThreadStruct.hoverThreadStruct = otherItem; - } else { - ThreadStruct.hoverThreadStruct = arr[0]; + let rs = res as ThreadStruct[]; + if (rs.length <= 0 && !threadRow.isComplete) { + this.trace.refreshCanvas(true); } + return rs; } - } - threadRow.supplierFrame = (): Promise> => { - return threadDataSender(thread.tid || 0, it.pid || 0, threadRow).then((res) => { - if (res === true) { - // threadRow.rowDiscard = true; - return []; - } else { - let rs = res as ThreadStruct[]; - if (rs.length <= 0 && !threadRow.isComplete) { - this.trace.refreshCanvas(true); - } - return rs; - } - }); }; - threadRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (threadRow.currentContext) { - context = threadRow.currentContext; + threadRow.onThreadHandler = rowThreadHandler('thread', 'context', { + type: `thread ${thread.tid} ${thread.threadName}`, + translateY: threadRow.translateY, + }, threadRow, this.trace); + this.insertThreadRowToDocument(it, j, thread, processRow, threadRow, threads, threadRowArr, actualRow, expectedRow, startupRow, soRow); + this.addFuncStackRow(it, thread, j, threads, threadRowArr, threadRow, processRow); + if ((thread.switchCount || 0) === 0) { + threadRow.rowDiscard = true; + } + } + } + + threadRowFindHoverStruct(threadRow: TraceRow) { + let arr = threadRow.dataListCache.filter( + (re) => re.frame && isFrameContainPoint(re.frame, threadRow.hoverX, threadRow.hoverY, true, false) + ); + let runItem = arr.find(it => it.state === 'Running'); + if (runItem) { + ThreadStruct.hoverThreadStruct = runItem; + } else { + let otherItem = arr.find(it => it.state !== 'S'); + if (otherItem) { + ThreadStruct.hoverThreadStruct = otherItem; + } else { + ThreadStruct.hoverThreadStruct = arr[0]; + } + } + } + + insertThreadRowToDocument( + it: any, + index: number, + thread: ThreadStruct, + processRow: TraceRow, + threadRow: TraceRow, + threads: ThreadStruct[], + threadRowArr: TraceRow[], + actualRow: TraceRow | null, + expectedRow: TraceRow | null, + startupRow: TraceRow | null | undefined, + soRow: TraceRow | null | undefined + ) { + if (it.processName === 'render_service') { + if (threadRow.name === `${it.processName} ${it.pid}`) { + this.renderRow = threadRow; + } + let flag = threads.length === index + 1 && !this.threadFuncMaxDepthMap.has(`${thread.upid}-${thread.tid}`); + processRow.sortRenderServiceData(threadRow, threadRow, threadRowArr, flag); + } else { + if (threadRow.rowId === threadRow.rowParentId) { + if (actualRow !== null) { + processRow.addChildTraceRowAfter(threadRow, actualRow); + } else if (expectedRow !== null) { + processRow.addChildTraceRowAfter(threadRow, expectedRow); + } else if (soRow) { + processRow.addChildTraceRowAfter(threadRow, soRow); + } else if (startupRow) { + processRow.addChildTraceRowAfter(threadRow, startupRow); } else { - context = threadRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + processRow.addChildTraceRowSpecifyLocation(threadRow, 0); } - threadRow.canvasSave(context); - (renders['thread'] as ThreadRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `thread ${thread.tid} ${thread.threadName}`, - translateY: threadRow.translateY, - }, - threadRow - ); - threadRow.canvasRestore(context, this.trace); + } else { + processRow.addChildTraceRow(threadRow); + } + } + } + + addFuncStackRow( + process: any, + thread: any, + index: number, + threads: Array, + threadRowArr: Array, + threadRow: TraceRow, + processRow: TraceRow + ) { + if (this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) != undefined) { + let max = this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) || 1; + let maxHeight = max * 18 + 6; + let funcRow = TraceRow.skeleton(); + funcRow.rowId = `${thread.tid}`; + funcRow.rowType = TraceRow.ROW_TYPE_FUNC; + funcRow.enableCollapseChart(); //允许折叠泳道图 + funcRow.rowParentId = `${process.pid}`; + funcRow.rowHidden = !processRow.expansion; + funcRow.checkType = threadRow.checkType; + funcRow.style.width = '100%'; + funcRow.style.height = `${maxHeight}px`; + funcRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; + funcRow.namePrefix = `${thread.threadName || 'Thread'}`; + funcRow.setAttribute('children', ''); + funcRow.supplierFrame = async (): Promise> => { + const rs = await funcDataSender(thread.tid || 0, thread.upid || 0, funcRow); + return this.funDataSenderCallback(rs, funcRow, thread); }; - if (it.processName === 'render_service') { - if (threadRow.name === `${it.processName} ${it.pid}`) { - this.renderRow = threadRow; - } - let flag = threads.length === j + 1 && !this.threadFuncMaxDepthMap.has(`${thread.upid}-${thread.tid}`); - processRow.sortRenderServiceData(threadRow, threadRow, threadRowArr, flag); + funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + funcRow.selectChangeHandler = this.trace.selectChangeHandler; + funcRow.findHoverStruct = (): void => { + FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); + } + funcRow.onThreadHandler = rowThreadHandler('func', 'context', { + type: `func${thread.tid}${thread.threadName}`, + }, funcRow, this.trace); + if (process.processName === 'render_service') { + let flag = threads.length === index + 1; + processRow.sortRenderServiceData(funcRow, threadRow, threadRowArr, flag); } else { - if (threadRow.rowId === threadRow.rowParentId) { - if (actualRow !== null) { - processRow.addChildTraceRowAfter(threadRow, actualRow); - } else if (expectedRow !== null) { - processRow.addChildTraceRowAfter(threadRow, expectedRow); - } else if (soRow) { - processRow.addChildTraceRowAfter(threadRow, soRow); - } else if (startupRow) { - processRow.addChildTraceRowAfter(threadRow, startupRow); - } else { - processRow.addChildTraceRowSpecifyLocation(threadRow, 0); - } - } else { - processRow.addChildTraceRow(threadRow); - } + processRow.addChildTraceRowAfter(funcRow, threadRow); } - if (this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) != undefined) { - let max = this.threadFuncMaxDepthMap.get(`${thread.upid}-${thread.tid}`) || 1; - let maxHeight = max * 18 + 6; - let funcRow = TraceRow.skeleton(); - funcRow.rowId = `${thread.tid}`; - funcRow.rowType = TraceRow.ROW_TYPE_FUNC; - funcRow.enableCollapseChart(); //允许折叠泳道图 - funcRow.rowParentId = `${it.pid}`; - funcRow.rowHidden = !processRow.expansion; - funcRow.checkType = threadRow.checkType; - funcRow.style.width = '100%'; - funcRow.style.height = `${maxHeight}px`; - funcRow.name = `${thread.threadName || 'Thread'} ${thread.tid}`; - funcRow.namePrefix = `${thread.threadName || 'Thread'}`; - funcRow.setAttribute('children', ''); - funcRow.supplierFrame = (): Promise> => { - return funcDataSender(thread.tid || 0, thread.upid || 0, funcRow).then( - (rs: Array | boolean) => { - if (rs === true) { - funcRow.rowDiscard = true; - return []; - } else { - let funs = rs as FuncStruct[]; - if (funs.length > 0) { - funs.forEach((fun, index) => { - funs[index].itid = thread.utid; - funs[index].ipid = thread.upid; - funs[index].funName = this.funcNameMap.get(funs[index].id!); - if (Utils.isBinder(fun)) { - } else { - if (fun.nofinish) { - fun.flag = 'Did not end'; - } - } - }); - } else { - this.trace.refreshCanvas(true); - } - return funs; - } - } - ); - }; - funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; - funcRow.selectChangeHandler = this.trace.selectChangeHandler; - funcRow.findHoverStruct = (): void => { - FuncStruct.hoverFuncStruct = funcRow.getHoverStruct(); - } - funcRow.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (funcRow.currentContext) { - context = funcRow.currentContext; + } + } + + funDataSenderCallback(rs: Array | boolean, funcRow: TraceRow, thread: ThreadStruct): FuncStruct[] { + if (rs === true) { + funcRow.rowDiscard = true; + return []; + } else { + let funs = rs as FuncStruct[]; + if (funs.length > 0) { + funs.forEach((fun, index) => { + funs[index].itid = thread.utid; + funs[index].ipid = thread.upid; + funs[index].funName = this.funcNameMap.get(funs[index].id!); + if (Utils.isBinder(fun)) { } else { - context = funcRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; + if (fun.nofinish) { + fun.flag = 'Did not end'; + } } - funcRow.canvasSave(context); - (renders.func as FuncRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `func${thread.tid}${thread.threadName}`, - }, - funcRow - ); - funcRow.canvasRestore(context, this.trace); - }; - if (it.processName === 'render_service') { - let flag = threads.length === j + 1; - processRow.sortRenderServiceData(funcRow, threadRow, threadRowArr, flag); - } else { - processRow.addChildTraceRowAfter(funcRow, threadRow); - } - } - if ((thread.switchCount || 0) === 0) { - threadRow.rowDiscard = true; + }); + } else { + this.trace.refreshCanvas(true); } + return funs; } } //进程内存信息 - addProcessMemInfo( - it: { pid: number | null; processName: string | null }, - processRow: TraceRow, - ) { + addProcessMemInfo(it: { pid: number | null; processName: string | null }, processRow: TraceRow) { let processMem = this.processMem.filter((mem) => mem.pid === it.pid); processMem.forEach((mem) => { let row = TraceRow.skeleton(); @@ -935,11 +823,7 @@ export class SpProcessChart { row.favoriteChangeHandler = this.trace.favoriteChangeHandler; row.selectChangeHandler = this.trace.selectChangeHandler; row.focusHandler = (): void => { - this.trace.displayTip( - row, - ProcessMemStruct.hoverProcessMemStruct, - `${ProcessMemStruct.hoverProcessMemStruct?.value || '0'}` - ); + this.trace.displayTip(row, ProcessMemStruct.hoverProcessMemStruct, `${ProcessMemStruct.hoverProcessMemStruct?.value || '0'}`); }; row.findHoverStruct = (): void => { ProcessMemStruct.hoverProcessMemStruct = row.getHoverStruct(false); @@ -962,24 +846,9 @@ export class SpProcessChart { } return resultProcess; }); - row.onThreadHandler = (useCache): void => { - let context: CanvasRenderingContext2D; - if (row.currentContext) { - context = row.currentContext; - } else { - context = row.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - row.canvasSave(context); - (renders.mem as MemRender).renderMainThread( - { - context: context, - useCache: useCache, - type: `mem ${mem.trackId} ${mem.trackName}`, - }, - row - ); - row.canvasRestore(context, this.trace); - }; + row.onThreadHandler = rowThreadHandler('mem', 'context', { + type: `mem ${mem.trackId} ${mem.trackName}`, + }, row, this.trace); if (this.renderRow && row.name === 'H:PreferredFrameRate') { processRow.addChildTraceRowBefore(row, this.renderRow); } else { @@ -1016,10 +885,7 @@ export class SpProcessChart { } let currentDepth = 0; let index = i; - while ( - depthArray[currentDepth] !== undefined && - isIntersect(depthArray[currentDepth], asyncFunctions[index]) - ) { + while (depthArray[currentDepth] !== undefined && isIntersect(depthArray[currentDepth], asyncFunctions[index])) { currentDepth++; } asyncFunctions[index].depth = currentDepth; @@ -1045,24 +911,9 @@ export class SpProcessChart { funcRow.supplier = (): Promise => new Promise((resolve) => resolve(asyncFunctions)); funcRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; funcRow.selectChangeHandler = this.trace.selectChangeHandler; - funcRow.onThreadHandler = (cacheFlag): void => { - let context: CanvasRenderingContext2D; - if (funcRow.currentContext) { - context = funcRow.currentContext; - } else { - context = funcRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; - } - funcRow.canvasSave(context); - (renders.func as FuncRender).renderMainThread( - { - context: context, - useCache: cacheFlag, - type: `func-${asyncFunctions[0].funName}-${it.pid}`, - }, - funcRow - ); - funcRow.canvasRestore(context, this.trace); - }; + funcRow.onThreadHandler = rowThreadHandler('func', 'context', { + type: `func-${asyncFunctions[0].funName}-${it.pid}`, + }, funcRow, this.trace); processRow.addChildTraceRow(funcRow); } }); diff --git a/ide/src/trace/component/chart/SpSegmentationChart.ts b/ide/src/trace/component/chart/SpSegmentationChart.ts index 311651cf7f0a8084d27794f2d0c103dd2d529c9d..c4d201560b2b195549ada764b6b29340cb3d7c2e 100644 --- a/ide/src/trace/component/chart/SpSegmentationChart.ts +++ b/ide/src/trace/component/chart/SpSegmentationChart.ts @@ -23,6 +23,7 @@ import { queryIrqList } from '../../database/sql/Irq.sql'; import { type BaseStruct } from '../../bean/BaseStruct'; import { type ThreadRender, ThreadStruct } from '../../database/ui-worker/ProcedureWorkerThread'; import { StateGroup } from '../../bean/StateModle'; +import { queryAllFuncNames } from '../../database/sql/Func.sql'; const UNIT_HEIGHT: number = 20; const MS_TO_US: number = 1000000; const MIN_HEIGHT: number = 2; @@ -76,8 +77,8 @@ export class SpSegmentationChart { SpSegmentationChart.trace.refreshCanvas(false); }; - // binder联动调用 - static setBinderChartData(data: Array>): void { + // binder联动调用 + static setBinderChartData(data: Array>): void { BinderStruct.maxHeight = 0; SpSegmentationChart.binderRow!.dataList = []; SpSegmentationChart.binderRow!.dataListCache = []; @@ -121,53 +122,70 @@ export class SpSegmentationChart { static tabHover(type: string, tableIsHover: boolean = false, cycle: number = -1): void { CpuFreqExtendStruct.isTabHover = tableIsHover; if (type === 'CPU-FREQ' || type === 'GPU-FREQ' || type === 'SCHED-SWITCH') { - CpuFreqExtendStruct.hoverType = type - if (tableIsHover) { - if (type === 'CPU-FREQ') { - CpuFreqExtendStruct.cpuCycle = cycle; - SpSegmentationChart.cpuRow!.isHover = false; - CpuFreqExtendStruct.gpuCycle = -1; - CpuFreqExtendStruct.schedCycle = -1; - } else if (type === 'GPU-FREQ') { - CpuFreqExtendStruct.gpuCycle = cycle; - SpSegmentationChart.GpuRow!.isHover = false; - CpuFreqExtendStruct.cpuCycle = -1; + // 竖线显示处理 + if (type === 'SCHED-SWITCH') { + CpuFreqExtendStruct.cpuCycle = -1; + CpuFreqExtendStruct.gpuCycle = -1; + if (cycle === CpuFreqExtendStruct.schedCycle) { + CpuFreqExtendStruct.isTabHover = false; CpuFreqExtendStruct.schedCycle = -1; } else { + CpuFreqExtendStruct.isTabHover = true; CpuFreqExtendStruct.schedCycle = cycle; - SpSegmentationChart.schedRow!.isHover = false; - CpuFreqExtendStruct.gpuCycle = -1; - CpuFreqExtendStruct.cpuCycle = -1; + BinderStruct.isTabHover = false; } - } else { - if (type === 'CPU-FREQ') { + } else if (type === 'CPU-FREQ') { + CpuFreqExtendStruct.gpuCycle = -1; + CpuFreqExtendStruct.schedCycle = -1; + if (cycle === CpuFreqExtendStruct.cpuCycle) { + CpuFreqExtendStruct.isTabHover = false; CpuFreqExtendStruct.cpuCycle = -1; - } else if (type === 'GPU-FREQ') { + } else { + CpuFreqExtendStruct.isTabHover = true; + CpuFreqExtendStruct.cpuCycle = cycle; + BinderStruct.isTabHover = false; + } + } else if (type === 'GPU-FREQ') { + CpuFreqExtendStruct.cpuCycle = -1; + CpuFreqExtendStruct.schedCycle = -1; + if (cycle === CpuFreqExtendStruct.gpuCycle) { CpuFreqExtendStruct.gpuCycle = -1; + CpuFreqExtendStruct.isTabHover = false; } else { - CpuFreqExtendStruct.schedCycle = -1; + CpuFreqExtendStruct.gpuCycle = cycle; + CpuFreqExtendStruct.isTabHover = true; + BinderStruct.isTabHover = false; } - CpuFreqExtendStruct.hoverCpuFreqStruct = undefined; + } + CpuFreqExtendStruct.hoverType = type } else if (type === 'BINDER') { - if (tableIsHover) { - BinderStruct.hoverCycle = cycle; - } else { + if (cycle === BinderStruct.hoverCycle) { BinderStruct.hoverCycle = -1; + BinderStruct.isTabHover = false; + CpuFreqExtendStruct.isTabHover = false; + } else { + BinderStruct.hoverCycle = cycle; + BinderStruct.isTabHover = true; } } - SpSegmentationChart.trace.refreshCanvas(true, 'flagChange'); + SpSegmentationChart.trace.refreshCanvas(false); } constructor(trace: SpSystemTrace) { SpSegmentationChart.trace = trace; } async init() { - await this.initFolder(); - await this.initCpuFreq(); - await this.initGpuTrace(); - await this.initSchedTrace(); - await this.initAllStates(); - await this.initBinderTrace(); + let funArr = await queryAllFuncNames(); + if (funArr.length > 0) { + await this.initFolder(); + await this.initCpuFreq(); + await this.initGpuTrace(); + await this.initSchedTrace(); + await this.initBinderTrace(); + await this.initAllStates(); + } else { + return + } } async initFolder() { let row = TraceRow.skeleton(); diff --git a/ide/src/trace/component/chart/SpVmTrackerChart.ts b/ide/src/trace/component/chart/SpVmTrackerChart.ts index b2a959c399118d1c9bb9d114ca3689f0df6956f3..4fe370e73a06bc002fd7bb5693c6246feb05b168 100644 --- a/ide/src/trace/component/chart/SpVmTrackerChart.ts +++ b/ide/src/trace/component/chart/SpVmTrackerChart.ts @@ -97,11 +97,14 @@ export class VmTrackerChart { if (isExistsDma[0].data_exists) { await this.initDmaRow(); } + await this.initGpuData(); + } + + private async initGpuData() { const isExistsGpuMemory = await queryisExistsGpuMemoryData(this.memoryConfig.iPid); const isExistsGpuResource = await queryisExistsGpuResourceData(this.scratchId); const isExistsGraph = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.graph_pss'"); const isExistsGl = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.gl_pss'"); - if ( // @ts-ignore isExistsGpuMemory[0].data_exists || @@ -445,6 +448,11 @@ export class VmTrackerChart { } ), ]; + this.addHandleEventByGpuTotalRow(gpuTotalRow); + this.gpuFolder.addChildTraceRow(gpuTotalRow); + } + + private addHandleEventByGpuTotalRow(gpuTotalRow: TraceRow): void { gpuTotalRow.onRowSettingChangeHandler = (setting): void => { if (setting && setting.length > 0) { gpuTotalRow.dataListCache = []; @@ -461,7 +469,6 @@ export class VmTrackerChart { return gpuTotalData; }); }; - this.gpuFolder.addChildTraceRow(gpuTotalRow); } private async addGpuWindowRow(): Promise { @@ -501,6 +508,11 @@ export class VmTrackerChart { gpuWindowRow.rowSetting = 'enable'; gpuWindowRow.rowSettingList = settings; gpuWindowRow.addTemplateTypes('sys-memory'); + this.addHandleEventByGpuWindowRow(gpuWindowRow); + this.gpuFolder.addChildTraceRow(gpuWindowRow); + } + + private addHandleEventByGpuWindowRow(gpuWindowRow: TraceRow): void { gpuWindowRow.onRowSettingChangeHandler = (setting) => { if (setting && setting.length > 0) { let split = setting[0].split('-'); @@ -521,7 +533,6 @@ export class VmTrackerChart { } ); }; - this.gpuFolder.addChildTraceRow(gpuWindowRow); } private initTraceRow(rowName: string, type: string, rowParentId: string): TraceRow { diff --git a/ide/src/trace/component/chart/VSync.ts b/ide/src/trace/component/chart/VSync.ts index 3687ffbf2b25fa99ac5935ffe3335c525c9b6c9c..eb91ccfc770cadc3b514117817223f181aee6ce8 100644 --- a/ide/src/trace/component/chart/VSync.ts +++ b/ide/src/trace/component/chart/VSync.ts @@ -24,11 +24,9 @@ interface VSyncData { let vSyncDataList: VSyncData[] = []; let vSyncEnable = false; let isSingle = false; -let isQuery = false; export function resetVSync(): void { vSyncEnable = false; - isQuery = false; } export const querySfVSyncData = (): Promise> => @@ -90,7 +88,6 @@ export async function setVSyncData(): Promise { } }); vSyncDataList = sfvSyncData; - isQuery = true; } /** @@ -134,12 +131,10 @@ export function drawVSync(ctx: CanvasRenderingContext2D, width: number, height: * enable/disable SingleVSync */ export function enableVSync(press: boolean, ev: KeyboardEvent, handler?: Function): void { - if (!isQuery) { + if (ev.key.toLocaleLowerCase() === 'v' && !ev.ctrlKey) { window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Query VSync' }); setVSyncData(); window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Query VSync' }); - } - if (ev.key.toLocaleLowerCase() === 'v' && !ev.ctrlKey) { vSyncEnable = !vSyncEnable; handler?.(); } diff --git a/ide/src/trace/component/setting/SpHisysEvent.html.ts b/ide/src/trace/component/setting/SpHisysEvent.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..6df54d17929014dc71edc203c367ffe2d13e0a60 --- /dev/null +++ b/ide/src/trace/component/setting/SpHisysEvent.html.ts @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const SpHiSysEventHtml = ` +
+
+
+ Start Hisystem Event Tracker Record + +
+
+
+
+ Domain + Record Domain Name +
+ + +
+
+
+ EventName + Record Event Name +
+ + +
+
`; diff --git a/ide/src/trace/component/setting/SpHisysEvent.ts b/ide/src/trace/component/setting/SpHisysEvent.ts index 043771940b74d2f1639646e7be7c80a4ae6cffc8..b4dd116a48990ffac6a75b4619501d9ea08a0a74 100644 --- a/ide/src/trace/component/setting/SpHisysEvent.ts +++ b/ide/src/trace/component/setting/SpHisysEvent.ts @@ -20,6 +20,7 @@ import '../../../base-ui/switch/lit-switch'; import { SpRecordTrace } from '../SpRecordTrace'; import { HdcDeviceManager } from '../../../hdc/HdcDeviceManager'; import { LitAllocationSelect } from '../../../base-ui/select/LitAllocationSelect'; +import { SpHiSysEventHtml } from './SpHisysEvent.html'; @element('sp-hisys-event') export class SpHisysEvent extends BaseElement { @@ -163,102 +164,7 @@ export class SpHisysEvent extends BaseElement { }); } - private getCssStyle(): string { - return ` - `; - } - initHtml(): string { - return ` - ${this.getCssStyle()} -
-
-
- Start Hisystem Event Tracker Record - -
-
-
-
- Domain - Record Domain Name -
- - -
-
-
- EventName - Record Event Name -
- - -
-
- `; + return SpHiSysEventHtml; } } diff --git a/ide/src/trace/component/setting/utils/PluginConvertUtils.ts b/ide/src/trace/component/setting/utils/PluginConvertUtils.ts index 353cb2b3c2354417795e2b80df0afde80115fb8b..e61e152825eefd2e22e87d69659db38f7c5fdf3c 100644 --- a/ide/src/trace/component/setting/utils/PluginConvertUtils.ts +++ b/ide/src/trace/component/setting/utils/PluginConvertUtils.ts @@ -60,77 +60,100 @@ export class PluginConvertUtils { prefixText = prefixText + ' '.repeat(spacesNumber) + this.leftBrace + this.crlf; } if (bean) { - // @ts-ignore - for (const [key, value] of Object.entries(bean)) { - const repeatedKey = Array.isArray(value); - if (repeatedKey) { - prefixText = prefixText + this.handleArray(key, value, indentation, needColon, spacesNumber); - } else { - switch (typeof value) { - case 'bigint': - prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); - break; - case 'boolean': - prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); - break; - case 'number': - if (value == 0 && !needColon) { - break; - } - prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); + prefixText = this.getPrefixText(prefixText, indentation, needColon, spacesNumber, bean); + } + if (indentation == 0) { + return prefixText; + } else { + return prefixText + ' '.repeat(spacesNumber).repeat(indentation) + this.rightBrace; + } + } + + private static getPrefixText(prefixText: string, indentation: number, needColon: boolean, spacesNumber: number, bean: any): string { + // @ts-ignore + for (const [key, value] of Object.entries(bean)) { + const repeatedKey = Array.isArray(value); + if (repeatedKey) { + prefixText = prefixText + this.handleArray(key, value, indentation, needColon, spacesNumber); + } else { + switch (typeof value) { + case 'bigint': + prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); + break; + case 'boolean': + prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); + break; + case 'number': + if (value == 0 && !needColon) { break; - case 'string': - if (value == '') { - break; - } - if (LevelConfigEnumList.indexOf(value) >= 0 || value.startsWith('IO_REPORT')) { - prefixText = - prefixText + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - value.toString() + - this.crlf; - } else { - prefixText = - prefixText + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': "' + - value.toString() + - '"' + - this.crlf; - } + } + prefixText = this.getMontageStrings(prefixText, spacesNumber, indentation, key, value); + break; + case 'string': + if (value == '') { break; - case 'object': - default: - if (needColon) { - prefixText = - prefixText + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - this.handleObj(value, indentation + 1, needColon, spacesNumber) + - '' + - this.crlf; - } else { - prefixText = - prefixText + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - this.handleObj(value, indentation + 1, needColon, spacesNumber) + - '' + - this.crlf; - } - } + } + prefixText = this.handleObjByStr(prefixText, value, spacesNumber, key, indentation); + break; + case 'object': + default: + prefixText = this.handleObjByDefault(prefixText, value, spacesNumber, key, indentation, needColon); + break; } } } - if (indentation == 0) { - return prefixText; + return prefixText; + } + + private static handleObjByDefault( + prefixText: string, + value: any, + spacesNumber: number, + key: string, + indentation: number, + needColon: boolean + ): string { + if (needColon) { + prefixText = + prefixText + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': ' + + this.handleObj(value, indentation + 1, needColon, spacesNumber) + + '' + + this.crlf; } else { - return prefixText + ' '.repeat(spacesNumber).repeat(indentation) + this.rightBrace; + prefixText = + prefixText + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + this.handleObj(value, indentation + 1, needColon, spacesNumber) + + '' + + this.crlf; } + return prefixText; + } + + private static handleObjByStr(prefixText: string, value: any, spacesNumber: number, key: string, indentation: number): string { + if (LevelConfigEnumList.indexOf(value) >= 0 || value.startsWith('IO_REPORT')) { + prefixText = + prefixText + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': ' + + value.toString() + + this.crlf; + } else { + prefixText = + prefixText + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': "' + + value.toString() + + '"' + + this.crlf; + } + return prefixText; } private static handleArray( @@ -144,80 +167,118 @@ export class PluginConvertUtils { arr.forEach((arrValue) => { switch (typeof arrValue) { case 'bigint': - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - arrValue.toString() + - this.crlf; + text = this.handleArrayByBigint(text, spacesNumber, indentation, key, arrValue); break; case 'boolean': - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - arrValue.toString() + - this.crlf; + text = this.handleArrayByBoolean(text, spacesNumber, indentation, key, arrValue); break; case 'number': - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - arrValue.toString() + - this.crlf; + text = this.handleArrayByNumber(text, spacesNumber, indentation, key, arrValue); break; case 'string': if (arrValue == '') { break; } - if (arrValue.startsWith('VMEMINFO') || arrValue.startsWith('PMEM')) { - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - arrValue.toString() + - this.crlf; - } else { - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': "' + - arrValue.toString() + - '"' + - this.crlf; - } + text = this.handleArrayByStr(text, spacesNumber, indentation, key, arrValue); break; case 'object': default: - if (needColon) { - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - ': ' + - this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + - '' + - this.crlf; - } else { - text = - text + - ' '.repeat(spacesNumber).repeat(indentation + 1) + - this.humpToSnake(key) + - this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + - '' + - this.crlf; - } + text = this.handleArrayByDefault(text, spacesNumber, indentation, key, arrValue, needColon); } }); return text; } + private static handleArrayByBigint( + text: string, + spacesNumber: number, + indentation: number, + key: string, + arrValue: any + ): string { + return text + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + ': ' + arrValue.toString() + this.crlf; + } + + private static handleArrayByBoolean( + text: string, + spacesNumber: number, + indentation: number, + key: string, + arrValue: any + ): string { + return text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ': ' + + arrValue.toString() + this.crlf; + } + + private static handleArrayByNumber( + text: string, + spacesNumber: number, + indentation: number, + key: string, + arrValue: any + ): string { + return text + ' '.repeat(spacesNumber).repeat(indentation + 1) + this.humpToSnake(key) + ': ' + + arrValue.toString() + this.crlf; + } + + private static handleArrayByStr( + text: string, + spacesNumber: number, + indentation: number, + key: string, + arrValue: any + ): string { + if (arrValue.startsWith('VMEMINFO') || arrValue.startsWith('PMEM')) { + text = + text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': ' + + arrValue.toString() + + this.crlf; + } else { + text = + text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': "' + + arrValue.toString() + + '"' + + this.crlf; + } + return text; + } + + private static handleArrayByDefault( + text: string, + spacesNumber: number, + indentation: number, + key: string, + arrValue: any, + needColon: boolean + ): string { + if (needColon) { + text = + text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + ': ' + + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + + '' + + this.crlf; + } else { + text = + text + + ' '.repeat(spacesNumber).repeat(indentation + 1) + + this.humpToSnake(key) + + this.handleObj(arrValue, indentation + 1, needColon, spacesNumber) + + '' + + this.crlf; + } + return text; + } + // 驼峰转snake private static humpToSnake(humpString: string): string { return humpString.replace(/[A-Z]/g, (value) => '_' + value.toLowerCase()); diff --git a/ide/src/trace/component/trace/SpChartList.ts b/ide/src/trace/component/trace/SpChartList.ts index 292e54158dfc77c9c701c503fd990233cc8994ed..fea441b0127ef914f6e17c82a4d01562bea32eb3 100644 --- a/ide/src/trace/component/trace/SpChartList.ts +++ b/ide/src/trace/component/trace/SpChartList.ts @@ -130,6 +130,17 @@ export class SpChartList extends BaseElement { }); } + removeAllCollectRow(): void { + for (let i = 0; i < this.collectRowList1.length; i++) { + this.collectRowList1[i].collectEL?.click(); + i--; + } + for (let i = 0; i < this.collectRowList2.length; i++) { + this.collectRowList2[i].collectEL?.click(); + i--; + } + } + private resizeHeight(): void { this.maxHeight = 0; this.collectEl1!.childNodes.forEach((item) => (this.maxHeight += (item as any).clientHeight)); @@ -161,6 +172,10 @@ export class SpChartList extends BaseElement { } } + getRowScrollTop() : number { + return this.rootEl?.scrollTop || 0 + } + expandSearchRowGroup(row: TraceRow): void { this.updateGroupDisplay(); if (row.collectGroup === SpChartList.COLLECT_G1) { @@ -188,6 +203,36 @@ export class SpChartList extends BaseElement { return [...this.collectRowList1, ...this.collectRowList2]; } + getCollectRowsInfo(group: string) { + return (group === SpChartList.COLLECT_G1 ? this.collectRowList1 : this.collectRowList2).map(row => { + let rowJson = { + type: row.rowType, + name: row.name, + id: row.rowId, + parents: [], + }; + this.getRowParent(rowJson, row); + rowJson.parents.reverse(); + return rowJson; + }); + } + + getRowParent(obj: any, row: TraceRow) { + if (row.parentRowEl) { + if (obj.parents) { + let parent: any = { + type: row.parentRowEl.rowType, + name: row.parentRowEl.name, + id: row.parentRowEl.rowId, + }; + (obj.parents as Array).push(parent); + } else { + obj.parents = [parent]; + } + this.getRowParent(obj, row.parentRowEl); + } + } + getAllSelectCollectRows(): Array> { const rows: Array> = []; for (const row of this.collectRowList1) { diff --git a/ide/src/trace/component/trace/TimerShaftElement.html.ts b/ide/src/trace/component/trace/TimerShaftElement.html.ts index 134c850c4826100a56af6975b61402d55c561957..04dc46941229e0e0fa3b70f0d4360a5ec4f60c1d 100644 --- a/ide/src/trace/component/trace/TimerShaftElement.html.ts +++ b/ide/src/trace/component/trace/TimerShaftElement.html.ts @@ -51,7 +51,7 @@ export const TimerShaftElementHtml = ` .cpu-usage{ color: var(--dark-color1,#4b5766); font-size: 0.9rem; - text-align: left !important; + text-align: left; padding-left: 10px; width: 100%; background: var(--dark-background4,#F6F6F6); diff --git a/ide/src/trace/component/trace/TimerShaftElement.ts b/ide/src/trace/component/trace/TimerShaftElement.ts index c4bc52e2d7473db4cb532a6aef6b424e3db67b79..25868890cd8cab973a7a279a04f4df0e11aca0ed 100644 --- a/ide/src/trace/component/trace/TimerShaftElement.ts +++ b/ide/src/trace/component/trace/TimerShaftElement.ts @@ -142,7 +142,7 @@ export class TimerShaftElement extends BaseElement { public timerShaftEL: TimerShaftElement | null | undefined; public rowsPaneEL: HTMLDivElement | null | undefined; _checkExpand: boolean = false; //是否展开 - _usageFoldHeight: number = 56.25;//初始化时折叠的负载区高度 + _usageFoldHeight: number = 56.25; //初始化时折叠的负载区高度 usageExpandHeight: number = 75; //给定的展开的负载区高度 _cpuUsageCount: Array<{ cpu: number; ro: number; rate: number }> = []; @@ -239,26 +239,25 @@ export class TimerShaftElement extends BaseElement { this.setRangeNS(0, this.endNS); //---------------每次导入trace时触发渲染----------------- if (this._rangeRuler && this._sportRuler) { - sessionStorage.setItem('foldHeight', String(56.25)) + this.canvas!.width = this.canvas!.clientWidth || 0; + sessionStorage.setItem('foldHeight', String(56.25)); if (this._checkExpand && this._checkExpand === true) { this._checkExpand = false; - sessionStorage.setItem('expand', String(this._checkExpand)) + sessionStorage.setItem('expand', String(this._checkExpand)); } - sessionStorage.setItem('expand', String(this._checkExpand)) + sessionStorage.setItem('expand', String(this._checkExpand)); this.usageEL!.innerHTML = ''; - this.usageEL!.style.textAlign = 'center'; this.usageEL!.style.height = `${100 - 56.25}px`; this.usageEL!.style.lineHeight = `${100 - 56.25}px`; this.timerShaftEL!.style.height = `${146 - 56.25 + 2}px`; this.canvas!.style.height = `${146 - 56.25}px`; this.canvas!.height = 146 - 56.25; - this.rowsPaneEL!.style.maxHeight = `${this.rowsPaneEL!.clientHeight + 200}px`; - this._rangeRuler.frame.height = 18.75; + this.rowsPaneEL!.style.maxHeight = `100%`; this._sportRuler.frame.y = 43.75; this.render(); this._checkExpand = true; - this._cpuUsageCount = []//清空判断数据 + this._cpuUsageCount = []; //清空判断数据 } } @@ -290,12 +289,12 @@ export class TimerShaftElement extends BaseElement { if (this._rangeRuler && this.sportRuler && this._cpuUsageCount.length) { // 计算需要被收起来的高度:总高度75-(总高度/cpu数量)* 2 this._usageFoldHeight = this.usageExpandHeight - (this.usageExpandHeight / this._rangeRuler.cpuCountData!) * 2; + this.canvas!.width = this.canvas!.clientWidth || 0; if (this._checkExpand) { - sessionStorage.setItem('expand', String(this._checkExpand)) - sessionStorage.setItem('foldHeight', String(this._usageFoldHeight)) + sessionStorage.setItem('expand', String(this._checkExpand)); + sessionStorage.setItem('foldHeight', String(this._usageFoldHeight)); this.usageEL!.style.height = '100px'; this.usageEL!.style.lineHeight = '100px'; - this.usageEL!.style.textAlign = 'center'; this.timerShaftEL!.style.height = `${height + 2}px`; this.canvas!.style.height = `${height}px`; this.canvas!.height = height; @@ -304,9 +303,8 @@ export class TimerShaftElement extends BaseElement { this.render(); this._checkExpand = false; } else { - sessionStorage.setItem('expand', String(this._checkExpand)) - sessionStorage.setItem('foldHeight', String(this._usageFoldHeight)) - this.usageEL!.style.textAlign = 'center'; + sessionStorage.setItem('expand', String(this._checkExpand)); + sessionStorage.setItem('foldHeight', String(this._usageFoldHeight)); this.usageEL!.style.height = `${100 - this._usageFoldHeight}px`; this.usageEL!.style.lineHeight = `${100 - this._usageFoldHeight}px`; this.timerShaftEL!.style.height = `${height - this._usageFoldHeight + 2}px`; @@ -375,7 +373,7 @@ export class TimerShaftElement extends BaseElement { if (!this._rangeRuler) { this._rangeRuler = new RangeRuler( this, - new Rect(0, 25, width, 75), + new Rect(0, 25, width, 75 - this._usageFoldHeight), { slicesTime: { startTime: null, @@ -475,19 +473,17 @@ export class TimerShaftElement extends BaseElement { }; documentOnKeyPress = (ev: KeyboardEvent, currentSlicesTime?: CurrentSlicesTime): void => { - if ((window as any).isSheetMove) return; if ((window as any).flagInputFocus) return; this._rangeRuler?.keyPress(ev, currentSlicesTime); this.sportRuler?.clearHoverFlag(); }; documentOnKeyUp = (ev: KeyboardEvent): void => { - if ((window as any).isSheetMove) return; if ((window as any).flagInputFocus) return; this._rangeRuler?.keyUp(ev); }; - disconnectedCallback(): void { } + disconnectedCallback(): void {} firstRender = true; diff --git a/ide/src/trace/component/trace/base/Extension.ts b/ide/src/trace/component/trace/base/Extension.ts index 52524d2839e36a6098b48ec5c2dc21a8d9698eca..45500794dc86c055ed46036c1ea7fbfffd355366 100644 --- a/ide/src/trace/component/trace/base/Extension.ts +++ b/ide/src/trace/component/trace/base/Extension.ts @@ -69,6 +69,8 @@ declare global { LoadFinish: string; LoadFinishFrame: string; ShowBottomTab: string; + ImportRecord: string; //导出时间区间和泳道图收藏记录 + ExportRecord: string; //导出时间区间和泳道图收藏记录 }; }; @@ -129,6 +131,8 @@ window.SmartEvent = { LoadFinish: 'SmartEvent-UI-LoadFinish',//所有泳道刷新完成触发 LoadFinishFrame: 'SmartEvent-UI-LoadFinishFrame',//单个泳道刷新完成触发 ShowBottomTab: 'SmartEvent-UI-ShowBottomTab',// 显示底部 tab + ImportRecord: 'SmartEvent-UI-ImportRecord', + ExportRecord: 'SmartEvent-UI-ExportRecord' }, }; Window.prototype.subscribe = (ev, fn) => EventCenter.subscribe(ev, fn); diff --git a/ide/src/trace/component/trace/base/RangeSelect.ts b/ide/src/trace/component/trace/base/RangeSelect.ts index 6b75443ea9aa9cb3b1640eb5854e36152e884100..e8feaaac1cdc4db96ce21211ecb6a8a343016202 100644 --- a/ide/src/trace/component/trace/base/RangeSelect.ts +++ b/ide/src/trace/component/trace/base/RangeSelect.ts @@ -41,6 +41,9 @@ export class RangeSelect { }; private trace: SpSystemTrace | null | undefined; drag = false; + docomList: Array = []; + repaintList: Array = []; + presentList: Array = []; constructor(trace: SpSystemTrace | null | undefined) { this.trace = trace; @@ -67,6 +70,63 @@ export class RangeSelect { this.rangeTraceRow = []; this.isMouseDown = true; TraceRow.rangeSelectObject = undefined; + // 遍历当前可视区域所有的泳道,如果有render_service进程,查询该进程下对应泳道的方法存起来,以便框选时直接使用 + this.trace?.visibleRows.forEach((row) => { + if (row.getAttribute('row-type') === 'process' && row.getAttribute('name')?.startsWith('render_service')) { + this.queryRowsData(row.childrenList) + return; + } + }) + } + + // 对应查询方法行所有的数据 + queryRowsData(rowList: Array>) { + rowList.forEach((row) => { + if (row.getAttribute('row-type') === 'func') { + if (row.getAttribute('name')?.startsWith('render_service')) { + this.saveFrameRateData(row, 'H:RSMainThread::DoComposition'); + } else if (row.getAttribute('name')?.startsWith('RSHardwareThrea')) { + this.saveFrameRateData(row, 'H:Repaint'); + } else if (row.getAttribute('name')?.startsWith('Present')) { + this.savePresentData(row, 'H:Waiting for Present Fence'); + } + } + }) + } + + // 查到所有的数据存储起来 + saveFrameRateData(row: TraceRow, funcName: string): void { + let dataList: any = [] + queryFuncRowData( + funcName, + Number(row?.getAttribute('row-id')), + ).then((res) => { + if (res.length) { + res.forEach((item) => { + dataList?.push({ startTime: item.startTime!, tid: item.tid }); + }); + if (funcName === 'H:RSMainThread::DoComposition') { + this.docomList = dataList; + } else { + this.repaintList = dataList; + } + } + }); + } + // 查到present泳道所有的数据存储起来 + savePresentData(row: TraceRow, funcName: string): void { + let dataList: any = [] + fuzzyQueryFuncRowData( + funcName, + Number(row?.getAttribute('row-id')), + ).then((res) => { + if (res.length) { + res.forEach((item) => { + dataList?.push({ endTime: item.endTime!, tid: item.tid }); + }); + this.presentList = dataList; + } + }); } mouseUp(mouseEventUp?: MouseEvent): void { @@ -86,77 +146,79 @@ export class RangeSelect { this.isMouseDown = false; } - // 判断框选的线程行类型和名称 + checkRowsName(rowList: Array>) { rowList.forEach((row) => { if (row.getAttribute('row-type') === 'func' && row.parentRowEl?.getAttribute('name')?.startsWith('render_service')) { if (row.getAttribute('name')?.startsWith('render_service')) { - this.handleFrameRateData(row, 'H:RSMainThread::DoComposition'); + this.filterRateData(row, this.docomList); } else if (row.getAttribute('name')?.startsWith('RSHardwareThrea')) { - this.handleFrameRateData(row, 'H:Repaint'); + this.filterRateData(row, this.repaintList); } else if (row.getAttribute('name')?.startsWith('Present')) { - this.handlePresentData(row, 'H:Waiting for Present Fence'); + this.filterPresentData(row, this.presentList); } } }) } - // 查询DoComposition方法和Repaint方法的数据 - handleFrameRateData(row: TraceRow, funcName: string): void { - let dataList: Array = [] - queryFuncRowData( - funcName, - Number(row?.getAttribute('row-id')), - TraceRow.rangeSelectObject!.startNS!, - TraceRow.rangeSelectObject!.endNS!, - ).then((res) => { - if (res.length >= 2) { - res.forEach((item) => { - dataList?.push(item.startTime!); - }); - row.frameRateList = dataList; + // 过滤处理数据 + filterRateData(row: TraceRow, data: any) { + data.forEach((it: any) => { + if ( + it.startTime >= TraceRow.rangeSelectObject!.startNS! && + it.startTime <= TraceRow.rangeSelectObject!.endNS! && + Number(row.rowId) === Number(it.tid) + ) { + row.frameRateList?.push(it.startTime); + } + }) + if (row.frameRateList?.length) { + row.frameRateList = [...new Set(row.frameRateList)]; + row.frameRateList.sort((a, b) => a - b); + if (row.frameRateList?.length >= 2) { const CONVERT_SECONDS = 1000000000; - let cutres: number = (dataList[dataList.length - 1] - dataList[0]); - row.avgRateTxt = ((dataList.length - 1) / cutres * CONVERT_SECONDS).toFixed(1) + 'fps'; + let cutres: number = (row.frameRateList[row.frameRateList.length - 1] - row.frameRateList[0]); + row.avgRateTxt = ((row.frameRateList.length - 1) / cutres * CONVERT_SECONDS).toFixed(1) + 'fps'; } - }); + } } - // 查询H:Waiting for Present Fence方法数据 - handlePresentData(row: TraceRow, funcName: string): void { - let dataList: Array = [] - fuzzyQueryFuncRowData( - funcName, - Number(row?.getAttribute('row-id')), - TraceRow.rangeSelectObject!.startNS!, - TraceRow.rangeSelectObject!.endNS!, - ).then((res) => { - if (res.length >= 2) { - res.forEach((item) => { - dataList?.push(item.endTime!); - }); - row.frameRateList = dataList; + // 过滤并处理present数据 + filterPresentData(row: TraceRow, data: any) { + data.forEach((it: any) => { + if ( + it.endTime >= TraceRow.rangeSelectObject!.startNS! && + it.endTime <= TraceRow.rangeSelectObject!.endNS! && + Number(row.rowId) === Number(it.tid) + ) { + row.frameRateList?.push(it.endTime) + } + }) + if (row.frameRateList?.length) { + row.frameRateList = [...new Set(row.frameRateList)];//去重 + row.frameRateList.sort((a, b) => a - b); //排序 + if (row.frameRateList?.length >= 2) { let hitchTimeList: Array = []; for (let i = 0; i < SpLtpoChart.sendHitchDataArr.length; i++) { - if (SpLtpoChart.sendHitchDataArr[i].startTs! >= res[0].endTime! + if (SpLtpoChart.sendHitchDataArr[i].startTs! >= row.frameRateList[0]! && - SpLtpoChart.sendHitchDataArr[i].startTs! < res[res.length - 1].endTime!) { + SpLtpoChart.sendHitchDataArr[i].startTs! < row.frameRateList[row.frameRateList.length - 1]!) { hitchTimeList.push(SpLtpoChart.sendHitchDataArr[i].value!); } else if ( - SpLtpoChart.sendHitchDataArr[i].startTs! >= res[res.length - 1].endTime! + SpLtpoChart.sendHitchDataArr[i].startTs! >= row.frameRateList[row.frameRateList.length - 1]! ) { break; } } const CONVERT_SECONDS = 1000000000; - let cutres: number = (dataList[dataList.length - 1] - dataList[0]); - let avgRate: string = ((dataList.length - 1) / cutres * CONVERT_SECONDS).toFixed(1) + 'fps'; + let cutres: number = (row.frameRateList[row.frameRateList.length - 1] - row.frameRateList[0]); + let avgRate: string = ((row.frameRateList.length - 1) / cutres * CONVERT_SECONDS).toFixed(1) + 'fps'; let sum: number = hitchTimeList.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // ∑hitchTimeData let hitchRate: number = (sum / ((TraceRow.rangeSelectObject!.endNS! - TraceRow.rangeSelectObject!.startNS!) / 1000000)); let perHitchRate: string = (Number(hitchRate) * 100).toFixed(2) + '%'; row.avgRateTxt = avgRate + ' ' + ',' + ' ' + 'HitchTime:' + ' ' + sum.toFixed(1) + 'ms' + ' ' + ',' + ' ' + perHitchRate; } - }); + } } isDrag(): boolean { diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 1ea5c6f17909ce61c63045805aadc85fdcc438e6..3d81568048fb96fe5a1f91071d80d10b23cae449 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -1062,23 +1062,21 @@ export class TraceRow extends HTMLElement { }; this.describeElEvent(); this.collectEL!.onclick = (e) => { - if (this.isComplete) { - this.collect = !this.collect; - if (this.collect) { - this.describeEl!.draggable = false; - } else { - this.describeEl!.draggable = false; - } - document.dispatchEvent( - new CustomEvent('collect', { - detail: { - type: e.type, - row: this, - }, - }) - ); - this.favoriteChangeHandler?.(this); + this.collect = !this.collect; + if (this.collect) { + this.describeEl!.draggable = false; + } else { + this.describeEl!.draggable = false; } + document.dispatchEvent( + new CustomEvent('collect', { + detail: { + type: e.type, + row: this, + }, + }) + ); + this.favoriteChangeHandler?.(this); }; if (!this.args['skeleton']) { this.initCanvas(this.canvas); diff --git a/ide/src/trace/component/trace/base/TraceRowConfig.ts b/ide/src/trace/component/trace/base/TraceRowConfig.ts index 6d6262c38a01f1d3f93e3f5e6d1daa7c42f6413f..01ab776535d788f3119fb342d438e4f0d6b5ed6d 100644 --- a/ide/src/trace/component/trace/base/TraceRowConfig.ts +++ b/ide/src/trace/component/trace/base/TraceRowConfig.ts @@ -548,131 +548,145 @@ export class TraceRowConfig extends BaseElement { private buildSubSystemTreeData(id: number, configJson: any): SubsystemNode[] { let subsystemsKey: string = 'subsystems'; let keys = Object.keys(configJson); + if (keys.indexOf(subsystemsKey) < 0) { + return []; + } let subSystems: SubsystemNode[] = []; - if (keys.indexOf(subsystemsKey) >= 0) { - let subsystemsData = configJson[subsystemsKey]; - if (this.traceRowList) { - this.otherRowNames = []; - for (let index = 0; index < this.traceRowList.length; index++) { - let item = this.traceRowList[index]; - this.otherRowNames.push({ - nodeName: item.name, - scene: [...item.templateType], - }); - } + let subsystemsData = configJson[subsystemsKey]; + this.initOtherRowNames(); + let subsystemList = []; + for (let subIndex = 0; subIndex < subsystemsData.length; subIndex++) { + let currentSystemData = subsystemsData[subIndex]; + if(!currentSystemData.hasOwnProperty('subsystem') || currentSystemData.subsystem === '' || + subsystemList.indexOf(currentSystemData.subsystem) > -1 || Array.isArray(currentSystemData.subsystem)) { + continue; } - let subsystemList = []; - for (let subIndex = 0; subIndex < subsystemsData.length; subIndex++) { - let currentSystemData = subsystemsData[subIndex]; - if(!currentSystemData.hasOwnProperty('subsystem') || currentSystemData.subsystem === '' || - subsystemList.indexOf(currentSystemData.subsystem) > -1 || Array.isArray(currentSystemData.subsystem)) { + let currentSubName = currentSystemData.subsystem; + subsystemList.push(currentSystemData.subsystem); + id++; + let subsystemStruct: SubsystemNode = { + id: id, + nodeName: currentSubName, + children: [], + depth: 1, + isCheck: true, + scene: [], + }; + if (subSystems.indexOf(subsystemStruct) < 0) { + let currentCompDates = currentSystemData.components; + if (!currentCompDates || !Array.isArray(currentCompDates)) { continue; } - let currentSubName = currentSystemData.subsystem; - subsystemList.push(currentSystemData.subsystem); + for (let compIndex = 0; compIndex < currentCompDates.length; compIndex++) { + let currentCompDate = currentCompDates[compIndex]; + if(!currentCompDate.hasOwnProperty('component') || currentCompDate.component === '' || + !currentCompDate.hasOwnProperty('charts')) { + continue; + } + id = this.setSubsystemComp(currentCompDate, id, subsystemStruct); + } + subSystems.push(subsystemStruct); + } + } + return subSystems; + } + + private initOtherRowNames(): void { + if (this.traceRowList) { + this.otherRowNames = []; + for (let index = 0; index < this.traceRowList.length; index++) { + let item = this.traceRowList[index]; + this.otherRowNames.push({ + nodeName: item.name, + scene: [...item.templateType], + }); + } + } + } + + private setSubsystemComp(currentCompDate: any, id: number, subsystemStruct: SubsystemNode): number { + let currentCompName = currentCompDate.component; + let currentChartDates = currentCompDate.charts; + id++; + let componentStruct: SubsystemNode = { + id: id, + parent: subsystemStruct, + nodeName: currentCompName, + children: [], + depth: 2, + isCheck: true, + scene: [], + }; + for (let chartIndex = 0; chartIndex < currentChartDates.length; chartIndex++) { + let currentChartDate = currentChartDates[chartIndex]; + if ((!currentChartDate.hasOwnProperty('chartName') && !currentChartDate.hasOwnProperty('chartId')) + || Array.isArray(currentChartDate.chartName)) { + continue; + } + let currentChartName = `${currentChartDate.chartName}`; + let currentChartId = currentChartDate.chartId; + let findChartNames: Array | undefined = []; + let scene: string[] = []; + this.setSubsystemChart(currentChartName, currentChartId, scene, findChartNames); + findChartNames.forEach((currentChartName) => { id++; - let subsystemStruct: SubsystemNode = { + let chartStruct: SubsystemNode = { id: id, - nodeName: currentSubName, + parent: componentStruct, + nodeName: currentChartName, children: [], - depth: 1, + depth: 3, isCheck: true, - scene: [], + scene: scene, }; - if (subSystems.indexOf(subsystemStruct) < 0) { - let currentCompDates = currentSystemData.components; - if (!currentCompDates || !Array.isArray(currentCompDates)) { - continue; + if (componentStruct.children.indexOf(chartStruct) < 0) { + let rowNumber = this.otherRowNames.findIndex((row) => row.nodeName === chartStruct.nodeName); + if (rowNumber >= 0) { + this.otherRowNames.splice(rowNumber, 1); } - for (let compIndex = 0; compIndex < currentCompDates.length; compIndex++) { - let currentCompDate = currentCompDates[compIndex]; - if(!currentCompDate.hasOwnProperty('component') || currentCompDate.component === '' || - !currentCompDate.hasOwnProperty('charts')) { - continue; - } - let currentCompName = currentCompDate.component; - let currentChartDates = currentCompDate.charts; - id++; - let componentStruct: SubsystemNode = { - id: id, - parent: subsystemStruct, - nodeName: currentCompName, - children: [], - depth: 2, - isCheck: true, - scene: [], - }; - for (let chartIndex = 0; chartIndex < currentChartDates.length; chartIndex++) { - let currentChartDate = currentChartDates[chartIndex]; - if((!currentChartDate.hasOwnProperty('chartName') && !currentChartDate.hasOwnProperty('chartId')) - || Array.isArray(currentChartDate.chartName)) { - continue; - } - let currentChartName = `${ currentChartDate.chartName}`; - let currentChartId = currentChartDate.chartId; - let findChartNames: Array | undefined = []; - let scene: string[] = []; - if (this.traceRowList) { - for (let index = 0; index < this.traceRowList.length; index++) { - let item = this.traceRowList[index]; - let chartId = ''; - let name = item.name; - let pattern = / (\d+)$/; - let match = item.name.match(pattern); - if (match) { - chartId = match[0].trim(); - name = item.name.split(match[0])[0]; - if (name !== 'Cpu') { - if ((currentChartName !== undefined && currentChartName !== '' && - name.toLowerCase().endsWith(currentChartName.toLowerCase())) || currentChartId === chartId) { - scene.push(...item.templateType); - findChartNames.push(item.name); - } - } else { - if ((currentChartName !== undefined && currentChartName !== '' && - name.toLowerCase().endsWith(currentChartName.toLowerCase()))) { - scene.push(...item.templateType); - findChartNames.push(item.name); - } - } - } else { - if ((currentChartName !== undefined && currentChartName !== '' && - name.toLowerCase().endsWith(currentChartName.toLowerCase()))) { - scene.push(...item.templateType); - findChartNames.push(item.name); - } - } - } - } - findChartNames.forEach((currentChartName) => { - id++; - let chartStruct: SubsystemNode = { - id: id, - parent: componentStruct, - nodeName: currentChartName, - children: [], - depth: 3, - isCheck: true, - scene: scene, - }; - if (componentStruct.children.indexOf(chartStruct) < 0) { - let rowNumber = this.otherRowNames.findIndex((row) => row.nodeName === chartStruct.nodeName); - if (rowNumber >= 0) { - this.otherRowNames.splice(rowNumber, 1); - } - componentStruct.children.push(chartStruct); - } - }); + componentStruct.children.push(chartStruct); + } + }); + } + if (subsystemStruct.children.indexOf(componentStruct) < 0) { + subsystemStruct.children.push(componentStruct); + } + return id; + } + + private setSubsystemChart(currentChartName: string, currentChartId: string, scene: Array, findChartNames: Array) { + if (this.traceRowList) { + for (let index = 0; index < this.traceRowList.length; index++) { + let item = this.traceRowList[index]; + let chartId = ''; + let name = item.name; + let pattern = / (\d+)$/; + let match = item.name.match(pattern); + if (match) { + chartId = match[0].trim(); + name = item.name.split(match[0])[0]; + if (name !== 'Cpu') { + if ((currentChartName !== undefined && currentChartName !== '' && + name.toLowerCase().endsWith(currentChartName.toLowerCase())) || currentChartId === chartId) { + scene.push(...item.templateType); + findChartNames.push(item.name); } - if (subsystemStruct.children.indexOf(componentStruct) < 0) { - subsystemStruct.children.push(componentStruct); + } else { + if ((currentChartName !== undefined && currentChartName !== '' && + name.toLowerCase().endsWith(currentChartName.toLowerCase()))) { + scene.push(...item.templateType); + findChartNames.push(item.name); } } - subSystems.push(subsystemStruct); + } else { + if ((currentChartName !== undefined && currentChartName !== '' && + name.toLowerCase().endsWith(currentChartName.toLowerCase()))) { + scene.push(...item.templateType); + findChartNames.push(item.name); + } } } } - return subSystems; } refreshTable(): void { diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index 0cfd9baac3adc551609c31122e60fbbb08ba69db..b93e8794b3ac34813ac2af9f96ae91b350c56f42 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -86,6 +86,7 @@ import { SampleStruct } from '../../../database/ui-worker/ProcedureWorkerBpftrac import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction'; import { TabPaneFreqStatesDataCut } from '../sheet/states/TabPaneFreqStatesDataCut'; import { TabPaneDataCut } from '../sheet/TabPaneDataCut'; +import { SpSystemTrace } from '../../SpSystemTrace'; @element('trace-sheet') export class TraceSheet extends BaseElement { @@ -379,6 +380,8 @@ export class TraceSheet extends BaseElement { let that = this; // 节点挂载时给Tab面板绑定鼠标按下事件 this.nav!.onmousedown = (event): void => { + if (SpSystemTrace.isKeyUp === false) + { return }; (window as any).isSheetMove = true; // 获取所有标签页的节点数组 let litTabpane: NodeListOf | undefined | null = @@ -624,8 +627,8 @@ export class TraceSheet extends BaseElement { this.displayTab('current-selection').setClockData(data); displayIrqData = (data: IrqStruct): void => this.displayTab('current-selection').setIrqData(data); - displayStartupData = (data: AppStartupStruct, scrollCallback: Function): void => - this.displayTab('current-selection').setStartupData(data, scrollCallback); + displayStartupData = (data: AppStartupStruct, scrollCallback: Function,rowData:any): void => + this.displayTab('current-selection').setStartupData(data, scrollCallback,rowData); displayAllStartupData = (data: AllAppStartupStruct, scrollCallback: Function): void => this.displayTab('current-selection').setAllStartupData(data, scrollCallback); displayStaticInitData = (data: SoStruct, scrollCallback: Function): void => @@ -654,7 +657,7 @@ export class TraceSheet extends BaseElement { this.displayTab('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject); }; - displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function): void => + displayFuncData = (names: string[], data: FuncStruct, scrollCallback: Function): Promise => this.displayTab(...names).setFunctionData(data, scrollCallback); displayCpuData = ( data: CpuStruct, @@ -719,8 +722,8 @@ export class TraceSheet extends BaseElement { displayFreqLimitData = (): CpuFreqLimitsStruct | undefined => (this.displayTab('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct); - displayFrameAnimationData = (data: FrameAnimationStruct): Promise => - this.displayTab('current-selection').setFrameAnimationData(data); + displayFrameAnimationData = (data: FrameAnimationStruct,scrollCallback: Function): Promise => + this.displayTab('current-selection').setFrameAnimationData(data,scrollCallback); displayFrameDynamicData = (row: TraceRow, data: FrameDynamicStruct): void => this.displayTab('box-frame-dynamic').buildDynamicTable([data], true); displayFrameSpacingData = (data: FrameSpacingStruct): void => diff --git a/ide/src/trace/component/trace/search/Search.ts b/ide/src/trace/component/trace/search/Search.ts index 5a2a8e6e6e089aa03b014048346ebe6faee3ad80..d32e2a64d143bba84eae7cda870b526e8a1a99be 100644 --- a/ide/src/trace/component/trace/search/Search.ts +++ b/ide/src/trace/component/trace/search/Search.ts @@ -307,6 +307,7 @@ export class LitSearch extends BaseElement { this._retarge_index!.value = ''; }, 2000); } + e.target.blur(); } e.stopPropagation(); }); diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 0b2943da66952967f511065ba27fba3c9363eef7..f6706af81ddc99878d5498bfb0bc004ee0862b72 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -43,7 +43,8 @@ import { queryBinderBySliceId, queryFlowsData, queryPrecedingData, - queryThreadByItid + queryThreadByItid, + queryFpsSourceList } from '../../../database/sql/SqlLite.sql'; import { queryBinderArgsByArgset, @@ -56,6 +57,7 @@ import { import { queryGpuDur } from '../../../database/sql/Gpu.sql'; import { queryWakeupListPriority } from '../../../database/sql/Cpu.sql'; import { TabPaneCurrentSelectionHtml } from './TabPaneCurrentSelection.html'; +import {queryRealTime} from "../../../database/sql/Clock.sql"; const INPUT_WORD = 'This is the interval from when the task became eligible to run \n(e.g.because of notifying a wait queue it was a suspended on) to\n when it started running.'; @@ -101,6 +103,7 @@ export function getTimeString(ns: number): string { @element('tabpane-current-selection') export class TabPaneCurrentSelection extends BaseElement { + static isTransformed : boolean = false; weakUpBean: WakeupBean | null | undefined; selectWakeupBean: any; private currentSelectionTbl: LitTable | null | undefined; @@ -110,6 +113,9 @@ export class TabPaneCurrentSelection extends BaseElement { // @ts-ignore private dpr: any = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1; private wakeUp: string = ''; + private isFpsAvailable: boolean = true; + private realTime: number = 0; + private bootTime: number = 0; set data(currentSelectionValue: any) { if ( @@ -251,8 +257,20 @@ export class TabPaneCurrentSelection extends BaseElement { list.push({ name: 'End State', value: state }); } - setFunctionData(data: FuncStruct, scrollCallback: Function): void { - //方法信息 + async setFunctionData(data: FuncStruct, scrollCallback: Function): Promise { + //方法信息 + await queryRealTime().then((result) => { + if (result && result.length > 0) { + result.forEach(item => { + if (item.name === 'realtime') { + this.realTime = item.ts; + } else { + this.bootTime = item.ts; + } + }); + } + }); + this.tabCurrentSelectionInit('Slice Details'); let list: any[] = []; let name = this.transferString(data.funName ?? ''); @@ -270,13 +288,31 @@ export class TabPaneCurrentSelection extends BaseElement { } else { this.setTableHeight('auto'); list.push({ name: 'Name', value: name }); + let timeStr: string = ''; + let startTimeValue: string = ''; + let startTimeAbsolute = (data.startTs || 0) + (window as any).recordStartNS; + + if (this.realTime > 0) { + if (TabPaneCurrentSelection.isTransformed) { + timeStr = this.getRealTimeStr(startTimeAbsolute); + } else { + timeStr = startTimeAbsolute / 1000000000 + 's'; + } + startTimeValue = `
+
${timeStr}
+ +
`; + } else { + startTimeValue = startTimeAbsolute / 1000000000 + 's'; + } list.push({ name: 'StartTime(Relative)', value: getTimeString(data.startTs || 0), }); list.push({ name: 'StartTime(Absolute)', - value: ((data.startTs || 0) + (window as any).recordStartNS) / 1000000000 + 's', + value: startTimeValue, }); list.push({ name: 'Duration', @@ -284,9 +320,36 @@ export class TabPaneCurrentSelection extends BaseElement { }); list.push({ name: 'depth', value: data.depth }); this.currentSelectionTbl!.dataSource = list; + let transfBtn = this.currentSelectionTbl?.shadowRoot?.querySelector('#transfBtn'); + transfBtn?.addEventListener('click', () => { + let startTimeAbsalute = this.currentSelectionTbl?.shadowRoot?.querySelector('#startTimeAbsalute'); + if (startTimeAbsalute) { + if (TabPaneCurrentSelection.isTransformed) { + startTimeAbsalute!.innerHTML = startTimeAbsolute / 1000000000 + 's'; + TabPaneCurrentSelection.isTransformed = false; + } else { + startTimeAbsalute!.innerHTML = this.getRealTimeStr(startTimeAbsolute); + TabPaneCurrentSelection.isTransformed = true; + } + } + }); } } + // 计算真实时间 + private getRealTimeStr(startTs: number): string { + let time = (startTs || 0) + (window as any).recordStartNS - this.bootTime + this.realTime; + const formateDateStr = this.getDate(parseInt(time.toString().substring(0, 13))); + return formateDateStr; + } + + // 格式化时间戳为字符串格式 yyyy/mm/dd hh:mi:ss + private getDate(timestamp: number): string { + let date = new Date(timestamp); + let gmt = date.toLocaleString(); + return gmt; + } + private handleNonBinder(data: FuncStruct, list: any[], name: string): void { queryBinderArgsByArgset(data.argsetid!).then((argset) => { list.push({ name: 'Name', value: name }); @@ -992,7 +1055,7 @@ export class TabPaneCurrentSelection extends BaseElement { this.currentSelectionTbl!.dataSource = list; } - setStartupData(data: AppStartupStruct, scrollCallback: Function): void { + setStartupData(data: AppStartupStruct, scrollCallback: Function, rowData: any): void { this.setTableHeight('550px'); this.initCanvas(); this.setStartUpStyle(); @@ -1033,6 +1096,12 @@ export class TabPaneCurrentSelection extends BaseElement { }); } list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); + rowData.forEach((item: any, index: number) => { + if (item.startName === data.startName) { + list.push({ name: 'StartSlice', value: index === 0 ? 'NULL' : `${AppStartupStruct.getStartupName(rowData[index - 1].startName)} ${getTimeString(rowData[index - 1].startTs + rowData[index - 1].dur)}` }); + list.push({ name: 'EndSlice', value: index === rowData.length - 1 ? 'NULL' : `${AppStartupStruct.getStartupName(rowData[index + 1].startName)} ${getTimeString(rowData[index + 1].startTs)}` }); + } + }) this.currentSelectionTbl!.dataSource = list; this.attachScrollHandlers(data, scrollCallback); } @@ -1158,7 +1227,7 @@ export class TabPaneCurrentSelection extends BaseElement { } } - async setFrameAnimationData(data: FrameAnimationStruct): Promise { + async setFrameAnimationData(data: FrameAnimationStruct, scrollCallback: Function): Promise { this.setTableHeight('550px'); this.tabCurrentSelectionInit('Animation Details'); let list = []; @@ -1182,7 +1251,15 @@ export class TabPaneCurrentSelection extends BaseElement { let frameFpsMessage = data.frameInfo?.split(':'); if (frameFpsMessage) { if (frameFpsMessage[1] !== '0') { - list.push({ name: 'FPS', value: `${frameFpsMessage[1]}` }); + if (this.isFpsAvailable) { + list.push({ + name: 'FPS', value: `
+
${frameFpsMessage[1]}
+ +
` }); + } else { + list.push({ name: 'FPS', value: `${frameFpsMessage[1]}` }); + } } else { let fixedNumber: number = 2; let fpsValue: number = Number(frameFpsMessage[0]) / (data.dur / 1000_000_000); @@ -1191,6 +1268,39 @@ export class TabPaneCurrentSelection extends BaseElement { } } this.currentSelectionTbl!.dataSource = list; + this.fpsClickEvent(data, scrollCallback); + } + + private fpsClickEvent(data: FrameAnimationStruct, scrollCallback: Function): void { + let queryJoinName = `${data.frameInfo?.split(':')[1]}: ${data.name?.split(':')![1]}`; + let recordNs: number = (window as any).recordStartNS; + this.currentSelectionTbl?.shadowRoot?.querySelector('#fps-jump')?.addEventListener('click', () => { + queryFpsSourceList(data.inputTime, data.endTime, queryJoinName).then((result) => { + if (result.length > 0) { + this.isFpsAvailable = true; + let pt: { + pid: number; + tid: number; + name: string; + ts: number; + dur: number; + depth: number + } = result[0]; + scrollCallback({ + pid: pt.tid, + tid: pt.tid, + dur: pt.dur, + type: 'func', + depth: pt.depth, + funName: pt.name, + startTs: pt.ts - recordNs, + keepOpen: true, + }); + } else { + this.isFpsAvailable = false; + } + }); + }) } private setJankType(data: JankStruct, list: any[]): void { diff --git a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts index d26ea71c5a239bdf301ba21aeef9496aa011cddd..b11208efe4c30426a001adada430642350f80628 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneDataCut.ts @@ -147,9 +147,7 @@ export class TabPaneDataCut extends BaseElement { align-items: center; } -
- -
+
diff --git a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts index 5be3b4f13c071cff74eb9a43a1e71b51aaf6923b..f1cd2f2cc8a8f39443981d6a6bf1bfc6d08c1c6b 100644 --- a/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts +++ b/ide/src/trace/component/trace/sheet/binder/TabPaneBinderDataCut.ts @@ -702,21 +702,21 @@ export class TabPaneBinderDataCut extends BaseElement {
- + - + - + - + - + - + - + - +
diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts index 5c2dced6467dd2dc8f11a40dff4d3040188fe1b8..36fdc4feab9733366d3eed450bfd3aba49619378 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -210,9 +210,7 @@ export class TabPaneFrequencySample extends BaseElement { this.worker!.postMessage(msg); this.worker!.onmessage = (event: MessageEvent) => { sampleMap = event.data; - sampleMap.forEach((value) => { - this.freqBusyDataList.push(value); - }); + this.freqBusyDataList = [...sampleMap.values()]; this.busyTimeLoadingHide = true; //当busyTimebutton的状态为true但busyTime的计算未完成时 if (this.frequencySampleClickType) { @@ -289,12 +287,10 @@ export class TabPaneFrequencySample extends BaseElement { return frequencySampleRightData.time - frequencySampleLeftData.time; } } else if (key === 'counter') { - if (frequencySampleLeftData.counter > frequencySampleRightData.counter) { - return type === 2 ? -1 : 1; - } else if (frequencySampleLeftData.counter === frequencySampleRightData.counter) { - return 0; + if (type === 1) { + return frequencySampleLeftData.cpu - frequencySampleRightData.cpu; } else { - return type === 2 ? 1 : -1; + return frequencySampleRightData.cpu - frequencySampleLeftData.cpu; } } else if (key === 'valueStr') { if (type === 1) { diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts index 574a13b5602e7e9d8628cc76e666c8d5fc707722..be6692f70ed4e5a384b76ee5fe38a5b12f69f84e 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPanePTS.ts @@ -17,9 +17,9 @@ import { BaseElement, element } from '../../../../../base-ui/BaseElement'; import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; import { SelectionParam } from '../../../../bean/BoxSelection'; import { resizeObserver } from '../SheetUtils'; -import { procedurePool } from '../../../../database/Procedure'; import { Utils } from '../../base/Utils'; import { SliceGroup } from '../../../../bean/StateProcessThread'; +import {sliceSPTSender} from "../../../../database/data-trafic/SliceSender"; @element('tabpane-pts') export class TabPanePTS extends BaseElement { @@ -45,17 +45,11 @@ export class TabPanePTS extends BaseElement { getDataByPTS(ptsLeftNs: number, ptsRightNs: number, cpus: Array) { this.ptsTbl!.loading = true; - procedurePool.submitWithName( - 'logic0', - 'spt-getPTS', - { leftNs: ptsLeftNs, rightNs: ptsRightNs, cpus: cpus }, - undefined, - (res: Array) => { - this.ptsTbl!.loading = false; - this.ptsTbl!.recycleDataSource = res; - this.theadClick(res); - } - ); + sliceSPTSender(ptsLeftNs, ptsRightNs, cpus, 'spt-getPTS').then(res => { + this.ptsTbl!.loading = false; + this.ptsTbl!.recycleDataSource = res; + this.theadClick(res); + }); } private theadClick(data: Array) { let labels = this.ptsTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts index c70c1091f5962c26ce91ff96e6ac81b0aed1dda0..0e4081182b38dbc1be0648d76fb6a71f9a3668b1 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSPT.ts @@ -18,8 +18,8 @@ import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table import { SelectionParam } from '../../../../bean/BoxSelection'; import { SliceGroup } from '../../../../bean/StateProcessThread'; import { resizeObserver } from '../SheetUtils'; -import { procedurePool } from '../../../../database/Procedure'; import { Utils } from '../../base/Utils'; +import {sliceSPTSender} from "../../../../database/data-trafic/SliceSender"; @element('tabpane-spt') export class TabPaneSPT extends BaseElement { @@ -54,17 +54,11 @@ export class TabPaneSPT extends BaseElement { getDataBySPT(leftNs: number, rightNs: number, cpus: Array) { this.sptTbl!.loading = true; - procedurePool.submitWithName( - 'logic0', - 'spt-getSPT', - { leftNs: leftNs, rightNs: rightNs, cpus: cpus }, - undefined, - (res: Array) => { - this.sptTbl!.loading = false; - this.sptTbl!.recycleDataSource = res; - this.theadClick(res); - } - ); + sliceSPTSender(leftNs, rightNs, cpus, 'spt-getSPT').then(res => { + this.sptTbl!.loading = false; + this.sptTbl!.recycleDataSource = res; + this.theadClick(res); + }); } private theadClick(data: Array) { diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts index 7f9fea5ae59d3880710f50f32f7df5d4cb2856af..579879dae230bf2d89be806563842d55a2ea5a8a 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneSchedPriority.ts @@ -17,11 +17,11 @@ import { BaseElement, element } from '../../../../../base-ui/BaseElement'; import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; import { SelectionParam } from '../../../../bean/BoxSelection'; import { resizeObserver } from '../SheetUtils'; -import { procedurePool } from '../../../../database/Procedure'; import { Utils } from '../../base/Utils'; import { Priority } from '../../../../bean/StateProcessThread'; import { queryThreadStateArgsByName } from '../../../../database/sql/ProcessThread.sql'; import { FlagsConfig } from '../../../../component/SpFlags'; +import {sliceSPTSender} from "../../../../database/data-trafic/SliceSender"; @element('tabpane-sched-priority') export class TabPaneSchedPriority extends BaseElement { @@ -90,24 +90,18 @@ export class TabPaneSchedPriority extends BaseElement { } // thread_state表中runnable数据的Map const runnableMap = new Map(); - procedurePool.submitWithName( - 'logic0', - 'spt-getCpuPriorityByTime', - { leftNs: sptParam.leftNs, rightNs: sptParam.rightNs }, - undefined, - async (res: Array) => { - for (const item of res) { - if (['R', 'R+'].includes(item.state)) { - runnableMap.set(`${item.itId}_${item.endTs}`, item); - } - if (item.cpu === null || !sptParam.cpus.includes(item.cpu)) { - continue; - } - this.fetchData(item, setPriority, resultData, runnableMap); + sliceSPTSender(sptParam.leftNs, sptParam.rightNs, [], 'spt-getCpuPriorityByTime').then(res => { + for (const item of res) { + if (['R', 'R+'].includes(item.state)) { + runnableMap.set(`${item.id}_${item.startTime + item.dur}`, item); + } + if (item.cpu === null || !sptParam.cpus.includes(item.cpu)) { + continue; } - this.getDataByPriority(resultData); + this.fetchData(item, setPriority, resultData, runnableMap); } - ); + this.getDataByPriority(resultData); + }) } private fetchData( @@ -117,11 +111,11 @@ export class TabPaneSchedPriority extends BaseElement { runnableMap: Map ) { let strArg: string[] = []; - const args = this.strValueMap.get(item.argSetID); + const args = this.strValueMap.get(item.argSetId); if (args) { strArg = args!.split(','); } - const slice = Utils.SCHED_SLICE_MAP.get(`${item.itId}-${item.startTs}`); + const slice = Utils.SCHED_SLICE_MAP.get(`${item.id}-${item.startTime}`); if (slice) { const runningPriority = new Priority(); runningPriority.priority = slice.priority; @@ -130,7 +124,7 @@ export class TabPaneSchedPriority extends BaseElement { setPriority(runningPriority, strArg); resultData.push(runningPriority); - const runnableItem = runnableMap.get(`${item.itId}_${item.startTs}`); + const runnableItem = runnableMap.get(`${item.id}_${item.startTime}`); if (runnableItem) { const runnablePriority = new Priority(); runnablePriority.priority = slice.priority; diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts index 75b192e65bf1d33d5b965d9aae827960b61662bf..9a0c10b06083396bbeb3e64ddb2f415fdd7d1d84 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqDataCut.ts @@ -1206,21 +1206,21 @@ export class TabPaneFreqDataCut extends BaseElement {
- + - + - + - + - + - + - + - +
diff --git a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts index a4847f092cf3b36931ce99486626a326774bbfd8..d60816178649c880acedba692aca769ce499a331 100644 --- a/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts +++ b/ide/src/trace/component/trace/sheet/frequsage/TabPaneFreqUsage.ts @@ -33,6 +33,7 @@ import { export class TabPaneFreqUsage extends BaseElement { private threadStatesTbl: LitTable | null | undefined; private currentSelectionParam: SelectionParam | undefined; + private result: Array = []; set data(threadStatesParam: SelectionParam) { if (this.currentSelectionParam === threadStatesParam) { @@ -43,9 +44,7 @@ export class TabPaneFreqUsage extends BaseElement { this.threadStatesTbl!.recycleDataSource = []; // @ts-ignore this.threadStatesTbl.value = []; - this.init(threadStatesParam); - } - init(threadStatesParam: SelectionParam): void { + this.result = []; this.queryAllData(threadStatesParam); } async queryAllData(threadStatesParam: SelectionParam): Promise { @@ -77,6 +76,10 @@ export class TabPaneFreqUsage extends BaseElement { const LEFT_TIME: number = threadStatesParam.leftNs + threadStatesParam.recordStartNs; const RIGHT_TIME: number = threadStatesParam.rightNs + threadStatesParam.recordStartNs; let resultArr: Array = orgnazitionMap(runningResult, cpuFreqData, LEFT_TIME, RIGHT_TIME); + // 递归拿出来最底层的数据,并以进程层级的数据作为分割 + this.recursion(resultArr); + this.result = JSON.parse(JSON.stringify(this.result)); + mergeTotal(resultArr, fixTotal(this.result)); this.fixedDeal(resultArr); this.threadClick(resultArr); this.threadStatesTbl!.recycleDataSource = resultArr; @@ -97,13 +100,20 @@ export class TabPaneFreqUsage extends BaseElement { const MIN_PERCENT: number = 2; const MIN_FREQ: number = 3; for (let i = 0; i < arr.length; i++) { - let str: number; + let trackId: number; + // 若存在空位元素则进行删除处理 + if (arr[i] === undefined) { + arr.splice(i, 1); + i--; + continue; + } if (arr[i].thread?.indexOf('P') !== -1) { - str = Number(arr[i].thread?.slice(1)!); - arr[i].thread = Utils.PROCESS_MAP.get(str) === null ? 'Process ' + str : Utils.PROCESS_MAP.get(str)! + ' ' + str; + trackId = Number(arr[i].thread?.slice(1)!); + arr[i].thread = Utils.PROCESS_MAP.get(trackId) === null ? 'Process ' + trackId : Utils.PROCESS_MAP.get(trackId)! + ' ' + trackId; + } else if (arr[i].thread === 'summary data') { } else { - str = Number(arr[i].thread!.split('_')[1]); - arr[i].thread = Utils.THREAD_MAP.get(str) === null ? 'Thread ' + str : Utils.THREAD_MAP.get(str)! + ' ' + str; + trackId = Number(arr[i].thread!.split('_')[1]); + arr[i].thread = Utils.THREAD_MAP.get(trackId) === null ? 'Thread ' + trackId : Utils.THREAD_MAP.get(trackId)! + ' ' + trackId; } if (arr[i].cpu < 0 ) { // @ts-ignore @@ -174,6 +184,23 @@ export class TabPaneFreqUsage extends BaseElement { } } + /** + * + * @param arr 待整理的数组,会经过递归取到最底层的数据 + */ + recursion(arr: Array): void { + for (let idx = 0; idx < arr.length; idx++) { + if (arr[idx].cpu === -1) { + this.result.push(arr[idx]); + } + if (arr[idx].children) { + this.recursion(arr[idx].children!); + } else { + this.result.push(arr[idx]); + } + } + } + initElements(): void { this.threadStatesTbl = this.shadowRoot?.querySelector( "#tb-running-percent" @@ -238,6 +265,10 @@ function orgnazitionMap( if (runData[i].ts + runData[i].dur > rightNs) { runData[i].dur = rightNs - runData[i].ts; } + // 特殊处理数据表中dur为负值的情况 + if (runData[i].dur < 0) { + runData[i].dur = 0; + } // 分组整理数据 result.get(mapKey)?.push({ pid: runData[i].pid, @@ -464,3 +495,59 @@ function creatNewObj(cpu: number, flag: boolean = true): RunningFreqData { children: [] }; } + +/** + * + * @param arr 需要整理汇总的频点级数据 + * @returns 返回一个total->cpu->频点的三级树结构数组 + */ +function fixTotal(arr: Array): Array { + let result: Array = []; + let flag: number = -1; + // 数据入参的情况是,第一条为进程数据,其后是该进程下所有线程的数据。以进程数据做分割 + for (let i = 0; i < arr.length; i++) { + // 判断如果是进程数据,则将其children的数组清空,并以其作为最顶层数据 + if (arr[i].thread?.indexOf('P') !== -1) { + arr[i].children = []; + arr[i].thread = arr[i].thread + '-summary data'; + result.push(arr[i]); + // 标志判定当前数组的长度,也可用.length判断 + flag++; + } else { + // 非进程数据会进入到else中,去判断当前线程数据的cpu分组是否存在,不存在则进行创建 + if (result[flag].children![arr[i].cpu] === undefined) { + result[flag].children![arr[i].cpu] = {'thread': 'summary data', 'consumption': 0, 'cpu': arr[i].cpu, 'frequency': -1, 'dur': 0, 'percent': 0, children: []}; + } + // 每有一条数据要放到cpu分组下时,则将该cpu分组的各项数据累和 + result[flag].children![arr[i].cpu].consumption += arr[i].consumption; + result[flag].children![arr[i].cpu].dur += arr[i].dur; + result[flag].children![arr[i].cpu].percent += arr[i].percent; + // 查找当前cpu分组下是否存在与当前数据的频点相同的数据,返回相同数据的索引值 + let index: number = result[flag].children![arr[i].cpu].children?.findIndex((item) => item.frequency === arr[i].frequency)!; + // 若存在相同频点的数据,则进行合并,不同直接push + if (index === -1) { + arr[i].thread = 'summary data'; + result[flag].children![arr[i].cpu].children?.push(arr[i]); + } else { + result[flag].children![arr[i].cpu].children![index].consumption += arr[i].consumption; + result[flag].children![arr[i].cpu].children![index].dur += arr[i].dur; + result[flag].children![arr[i].cpu].children![index].percent += arr[i].percent; + } + } + } + return result; +} + +/** + * + * @param arr1 前次整理好的区分线程的数据 + * @param arr2 不区分线程的Total数据 + */ +function mergeTotal (arr1: Array, arr2: Array): void { + for (var i = 0; i < arr1.length; i++) { + const num: number = arr2.findIndex((item) => item.thread?.includes(arr1[i].thread!)); + arr2[num].thread = 'summary data'; + arr1[i].children?.unshift(arr2[num]); + arr2.splice(num, 1); + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts b/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts index 49ba49272926c6956767dd5133d514827a60913e..821ab5ec4577c858a60f31b3819b3bae0f75d599 100644 --- a/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts +++ b/ide/src/trace/component/trace/sheet/gpufreq/TabPaneGpufreqDataCut.ts @@ -321,7 +321,7 @@ export class TabPaneGpufreqDataCut extends BaseElement { if (Array.isArray(obj.children)) { obj.children.forEach((child) => { if (child.cycle !== undefined && child.dur !== undefined && child.value !== undefined && child.startNS !== undefined) { - result.push(new CycleDataBean(7,child.dur, child.value, child.startNS, child.cycle,'',1)); + result.push(new CycleDataBean(7,child.dur, Number((child.value / this.KUNIT).toFixed(3)), child.startNS, child.cycle,'',1)); }; }); }; diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts index cbf352b7c0bb4edab4d9161a793a80553fb65c6c..2086e06cd7d43192a4d62caf2772e3cf057c7915 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts @@ -65,7 +65,7 @@ export class TabPaneNMemory extends BaseElement { this.queryData(memoryParam); } - queryData(memoryParam: SelectionParam | any): void { + queryData(memoryParam: SelectionParam | any, resetFilter: boolean = true): void { this.eventTypes = []; if (memoryParam.nativeMemory.indexOf(this.defaultNativeTypes[0]) !== -1) { this.eventTypes.push("'AllocEvent'"); @@ -89,8 +89,16 @@ export class TabPaneNMemory extends BaseElement { // @ts-ignore this.memoryTbl.recycleDataSource = []; } - this.resetFilter(); - this.getDataByNativeMemoryWorker(memoryParam, true); + if (resetFilter) { + this.resetFilter(); + this.setNmMemoryLoading(true); + this.initFilterTypes(() => { + this.filterSetSelectList(this.filter!, 0); + this.getDataByNativeMemoryWorker(memoryParam, resetFilter); + }) + } else { + this.getDataByNativeMemoryWorker(memoryParam, resetFilter); + } } getDataByNativeMemoryWorker(val: SelectionParam | any, refresh = false): void { @@ -120,10 +128,7 @@ export class TabPaneNMemory extends BaseElement { } this.startNmMemoryWorker('native-memory-queryNativeHookEvent', args, (results: any[]) => { this.tblData!.recycleDataSource = []; - if (refresh) { - this.setNmMemoryLoading(true); - this.initFilterTypes(() => this.setNmMemoryLoading(false)); - } + this.setNmMemoryLoading(false) if (results.length > 0) { this.memorySource = results; this.memoryTbl!.recycleDataSource = this.memorySource; @@ -166,26 +171,18 @@ export class TabPaneNMemory extends BaseElement { fromStastics(val: SelectionParam | any): void { let nmFilterEl = this.shadowRoot?.querySelector('#filter'); - if (this.currentSelection != val) { + if (this.currentSelection !== val) { + this.resetFilter(); this.initFilterTypes(() => { this.currentSelection = val; + let typeIndexOf = this.setFilterNativeTypeSelection(this.currentSelection!); this.filterSetSelectList(nmFilterEl!, typeIndexOf); this.filterNativeType = `${typeIndexOf}`; - this.queryData(val); + this.rowSelectData = undefined; + this.queryData(val, false); }); - } - let typeIndexOf = this.nativeType.indexOf(val.statisticsSelectData.memoryTap); - if (this.statsticsSelection.indexOf(val.statisticsSelectData) === -1 && typeIndexOf === -1) { - this.statsticsSelection.push(val.statisticsSelectData); - this.nativeType.push(val.statisticsSelectData.memoryTap); - typeIndexOf = this.nativeType.length - 1; } else { - let index = this.statsticsSelection.findIndex((mt) => mt.memoryTap === val.statisticsSelectData.memoryTap); - if (index !== -1) { - this.statsticsSelection[index] = val.statisticsSelectData; - } - } - if (this.currentSelection === val) { + let typeIndexOf = this.setFilterNativeTypeSelection(val); this.tblData!.recycleDataSource = []; this.rowSelectData = undefined; this.filterSetSelectList(nmFilterEl!, typeIndexOf); @@ -195,6 +192,24 @@ export class TabPaneNMemory extends BaseElement { } } + private setFilterNativeTypeSelection(val: SelectionParam): number { + let typeIndexOf = -1; + if (val.statisticsSelectData) { + typeIndexOf = this.nativeType.indexOf(val.statisticsSelectData.memoryTap); + if (this.statsticsSelection.indexOf(val.statisticsSelectData) === -1 && typeIndexOf === -1) { + this.statsticsSelection.push(val.statisticsSelectData); + this.nativeType.push(val.statisticsSelectData.memoryTap); + typeIndexOf = this.nativeType.length - 1; + } else { + let index = this.statsticsSelection.findIndex((mt) => mt.memoryTap === val.statisticsSelectData.memoryTap); + if (index !== -1) { + this.statsticsSelection[index] = val.statisticsSelectData; + } + } + } + return typeIndexOf; + } + private filterSetSelectList(nmFilterEl: TabPaneFilter, typeIndexOf: number): void { nmFilterEl!.setSelectList( null, @@ -212,6 +227,9 @@ export class TabPaneNMemory extends BaseElement { initFilterTypes(initCallback?: () => void): void { this.nativeType = [...this.defaultNativeTypes]; this.statsticsSelection = []; + if (this.currentSelection) { + this.setFilterNativeTypeSelection(this.currentSelection); + } procedurePool.submitWithName('logic0', 'native-memory-get-responseType', {}, undefined, (res: any) => { this.filter!.setSelectList( null, @@ -226,7 +244,6 @@ export class TabPaneNMemory extends BaseElement { this.filter!.setFilterModuleSelect('#second-select', 'width', '150px'); this.filter!.setFilterModuleSelect('#third-select', 'width', '150px'); this.responseTypes = res; - this.resetFilter(); this.rowSelectData = undefined; if (initCallback) { initCallback(); diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts index a09f4bed9a000cf1a0b33e7f5936d69ca490e3b9..bed8dd35415516ac235598d89a395d0a74246a48 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts @@ -23,6 +23,7 @@ import { LitSearch } from '../../search/Search'; import { resizeObserver } from '../SheetUtils'; import { getTabSlicesAsyncFunc } from '../../../../database/sql/Func.sql'; import { getTabSlices } from '../../../../database/sql/ProcessThread.sql'; +import { FuncStruct } from '.././../../../database/ui-worker/ProcedureWorkerFunc'; @element('tabpane-slices') export class TabPaneSlices extends BaseElement { @@ -30,7 +31,6 @@ export class TabPaneSlices extends BaseElement { private slicesRange: HTMLLabelElement | null | undefined; private slicesSource: Array = []; private currentSelectionParam: SelectionParam | undefined; - private flag: boolean = false; set data(slicesParam: SelectionParam | any) { if (this.currentSelectionParam === slicesParam) { @@ -85,55 +85,64 @@ export class TabPaneSlices extends BaseElement { this.sortByColumn(evt.detail); }); // @ts-ignore - let testData; - this.slicesTbl!.addEventListener('contextmenu', async (evt) => { - let spApplication = document.querySelector('body > sp-application') as SpAllocations; - let spSystemTrace = spApplication?.shadowRoot?.querySelector( - 'div > div.content > sp-system-trace' - ) as SpSystemTrace; - let search = spApplication.shadowRoot?.querySelector('#lit-search') as LitSearch; - spSystemTrace?.visibleRows.forEach((it) => { - it.highlight = false; - it.draw(); - }); - spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); + let data; + this.slicesTbl!.addEventListener('row-click', (evt) => { // @ts-ignore - await spSystemTrace!.searchFunction([], testData.name).then((mixedResults) => { - if (mixedResults && mixedResults.length === 0) { - return; - } - // @ts-ignore - search.list = mixedResults.filter((item) => item.funName === testData.name); - const sliceRowList: Array> = []; - // 框选的slice泳道 - for (let row of spSystemTrace.rangeSelect.rangeTraceRow!) { - if (row.rowType === 'func') { - sliceRowList.push(row); - } - if (row.childrenList) { - for (const childrenRow of row.childrenList) { - if (childrenRow.rowType === 'func') { - sliceRowList.push(childrenRow); - } - } - } - } - if (sliceRowList.length === 0) { - return; - } - // @ts-ignore - this.slicesTblFreshSearchSelect(search, sliceRowList, testData, spSystemTrace); - }); + data = evt.detail.data; }); - this.slicesTbl!.addEventListener('row-click', async (evt) => { + this.slicesTbl!.addEventListener('click', () => { + FuncStruct.funcSelect = false; // @ts-ignore - testData = evt.detail.data; + this.orgnazitionData(data); + }); + this.slicesTbl!.addEventListener('contextmenu', () => { + FuncStruct.funcSelect = true; + // @ts-ignore + this.orgnazitionData(data); }); this.shadowRoot?.querySelector('#filterName')?.addEventListener('input', (e) => { // @ts-ignore this.findName(e.target.value); }); } + async orgnazitionData(data: Object): Promise { + let spApplication = document.querySelector('body > sp-application') as SpAllocations; + let spSystemTrace = spApplication?.shadowRoot?.querySelector( + 'div > div.content > sp-system-trace' + ) as SpSystemTrace; + let search = spApplication.shadowRoot?.querySelector('#lit-search') as LitSearch; + spSystemTrace?.visibleRows.forEach((it) => { + it.highlight = false; + it.draw(); + }); + spSystemTrace?.timerShaftEL?.removeTriangle('inverted'); + // @ts-ignore + await spSystemTrace!.searchFunction([], data.name).then((mixedResults) => { + if (mixedResults && mixedResults.length === 0) { + return; + } + // @ts-ignore + search.list = mixedResults.filter((item) => item.funName === data.name); + const sliceRowList: Array> = []; + // 框选的slice泳道 + for (let row of spSystemTrace.rangeSelect.rangeTraceRow!) { + if (row.rowType === 'func') { + sliceRowList.push(row); + } + if (row.childrenList) { + for (const childrenRow of row.childrenList) { + if (childrenRow.rowType === 'func') { + sliceRowList.push(childrenRow); + } + } + } + } + if (sliceRowList.length === 0) { + return; + } + this.slicesTblFreshSearchSelect(search, sliceRowList, data, spSystemTrace); + }); + } private slicesTblFreshSearchSelect( search: LitSearch, diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts index 32bde189428f315fe937d4a92fdec2a37af75d8b..4f5fedc380897cc9f393836c9671efcbf4464b8a 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneThreadUsage.ts @@ -18,7 +18,7 @@ import { LitTable } from '../../../../../base-ui/table/lit-table'; import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; import '../../../StackBar'; import { log } from '../../../../../log/Log'; -import { getProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; +import { getThreadUsageProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; import { Utils } from '../../base/Utils'; import { CpuStruct } from '../../../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { resizeObserver } from '../SheetUtils'; @@ -47,7 +47,7 @@ export class TabPaneThreadUsage extends BaseElement { - `; @@ -98,10 +98,10 @@ export class TabPaneThreadUsage extends BaseElement { if (threadUsageParam.processIds.includes(resultEl.pid)) { if (map.has(resultEl.tid)) { map.get(resultEl.tid)[`cpu${resultEl.cpu}`] = resultEl.wallDuration || 0; - map.get(resultEl.tid)[`cpu${resultEl.cpu}TimeStr`] = getProbablyTime(resultEl.wallDuration || 0); + map.get(resultEl.tid)[`cpu${resultEl.cpu}TimeStr`] = getThreadUsageProbablyTime(resultEl.wallDuration || 0); map.get(resultEl.tid).wallDuration = map.get(resultEl.tid).wallDuration + (resultEl.wallDuration || 0); - map.get(resultEl.tid).wallDurationTimeStr = getProbablyTime(map.get(resultEl.tid).wallDuration); + map.get(resultEl.tid).wallDurationTimeStr = getThreadUsageProbablyTime(map.get(resultEl.tid).wallDuration); } else { let process = Utils.PROCESS_MAP.get(resultEl.pid); let thread = Utils.THREAD_MAP.get(resultEl.tid); @@ -111,7 +111,7 @@ export class TabPaneThreadUsage extends BaseElement { thread: thread || 'null', process: process || 'null', wallDuration: resultEl.wallDuration || 0, - wallDurationTimeStr: getProbablyTime(resultEl.wallDuration || 0), + wallDurationTimeStr: getThreadUsageProbablyTime(resultEl.wallDuration || 0), }; for (let i = 0; i < this.cpuCount; i++) { threadStatesStruct[`cpu${i}`] = 0; @@ -119,7 +119,7 @@ export class TabPaneThreadUsage extends BaseElement { threadStatesStruct[`cpu${i}Ratio`] = '0'; } threadStatesStruct[`cpu${resultEl.cpu}`] = resultEl.wallDuration || 0; - threadStatesStruct[`cpu${resultEl.cpu}TimeStr`] = getProbablyTime(resultEl.wallDuration || 0); + threadStatesStruct[`cpu${resultEl.cpu}TimeStr`] = getThreadUsageProbablyTime(resultEl.wallDuration || 0); map.set(resultEl.tid, threadStatesStruct); } } @@ -142,7 +142,7 @@ export class TabPaneThreadUsage extends BaseElement { let cpuCount = CpuStruct.cpuCount; for (let index = 0; index < cpuCount; index++) { threadUsageHtml = `${threadUsageHtml} -
- + - + - + diff --git a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts index 72d693709162010fdd4511abc911a8c6e66b3bf7..71e084f0b9a5f95cbff0aae8e3ee9f6936083e92 100644 --- a/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts +++ b/ide/src/trace/component/trace/sheet/smaps/TabPaneSmapsStatistics.ts @@ -221,120 +221,117 @@ export class TabPaneSmapsStatistics extends BaseElement { this.filteredData(result, this.tblSmapsStatistics!, this.sumSize); }); } + + private initTreeObj(): Map { + let allTreeObjs: Map = new Map(); + allTreeObjs.set(SmapsType.TYPE_CODE_SYS, new SmapsTreeObj('CODE_SYS', '', 'CODE_SYS')) + allTreeObjs.set(SmapsType.TYPE_CODE_APP, new SmapsTreeObj('CODE_APP', '', 'CODE_APP')); + allTreeObjs.set(SmapsType.TYPE_DATA_SYS, new SmapsTreeObj('DATA_SYS', '', 'DATA_SYS')); + allTreeObjs.set(SmapsType.TYPE_DATA_APP, new SmapsTreeObj('DATA_APP', '', 'DATA_APP')); + allTreeObjs.set(SmapsType.TYPE_UNKNOWN_ANON, new SmapsTreeObj('UNKNOWN_ANON', '', 'UNKNOWN_ANON')); + allTreeObjs.set(SmapsType.TYPE_STACK, new SmapsTreeObj('STACK', '', 'STACK')); + allTreeObjs.set(SmapsType.TYPE_JS_HEAP, new SmapsTreeObj('JS_HEAP', '', 'JS_HEAP')); + allTreeObjs.set(SmapsType.TYPE_JAVA_VM, new SmapsTreeObj('JAVA_VM', '', 'JAVA_VM')); + allTreeObjs.set(SmapsType.TYPE_NATIVE_HEAP, new SmapsTreeObj('NATIVE_HEAP', '', 'NATIVE_HEAP')); + allTreeObjs.set(SmapsType.TYPE_ASHMEM, new SmapsTreeObj('ASHMEM', '', 'ASHMEM')); + allTreeObjs.set(SmapsType.TYPE_OTHER_SYS, new SmapsTreeObj('OTHER_SYS', '', 'OTHER_SYS')); + allTreeObjs.set(SmapsType.TYPE_OTHER_APP, new SmapsTreeObj('OTHER_APP', '', 'OTHER_APP')); + return allTreeObjs; + } + + private handleAllSMapsTreeObj(sumSize: number, allTreeObjs: Map): void { + let codeSysTree = allTreeObjs.get(SmapsType.TYPE_CODE_SYS); + let codeAppTree = allTreeObjs.get(SmapsType.TYPE_CODE_APP); + let dataSysTree = allTreeObjs.get(SmapsType.TYPE_DATA_SYS); + let dataAppTree = allTreeObjs.get(SmapsType.TYPE_DATA_APP); + let unKownTree = allTreeObjs.get(SmapsType.TYPE_UNKNOWN_ANON); + let stackTree = allTreeObjs.get(SmapsType.TYPE_STACK); + let jsTree = allTreeObjs.get(SmapsType.TYPE_JS_HEAP); + let javaVmTree = allTreeObjs.get(SmapsType.TYPE_JAVA_VM); + let nativeTree = allTreeObjs.get(SmapsType.TYPE_NATIVE_HEAP); + let ashMemTree = allTreeObjs.get(SmapsType.TYPE_ASHMEM); + let otherSysTree = allTreeObjs.get(SmapsType.TYPE_OTHER_SYS); + let otherAppTree = allTreeObjs.get(SmapsType.TYPE_OTHER_APP); + this.handleSmapsTreeObj(codeSysTree!, sumSize); + this.handleSmapsTreeObj(codeAppTree!, sumSize); + this.handleSmapsTreeObj(dataSysTree!, sumSize); + this.handleSmapsTreeObj(dataAppTree!, sumSize); + this.handleSmapsTreeObj(unKownTree!, sumSize); + this.handleSmapsTreeObj(stackTree!, sumSize); + this.handleSmapsTreeObj(jsTree!, sumSize); + this.handleSmapsTreeObj(javaVmTree!, sumSize); + this.handleSmapsTreeObj(nativeTree!, sumSize); + this.handleSmapsTreeObj(ashMemTree!, sumSize); + this.handleSmapsTreeObj(otherSysTree!, sumSize); + this.handleSmapsTreeObj(otherAppTree!, sumSize); + this.handleSmapsTreeObj(this.allTree!, sumSize); + } public filteredData(result: Array, table: LitTable, sumSize?: number): void { this.allTree = new SmapsTreeObj('All', '', '*All*'); - let codeSysTree: SmapsTreeObj = new SmapsTreeObj('CODE_SYS', '', 'CODE_SYS'); - let codeAppTree: SmapsTreeObj = new SmapsTreeObj('CODE_APP', '', 'CODE_APP'); - let dataSysTree: SmapsTreeObj = new SmapsTreeObj('DATA_SYS', '', 'DATA_SYS'); - let dataAppTree: SmapsTreeObj = new SmapsTreeObj('DATA_APP', '', 'DATA_APP'); - let unKownTree: SmapsTreeObj = new SmapsTreeObj('UNKNOWN_ANON', '', 'UNKNOWN_ANON'); - let stackTree: SmapsTreeObj = new SmapsTreeObj('STACK', '', 'STACK'); - let jsTree: SmapsTreeObj = new SmapsTreeObj('JS_HEAP', '', 'JS_HEAP'); - let javaVmTree: SmapsTreeObj = new SmapsTreeObj('JAVA_VM', '', 'JAVA_VM'); - let nativeTree: SmapsTreeObj = new SmapsTreeObj('NATIVE_HEAP', '', 'NATIVE_HEAP'); - let ashMemTree: SmapsTreeObj = new SmapsTreeObj('ASHMEM', '', 'ASHMEM'); - let otherSysTree: SmapsTreeObj = new SmapsTreeObj('OTHER_SYS', '', 'OTHER_SYS'); - let otherAppTree: SmapsTreeObj = new SmapsTreeObj('OTHER_APP', '', 'OTHER_APP'); + let allTreeObjs = this.initTreeObj(); if (result.length !== null && result.length > 0) { for (let id = 0; id < result.length; id++) { let smaps = result[id]; smaps.typeName = TYPE_STRING[smaps.type]; - switch (smaps.type) { - case SmapsType.TYPE_CODE_SYS: - this.handleTree(smaps, id, smaps.typeName, codeSysTree, sumSize); - break; - case SmapsType.TYPE_CODE_APP: - this.handleTree(smaps, id, smaps.typeName, codeAppTree, sumSize); - break; - case SmapsType.TYPE_DATA_SYS: - this.handleTree(smaps, id, smaps.typeName, dataSysTree, sumSize); - break; - case SmapsType.TYPE_DATA_APP: - this.handleTree(smaps, id, smaps.typeName, dataAppTree, sumSize); - break; - case SmapsType.TYPE_UNKNOWN_ANON: - this.handleTree(smaps, id, smaps.typeName, unKownTree, sumSize); - break; - case SmapsType.TYPE_STACK: - this.handleTree(smaps, id, smaps.typeName, stackTree, sumSize); - break; - case SmapsType.TYPE_JS_HEAP: - this.handleTree(smaps, id, smaps.typeName, jsTree, sumSize); - break; - case SmapsType.TYPE_JAVA_VM: - this.handleTree(smaps, id, smaps.typeName, javaVmTree, sumSize); - break; - case SmapsType.TYPE_NATIVE_HEAP: - this.handleTree(smaps, id, smaps.typeName, nativeTree, sumSize); - break; - case SmapsType.TYPE_ASHMEM: - this.handleTree(smaps, id, smaps.typeName, ashMemTree, sumSize); - break; - case SmapsType.TYPE_OTHER_SYS: - this.handleTree(smaps, id, smaps.typeName, otherSysTree, sumSize); - break; - case SmapsType.TYPE_OTHER_APP: - this.handleTree(smaps, id, smaps.typeName, otherAppTree, sumSize); - break; + if (allTreeObjs.has(smaps.type)) { + let newVar = allTreeObjs.get(smaps.type); + this.handleTree(smaps, id, smaps.typeName, newVar!, sumSize); } - this.handleAllDataTree(smaps, id, 'All', this.allTree, sumSize!); if (id === result.length - 1) { - this.handleSmapsTreeObj(codeSysTree, sumSize); - this.handleSmapsTreeObj(codeAppTree, sumSize); - this.handleSmapsTreeObj(dataSysTree, sumSize); - this.handleSmapsTreeObj(dataAppTree, sumSize); - this.handleSmapsTreeObj(unKownTree, sumSize); - this.handleSmapsTreeObj(stackTree, sumSize); - this.handleSmapsTreeObj(jsTree, sumSize); - this.handleSmapsTreeObj(javaVmTree, sumSize); - this.handleSmapsTreeObj(nativeTree, sumSize); - this.handleSmapsTreeObj(ashMemTree, sumSize); - this.handleSmapsTreeObj(otherSysTree, sumSize); - this.handleSmapsTreeObj(otherAppTree, sumSize); - this.handleSmapsTreeObj(this.allTree, sumSize!); - } - } - let treeList = [ - this.allTree, - codeSysTree, - codeAppTree, - dataSysTree, - dataAppTree, - unKownTree, - stackTree, - jsTree, - javaVmTree, - nativeTree, - ashMemTree, - otherSysTree, - otherAppTree, - ]; - this.totalTree = []; - for (let i = 0; i < treeList.length; i++) { - let tree = treeList[i]; - if (tree.children.length !== 0) { - this.totalTree.push(tree); + this.handleAllSMapsTreeObj(sumSize!, allTreeObjs); } } - - // @ts-ignore - this.totalTree.sort((previous, next) => next.size - previous.size); - this.totalTree.unshift(this.allTree); + this.setTotalTreeList(allTreeObjs); // 深拷贝数组,不然在给表格赋值之后删除了all那行,表格的数据this.value也会少了all行 let copyTotalTree = Array.from(this.totalTree); - table!.recycleDataSource = copyTotalTree; + table.recycleDataSource = copyTotalTree; this.totalTree.shift(); - table?.reMeauseHeight(); + table.reMeauseHeight(); } else { - table!.recycleDataSource = []; - table?.reMeauseHeight(); + table.recycleDataSource = []; + table.reMeauseHeight(); } } + private setTotalTreeList(allTreeObjs: Map): void { + let treeList = [ + this.allTree, + allTreeObjs.get(SmapsType.TYPE_CODE_SYS), + allTreeObjs.get(SmapsType.TYPE_CODE_APP), + allTreeObjs.get(SmapsType.TYPE_DATA_SYS), + allTreeObjs.get(SmapsType.TYPE_DATA_APP), + allTreeObjs.get(SmapsType.TYPE_UNKNOWN_ANON), + allTreeObjs.get(SmapsType.TYPE_STACK), + allTreeObjs.get(SmapsType.TYPE_JS_HEAP), + allTreeObjs.get(SmapsType.TYPE_JAVA_VM), + allTreeObjs.get(SmapsType.TYPE_NATIVE_HEAP), + allTreeObjs.get(SmapsType.TYPE_ASHMEM), + allTreeObjs.get(SmapsType.TYPE_OTHER_SYS), + allTreeObjs.get(SmapsType.TYPE_OTHER_APP), + ]; + this.totalTree = []; + for (let i = 0; i < treeList.length; i++) { + let tree = treeList[i]; + if (tree && tree.children.length !== 0) { + this.totalTree.push(tree); + } + } + this.totalTree.sort((previous, next) => next.size - previous.size); + this.totalTree.unshift(this.allTree!); + } + public sortByColumn(column: string, sort: number, table: LitTable): void { this.sortArray = [...this.totalTree]; + this.sortByKey(column, sort, table); + this.sortArray.unshift(this.allTree!); + let copySortArray = Array.from(this.sortArray); + table!.recycleDataSource = copySortArray; + this.sortArray.shift(); + } + + private sortByKey(column: string, sort: number, table: LitTable): void{ switch (sort) { case 0: this.sortArray.sort((previous, next) => { @@ -347,8 +344,18 @@ export class TabPaneSmapsStatistics extends BaseElement { default: switch (column) { case 'sizeStr': + case 'rssStr': + case 'pssStr': + case 'sharedCleanStr': + case 'sharedDirtyStr': + case 'privateCleanStr': + case 'privateDirtyStr': + case 'swapStr': + case 'swapPssStr': + let key = column.split('Str')[0]; this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.size - next.size : next.size - previous.size; + // @ts-ignore + return sort === 1 ? previous[key] - next[key] : next[key] - previous[key]; }); break; case 'sizeProStr': @@ -361,11 +368,6 @@ export class TabPaneSmapsStatistics extends BaseElement { return sort === 1 ? previous.count - next.count : next.count - previous.count; }); break; - case 'rssStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.rss - next.rss : next.rss - previous.rss; - }); - break; case 'typeName': this.sortArray.sort((previous, next) => { return sort === 1 @@ -373,48 +375,9 @@ export class TabPaneSmapsStatistics extends BaseElement { : next.typeName.toString().localeCompare(previous.typeName.toString()); }); break; - case 'pssStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.pss - next.pss : next.pss - previous.pss; - }); - break; - case 'sharedCleanStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.sharedClean - next.sharedClean : next.sharedClean - previous.sharedClean; - }); - break; - case 'sharedDirtyStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.sharedDirty - next.sharedDirty : next.sharedDirty - previous.sharedDirty; - }); - break; - case 'privateCleanStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.privateClean - next.privateClean : next.privateClean - previous.privateClean; - }); - break; - case 'privateDirtyStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.privateDirty - next.privateDirty : next.privateDirty - previous.privateDirty; - }); - break; - case 'swapStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.swap - next.swap : next.swap - previous.swap; - }); - break; - case 'swapPssStr': - this.sortArray.sort((previous, next) => { - return sort === 1 ? previous.swapPss - next.swapPss : next.swapPss - previous.swapPss; - }); - break; } break; } - this.sortArray.unshift(this.allTree!); - let copySortArray = Array.from(this.sortArray); - table!.recycleDataSource = copySortArray; - this.sortArray.shift(); } public initHtml(): string { diff --git a/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts b/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts index 776755cca15aebb75700daf0fe7c227044306b2c..60fa4090e54a0507ed12ecd2746c5aea799a99e5 100644 --- a/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts +++ b/ide/src/trace/component/trace/sheet/states/TabPaneFreqStatesDataCut.ts @@ -54,6 +54,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { private spSystemTrace: SpSystemTrace | undefined | null; private lineCycleNum: number = -1; private cycleIsClick: Boolean = false; + static isStateTabHover:boolean = false; // tab页入口函数 @@ -127,6 +128,8 @@ export class TabPaneFreqStatesDataCut extends BaseElement { threadFunc.style.border = '1px solid rgb(151,151,151)'; this.threadBindersTbl!.loading = true; this.funcNameCycleArr = await queryLoopFuncNameCycle(threadFuncName, threadIdValue, leftNS, rightNS); + this.cycleStartTime = this.funcNameCycleArr!.length > 0 ? this.funcNameCycleArr![0].cycleStartTime : undefined; + this.cycleEndTime = this.funcNameCycleArr!.length > 1 ? this.funcNameCycleArr![this.funcNameCycleArr!.length - 1].cycleStartTime : undefined; // 遍历设置周期的起始时间 for (let i = 0; i < this.funcNameCycleArr!.length - 1; i++) { this.funcNameCycleArr![i].endTime = this.funcNameCycleArr![i + 1].cycleStartTime; @@ -395,6 +398,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.cycleIsClick = false; this.lineCycleNum = -1; this.traceSheetEl!.systemLogFlag = undefined; + TabPaneFreqStatesDataCut.isStateTabHover = false; this.spSystemTrace?.refreshCanvas(false); }) @@ -426,6 +430,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { this.threadBindersTbl!.setCurrentSelection(currentData); if (currentData.cycle === this.lineCycleNum && this.cycleIsClick === true) { this.traceSheetEl!.systemLogFlag = undefined; + TabPaneFreqStatesDataCut.isStateTabHover = false; this.cycleIsClick = false; } else { let pointX: number = ns2x( @@ -435,7 +440,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { TraceRow.range!.totalNS, new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) ); - this.traceSheetEl!.systemLogFlag = new Flag( + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag( Math.floor(pointX), 0, 0, @@ -446,10 +451,11 @@ export class TabPaneFreqStatesDataCut extends BaseElement { true, '' ); + TabPaneFreqStatesDataCut.isStateTabHover = true; this.lineCycleNum = currentData.cycle; this.cycleIsClick = true; } - this.spSystemTrace?.refreshCanvas(false); + SpSegmentationChart.trace.refreshCanvas(false); } }); @@ -490,7 +496,7 @@ export class TabPaneFreqStatesDataCut extends BaseElement { // 筛选出点击的线程数据 filCycleData(pid: number, tid: number): Array { return this.filterState?.filter((v: StateGroup) => { - return v.pid === pid && v.tid === tid && v.ts + v.dur! > this.cycleStartTime! && v.ts + v.dur! < this.cycleEndTime!; + return v.pid === pid && v.tid === tid && v.ts > this.cycleStartTime! && v.ts + v.dur! < this.cycleEndTime!; }) }; @@ -678,27 +684,27 @@ export class TabPaneFreqStatesDataCut extends BaseElement {
- + - + - + - + - + - + - + - + - + - + - +
diff --git a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts index 8bf3f96579f4e5ca6aa32392a48648b4bce74010..564cdc318bbdc3e946d4ce3bad53d8fce70903fe 100644 --- a/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts +++ b/ide/src/trace/component/trace/sheet/task/TabPaneTaskFrames.ts @@ -21,8 +21,8 @@ import { FuncStruct } from '../../../../database/ui-worker/ProcedureWorkerFunc'; import { BaseStruct } from '../../../../database/ui-worker/ProcedureWorkerCommon'; import { SpSystemTrace } from '../../../SpSystemTrace'; import { type LitProgressBar } from '../../../../../base-ui/progress-bar/LitProgressBar'; -import {queryTaskListByExecuteTaskIds, queryTaskPoolTotalNum} from "../../../../database/sql/SqlLite.sql"; -import {queryConcurrencyTask} from "../../../../database/sql/Perf.sql"; +import { queryTaskListByExecuteTaskIds, queryTaskPoolTotalNum } from '../../../../database/sql/SqlLite.sql'; +import { queryConcurrencyTask } from '../../../../database/sql/Perf.sql'; const ALLOCATION_TASK = 'H:Task Allocation:'; const PERFORM_TASK = 'H:Task Perform:'; @@ -137,7 +137,7 @@ export class TabPaneTaskFrames extends BaseElement { task.taskPriority = Priority[priorityId]; task.taskST = this.getMsTime(sTime); task.taskET = this.getMsTime(eTime); - task.taskRT = this.getMsTime(rTime); + task.taskRT = rTime > 0 ? this.getMsTime(rTime) : '-'; this.taskFramesSource = [task]; this.taskFramesGroupSource = [[task]]; this.taskFramesTbl!!.recycleDataSource = this.taskFramesSource; @@ -399,7 +399,7 @@ export class TabPaneTaskFrames extends BaseElement { tempTask.taskPriority = Priority[value.priority!]; tempTask.taskST = this.getMsTime(executeStartTime - allocationStartTime); tempTask.taskET = this.getMsTime(executeTime); - tempTask.taskRT = this.getMsTime(returnEndTime); + tempTask.taskRT = returnEndTime > 0 ? this.getMsTime(returnEndTime) : '-'; tableList.push(tempTask); } } @@ -424,7 +424,7 @@ export class TaskTabStruct extends BaseStruct { dur: number | undefined; taskST: number | undefined; taskET: number | undefined; - taskRT: number | undefined; + taskRT?: number | string; allocationTaskRow: number | undefined; executeTaskRow: number | undefined; returnTaskRow: number | undefined; diff --git a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts index 45f50cdbd4b6e76fc587a255e6733b60d6322c68..0e81c05d96a36f2d938200dd75443057b335c0c3 100644 --- a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts +++ b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts @@ -54,12 +54,12 @@ export class Mark extends Graph { this.context2D.strokeStyle = '#999999'; this.context2D.lineWidth = 7; this.context2D.moveTo(this.frame.x, this.frame.y); - this.context2D.lineTo(this.frame.x, this.frame.y + this.frame.height / 3); + this.context2D.lineTo(this.frame.x, this.frame.y + 75 / 3); this.context2D.stroke(); this.context2D.strokeStyle = '#999999'; this.context2D.lineWidth = 1; this.context2D.moveTo(this.frame.x, this.frame.y); - this.context2D.lineTo(this.frame.x, this.frame.y + this.frame.height); + this.context2D.lineTo(this.frame.x, this.frame.y + 75); this.context2D.stroke(); this.context2D.closePath(); } @@ -540,6 +540,9 @@ export class RangeRuler extends Graph { this.pressedKeys.length == 0 || this.pressedKeys[this.pressedKeys.length - 1] !== keyboardEvent.key.toLocaleLowerCase() ) { + this.pressedKeys = this.pressedKeys.filter(v => { + return v !== keyboardEvent.key.toLocaleLowerCase(); + }) this.setCacheInterval(); this.range.refresh = this.cacheInterval.flag; if (currentSlicesTime) { diff --git a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts index 3b99e41381408ef83db3aa23dccf8ae3c1fd75b1..d55ce7d9792d1defa883226dc1702ec586333788 100644 --- a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts +++ b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -131,7 +131,24 @@ export class TabPaneFlag extends BaseElement { */ private eventHandler(): void { let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf; - tr[0].querySelector('.removeAll')!.addEventListener('click', () => { + this.removeAllClickEventByFlag(tr[0]); + // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1 + for (let i = 1; i < tr.length; i++) { + tr[i].querySelector('#color-input')!.value = this.flagList[i - 1].color; + // 点击色块修改颜色 + this.colorInputChangeEventByFlag(i, tr[i]); + // 修改备注 + tr[i].querySelector('#text-input')!.value = this.flagList[i - 1].text; + this.textInputKeyUpEventByFlag(i, tr[i]); + this.textInputBlurEventByFlag(i, tr[i]); + this.textInputFocusEventByFlag(tr[i]); + // 点击remove按钮移除 + this.removeClickEventByFlag(i, tr[i]); + } + } + + private removeAllClickEventByFlag(tr: HTMLDivElement): void { + tr.querySelector('.removeAll')!.addEventListener('click', () => { this.systemTrace!.flagList = []; let flagList = [...this.flagList]; for (let i = 0; i < flagList.length; i++) { @@ -141,69 +158,73 @@ export class TabPaneFlag extends BaseElement { this.flagList = []; return; }); + } - // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1 - for (let i = 1; i < tr.length; i++) { - tr[i].querySelector('#color-input')!.value = this.flagList[i - 1].color; - // 点击色块修改颜色 - tr[i].querySelector('#color-input')?.addEventListener('change', (event: any) => { - if (this.tableDataSource[i].startTime === this.flagList[i - 1].time) { - this.flagList[i - 1].color = event?.target.value; - document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[i - 1] })); - // 旗子颜色改变时,重绘泳道图 - this.systemTrace?.refreshCanvas(true); - } - event.stopPropagation(); - }); - // 修改备注 - tr[i].querySelector('#text-input')!.value = this.flagList[i - 1].text; - tr[i].querySelector('#text-input')?.addEventListener('keyup', (event: any) => { - if (this.tableDataSource[i].startTime === this.flagList[i - 1].time && event.keyCode === '13') { - this.flagList[i - 1].text = event?.target.value; - document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[i - 1] })); - // 旗子颜色改变时,重绘泳道图 - this.systemTrace?.refreshCanvas(true); - } - event.stopPropagation(); - }); + private colorInputChangeEventByFlag(index: number, tr: HTMLDivElement): void { + tr.querySelector('#color-input')?.addEventListener('change', (event: any) => { + if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) { + this.flagList[index - 1].color = event?.target.value; + document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] })); + // 旗子颜色改变时,重绘泳道图 + this.systemTrace?.refreshCanvas(true); + } + event.stopPropagation(); + }); + } - tr[i].querySelector('#text-input')?.addEventListener('blur', (event: any) => { - (window as any).flagInputFocus = false; - window.publish(window.SmartEvent.UI.KeyboardEnable, { - enable: true, - }); - if (this.tableDataSource[i].startTime === this.flagList[i - 1].time) { - this.flagList[i - 1].text = event?.target.value; - document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[i - 1] })); - // 旗子颜色改变时,重绘泳道图 - this.systemTrace?.refreshCanvas(true); - } - event.stopPropagation(); - }); + private textInputKeyUpEventByFlag(index: number, tr: HTMLDivElement): void { + tr.querySelector('#text-input')?.addEventListener('keyup', (event: any) => { + if (this.tableDataSource[index].startTime === this.flagList[index - 1].time && event.keyCode === '13') { + this.flagList[index - 1].text = event?.target.value; + document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] })); + // 旗子颜色改变时,重绘泳道图 + this.systemTrace?.refreshCanvas(true); + } + event.stopPropagation(); + }); + } - tr[i].querySelector('#text-input')?.addEventListener('focus', (event: any) => { - (window as any).flagInputFocus = true; - window.publish(window.SmartEvent.UI.KeyboardEnable, { - enable: false, - }); - let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf; - // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1 - for (let i = 1; i < tr.length; i++) { - tr[i].querySelector('#text-input')!.value = this.flagList[i - 1].text; - } + private textInputBlurEventByFlag(index: number, tr: HTMLDivElement): void { + tr.querySelector('#text-input')?.addEventListener('blur', (event: any) => { + (window as any).flagInputFocus = false; + window.publish(window.SmartEvent.UI.KeyboardEnable, { + enable: true, }); - // 点击remove按钮移除 - tr[i]!.querySelector('.remove')?.addEventListener('click', (event: any) => { - if (this.tableDataSource[i].startTime === this.flagList[i - 1].time) { - this.flagList[i - 1].hidden = true; - this.systemTrace!.flagList = this.flagList || []; - document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[i - 1] })); - // 移除时更新表格内容 - this.setTableData(); - } - event.stopPropagation(); + if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) { + this.flagList[index - 1].text = event?.target.value; + document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] })); + // 旗子颜色改变时,重绘泳道图 + this.systemTrace?.refreshCanvas(true); + } + event.stopPropagation(); + }); + } + + private textInputFocusEventByFlag(tr: HTMLDivElement): void { + tr.querySelector('#text-input')?.addEventListener('focus', (event: any) => { + (window as any).flagInputFocus = true; + window.publish(window.SmartEvent.UI.KeyboardEnable, { + enable: false, }); - } + let tr = this.panelTable!.shadowRoot!.querySelectorAll('.tr') as NodeListOf; + // 第一个tr是移除全部,所以跳过,从第二个tr开始,和this.flagList数组的第一个对应……,所以i从1开始,在this.flagList数组中取值时用i-1 + for (let i = 1; i < tr.length; i++) { + tr[i].querySelector('#text-input')!.value = this.flagList[i - 1].text; + } + }); + } + + private removeClickEventByFlag(index: number, tr: HTMLDivElement): void { + tr!.querySelector('.remove')?.addEventListener('click', (event: any) => { + if (this.tableDataSource[index].startTime === this.flagList[index - 1].time) { + this.flagList[index - 1].hidden = true; + this.systemTrace!.flagList = this.flagList || []; + document.dispatchEvent(new CustomEvent('flag-change', { detail: this.flagList[index - 1] })); + // 移除时更新表格内容 + this.setTableData(); + } + event.stopPropagation(); + }); } /** diff --git a/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts b/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts index 42ceb7793ddedef27c09326733d804b0b8d92c67..80b4212395f48d286df73631ae4217d73b627256 100644 --- a/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts +++ b/ide/src/trace/component/trace/timer-shaft/TimeRuler.ts @@ -52,7 +52,7 @@ export class TimeRuler extends Graph { } this.context2D.fillStyle = '#999'; // ------------------修改刻度尺文字------------------------ - this.context2D.font = '8px sans-serif'; + this.context2D.font = '10px sans-serif'; this.context2D.fillText(`${ns2s(index * this.stepNS)}`, x + 5, this.frame.height - 1); } this.context2D.stroke(); diff --git a/ide/src/trace/database/ConvertTraceWorker.ts b/ide/src/trace/database/ConvertTraceWorker.ts index eec44b28b25f2b1245f1475392376316568ce45d..87d71f8edf8e49ebaf8d89aa7b2ce9025258edb5 100644 --- a/ide/src/trace/database/ConvertTraceWorker.ts +++ b/ide/src/trace/database/ConvertTraceWorker.ts @@ -18,6 +18,12 @@ self.onerror = function (error: any) {}; let convertModule: any = null; +const CONTENT_TYPE_CMDLINES = 2; +const CONTENT_TYPE_TGIDS = 3; +const CONTENT_TYPE_HEADER_PAGE = 30; +const CONTENT_TYPE_PRINTK_FORMATS = 31; +const CONTENT_TYPE_KALLSYMS = 32; + function initConvertWASM() { return new Promise((resolve, reject) => { // @ts-ignore @@ -132,6 +138,12 @@ function handleRowTrace( return [totalSize, currentPosition, traceAllData]; } +function isCommonData(dataType: number): boolean { + return dataType === CONTENT_TYPE_CMDLINES || dataType === CONTENT_TYPE_TGIDS || + dataType === CONTENT_TYPE_HEADER_PAGE || dataType === CONTENT_TYPE_PRINTK_FORMATS || + dataType === CONTENT_TYPE_KALLSYMS +} + function setCommonDataOffsetList( e: MessageEvent, allRowTraceData: Uint8Array, @@ -153,7 +165,7 @@ function setCommonDataOffsetList( let currentVLength = Array.from(new Uint32Array(currentLData)); commonOffset += currentVLength[0]; commonDataOffset.endOffset = commonOffset; - if (dataType[0] === 2 || dataType[0] === 3) { + if (isCommonData(dataType[0])) { commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; commonDataOffsetList.push(commonDataOffset); } diff --git a/ide/src/trace/database/TraceWorker.ts b/ide/src/trace/database/TraceWorker.ts index 119d8dd7061923c9228cb622fc0d6f45a7d9556e..a140f583cab04382b121641d1b42bdca9b7caa92 100644 --- a/ide/src/trace/database/TraceWorker.ts +++ b/ide/src/trace/database/TraceWorker.ts @@ -34,8 +34,12 @@ let headUnitArray: Uint8Array | undefined; let thirdWasmMap = new Map(); let thirdJsonResult = new Map(); -let CONTENT_TYPE_CMDLINES = 2; -let CONTENT_TYPE_TGIDS = 3; +const CONTENT_TYPE_CMDLINES = 2; +const CONTENT_TYPE_TGIDS = 3; +const CONTENT_TYPE_HEADER_PAGE = 30; +const CONTENT_TYPE_PRINTK_FORMATS = 31; +const CONTENT_TYPE_KALLSYMS = 32; + let arkTsData: Array = []; let arkTsDataSize: number = 0; @@ -43,6 +47,8 @@ let arkTsDataSize: number = 0; let currentAction: string = ''; let currentActionId: string = ''; let ffrtFileCacheKey = '-1'; +let indexDB: IDBDatabase; +const maxSize = 48 * 1024 * 1024; let protoDataMap: Map = new Map(); function clear() { @@ -225,601 +231,701 @@ async function obligateFileBufferSpace(size: number): Promise { } } -self.onmessage = async (e: MessageEvent) => { - currentAction = e.data.action; - currentActionId = e.data.id; - let typeLength = 4; - if (e.data.action === 'reset') { - clear(); - } else if (e.data.action === 'open') { - await initWASM(); - ffrtFileCacheKey = '-1'; - // @ts-ignore - self.postMessage({ - id: e.data.id, - action: e.data.action, - ready: true, - index: 0, - }); - let uint8Array = new Uint8Array(e.data.buffer); - let callback = (heapPtr: number, size: number, isEnd: number) => { - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - bufferSlice.push(out); - if (isEnd == 1) { - arr = merged(); - bufferSlice.length = 0; - } - }; - let fn = Module.addFunction(callback, 'viii'); - reqBufferAddr = Module._Initialize(fn, REQ_BUF_SIZE); - let ffrtConvertCallback = (heapPtr: number, size: number, isEnd: number) => { - if (isEnd !== 1) { - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - bufferSlice.push(out); - } else { - arr = merged(); - bufferSlice.length = 0; - ffrtFileCacheKey = `ffrt/${new Date().getTime()}-${arr.buffer.byteLength}`; - saveTraceFileBuffer(ffrtFileCacheKey, arr.buffer); - } - }; - let tlvResultCallback = (heapPtr: number, size: number, type: number, isEnd: number) => { - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - protoDataMap.set(type, BatchSphData.decode(out).values); - }; - let fn1 = Module.addFunction(callback, 'viii'); - let fn2 = Module.addFunction(ffrtConvertCallback, 'viii'); - let tlvResultFun = Module.addFunction(tlvResultCallback, 'viiii'); - Module._TraceStreamer_Set_Log_Level(5); - reqBufferAddr = Module._Initialize(REQ_BUF_SIZE, fn1, tlvResultFun, fn2); - let parseConfig = e.data.parseConfig; - if (parseConfig !== '') { - let parseConfigArray = enc.encode(parseConfig); - let parseConfigAddr = Module._InitializeParseConfig(1024); - Module.HEAPU8.set(parseConfigArray, parseConfigAddr); - Module._TraceStreamerParserConfigEx(parseConfigArray.length); - } - let wasmConfigStr = e.data.wasmConfig; - if (wasmConfigStr != '' && wasmConfigStr.indexOf('WasmFiles') != -1) { - let wasmConfig = JSON.parse(wasmConfigStr); - let wasmConfigs = wasmConfig.WasmFiles; - let itemArray = wasmConfigs.map((item: any) => { - return item.componentId + ';' + item.pluginName; - }); - let thirdWasmStr: string = itemArray.join(';'); - let configUintArray = enc.encode(thirdWasmStr + ';'); - Module.HEAPU8.set(configUintArray, reqBufferAddr); - Module._TraceStreamer_Init_ThirdParty_Config(configUintArray.length); - let first = true; - let sendDataCallback = (heapPtr: number, size: number, componentID: number) => { - if (componentID === 100) { - if (first) { - first = false; - headUnitArray = Module.HEAPU8.slice(heapPtr, heapPtr + size); - } - return; - } - let configs = wasmConfigs.filter((wasmConfig: any) => { - return wasmConfig.componentId == componentID; - }); - if (configs.length > 0) { - let config = configs[0]; - let model = thirdWasmMap.get(componentID); - if (!model && config.componentId === componentID) { - importScripts(config.wasmJsName); - setThirdWasmMap(config, heapPtr, size, componentID); - } else { - let mm = model.model; - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - mm.HEAPU8.set(out, model.bufferAddr); - mm._ParserData(out.length, componentID); - } - } - }; - let fn1 = Module.addFunction(sendDataCallback, 'viii'); - let reqBufferAddr1 = Module._TraceStreamer_Set_ThirdParty_DataDealer(fn1, REQ_BUF_SIZE); - } - function initTraceRange(thirdMode: any): any { - let updateTraceTimeCallBack = (heapPtr: number, size: number) => { - let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); - Module.HEAPU8.set(out, reqBufferAddr); - Module._UpdateTraceTime(out.length); - }; - let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, 'vii'); - let mm = thirdMode._InitTraceRange(traceRangeFn, 1024); - return mm; +async function onmessageByOpenAction(e: MessageEvent): Promise { + await initWASM(); + ffrtFileCacheKey = '-1'; + // @ts-ignore + self.postMessage({ + id: e.data.id, + action: e.data.action, + ready: true, + index: 0, + }); + let uint8Array = new Uint8Array(e.data.buffer); + initModuleCallBackAndFun(); + parseThirdWasmByOpenAction(e); + let wrSize = 0; + let r2 = -1; + if (isRawTrace(e.data)) { + r2 = parseRawTraceByOpenAction(e, wrSize, r2, uint8Array); + } else { + r2 = parseNormalTraceByOpenAction(wrSize, r2, uint8Array); + } + Module._TraceStreamerParseDataOver(); + for (let value of thirdWasmMap.values()) { + value.model._TraceStreamer_In_ParseDataOver(); + } + postMessageByOpenAction(r2, e); +} + +function initModuleCallBackAndFun(): void { + let callback = (heapPtr: number, size: number, isEnd: number) => { + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + bufferSlice.push(out); + if (isEnd == 1) { + arr = merged(); + bufferSlice.length = 0; } - function setThirdWasmMap(config: any, heapPtr: number, size: number, componentID: number) { - let thirdMode = initThirdWASM(config.wasmName); - let configPluginName = config.pluginName; - let pluginNameUintArray = enc.encode(configPluginName); - let pluginNameBuffer = thirdMode._InitPluginName(pluginNameUintArray.length); - thirdMode.HEAPU8.set(pluginNameUintArray, pluginNameBuffer); - thirdMode._TraceStreamerGetPluginNameEx(configPluginName.length); - let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => { - if (isConfig == 1) { - let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); - thirdJsonResult.set(componentID, { - jsonConfig: dec.decode(out), - disPlayName: config.disPlayName, - pluginName: config.pluginName, - }); - } else { - let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); - bufferSlice.push(out); - if (isEnd == 1) { - arr = merged(); - bufferSlice.length = 0; - } - } - }; - let fn = thirdMode.addFunction(thirdQueryDataCallBack, 'viiii'); - let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE); - let mm = initTraceRange(thirdMode); - thirdMode._TraceStreamer_In_JsonConfig(); - thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr); - thirdMode._ParserData(headUnitArray!.length, 100); + }; + let fn = Module.addFunction(callback, 'viii'); + reqBufferAddr = Module._Initialize(fn, REQ_BUF_SIZE); + let ffrtConvertCallback = (heapPtr: number, size: number, isEnd: number) => { + if (isEnd !== 1) { let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - thirdMode.HEAPU8.set(out, thirdreqBufferAddr); - thirdMode._ParserData(out.length, componentID); - thirdWasmMap.set(componentID, { - model: thirdMode, - bufferAddr: thirdreqBufferAddr, - }); + bufferSlice.push(out); + } else { + arr = merged(); + bufferSlice.length = 0; + ffrtFileCacheKey = `ffrt/${new Date().getTime()}-${arr.buffer.byteLength}`; + saveTraceFileBuffer(ffrtFileCacheKey, arr.buffer); } - let wrSize = 0; - let r2 = -1; - if (isRawTrace(e.data)) { - let commonDataOffsetList: Array<{ - startOffset: number; - endOffset: number; - }> = []; - let offset = 12; - let tlvTypeLength = 4; - let headArray = uint8Array.slice(0, offset); - let commonTotalLength = 0; - while (offset < uint8Array.length) { - let commonDataOffset = { - startOffset: offset, - endOffset: offset, - }; - let dataTypeData = e.data.buffer.slice(offset, offset + tlvTypeLength); - offset += tlvTypeLength; - let dataType = Array.from(new Uint32Array(dataTypeData)); - let currentLData = e.data.buffer.slice(offset, offset + tlvTypeLength); - offset += tlvTypeLength; - let currentVLength = Array.from(new Uint32Array(currentLData)); - offset += currentVLength[0]; - commonDataOffset.endOffset = offset; - if (dataType[0] === CONTENT_TYPE_CMDLINES || dataType[0] === CONTENT_TYPE_TGIDS) { - commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; - commonDataOffsetList.push(commonDataOffset); + }; + let tlvResultCallback = (heapPtr: number, size: number, type: number, isEnd: number) => { + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + protoDataMap.set(type, BatchSphData.decode(out).values); + }; + let fn1 = Module.addFunction(callback, 'viii'); + let fn2 = Module.addFunction(ffrtConvertCallback, 'viii'); + let tlvResultFun = Module.addFunction(tlvResultCallback, 'viiii'); + Module._TraceStreamer_Set_Log_Level(5); + reqBufferAddr = Module._Initialize(REQ_BUF_SIZE, fn1, tlvResultFun, fn2); +} + +function parseThirdWasmByOpenAction(e: MessageEvent): void { + let parseConfig = e.data.parseConfig; + if (parseConfig !== '') { + let parseConfigArray = enc.encode(parseConfig); + let parseConfigAddr = Module._InitializeParseConfig(1024); + Module.HEAPU8.set(parseConfigArray, parseConfigAddr); + Module._TraceStreamerParserConfigEx(parseConfigArray.length); + } + let wasmConfigStr = e.data.wasmConfig; + if (wasmConfigStr != '' && wasmConfigStr.indexOf('WasmFiles') != -1) { + let wasmConfig = JSON.parse(wasmConfigStr); + let wasmConfigs = wasmConfig.WasmFiles; + let itemArray = wasmConfigs.map((item: any) => { + return item.componentId + ';' + item.pluginName; + }); + let thirdWasmStr: string = itemArray.join(';'); + let configUintArray = enc.encode(thirdWasmStr + ';'); + Module.HEAPU8.set(configUintArray, reqBufferAddr); + Module._TraceStreamer_Init_ThirdParty_Config(configUintArray.length); + let first = true; + let sendDataCallback = (heapPtr: number, size: number, componentID: number) => { + if (componentID === 100) { + if (first) { + first = false; + headUnitArray = Module.HEAPU8.slice(heapPtr, heapPtr + size); } + return; } - let frontData = new Uint8Array(headArray.byteLength + commonTotalLength); - // HeadArray - frontData.set(headArray, 0); - let lengthOffset = headArray.byteLength; - // common Data - commonDataOffsetList.forEach((item) => { - let commonData = uint8Array.slice(item.startOffset, item.endOffset); - frontData.set(commonData, lengthOffset); - lengthOffset += commonData.byteLength; + let configs = wasmConfigs.filter((wasmConfig: any) => { + return wasmConfig.componentId == componentID; }); - let freeData = uint8Array.slice(12); - let final = new Uint8Array(frontData.length + freeData.length); - final.set(frontData); - final.set(freeData, frontData.length); - wrSize = 0; - while (wrSize < final.length) { - const sliceLen = Math.min(final.length - wrSize, REQ_BUF_SIZE); - const dataSlice = final.subarray(wrSize, wrSize + sliceLen); - Module.HEAPU8.set(dataSlice, reqBufferAddr); - wrSize += sliceLen; - r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === final.length ? 1 : 0); - if (r2 === -1) { - break; - } - } - } else { - while (wrSize < uint8Array.length) { - const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE); - const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen); - Module.HEAPU8.set(dataSlice, reqBufferAddr); - wrSize += sliceLen; - r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === uint8Array.length ? 1 : 0); - if (r2 == -1) { - break; + if (configs.length > 0) { + let config = configs[0]; + let model = thirdWasmMap.get(componentID); + if (!model && config.componentId === componentID) { + importScripts(config.wasmJsName); + setThirdWasmMap(config, heapPtr, size, componentID); + } else { + let mm = model.model; + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + mm.HEAPU8.set(out, model.bufferAddr); + mm._ParserData(out.length, componentID); } } + }; + let fn1 = Module.addFunction(sendDataCallback, 'viii'); + let reqBufferAddr1 = Module._TraceStreamer_Set_ThirdParty_DataDealer(fn1, REQ_BUF_SIZE); + } +} + +function isCommonData(dataType: number): boolean { + return dataType === CONTENT_TYPE_CMDLINES || dataType === CONTENT_TYPE_TGIDS || + dataType === CONTENT_TYPE_HEADER_PAGE || dataType === CONTENT_TYPE_PRINTK_FORMATS || + dataType === CONTENT_TYPE_KALLSYMS +} + +function parseRawTraceByOpenAction(e: MessageEvent, wrSize: number, r2: number, uint8Array: Uint8Array): number { + let commonDataOffsetList: Array<{ startOffset: number; endOffset: number}> = []; // common Data + let offset = 12; + let tlvTypeLength = 4; + let headArray = uint8Array.slice(0, offset); + let commonTotalLength = 0; + while (offset < uint8Array.length) { + let commonDataOffset = {startOffset: offset, endOffset: offset}; + let dataTypeData = e.data.buffer.slice(offset, offset + tlvTypeLength); + offset += tlvTypeLength; + let dataType = Array.from(new Uint32Array(dataTypeData)); + let currentLData = e.data.buffer.slice(offset, offset + tlvTypeLength); + offset += tlvTypeLength; + let currentVLength = Array.from(new Uint32Array(currentLData)); + offset += currentVLength[0]; + commonDataOffset.endOffset = offset; + if (isCommonData(dataType[0])) { + commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; + commonDataOffsetList.push(commonDataOffset); } - Module._TraceStreamerParseDataOver(); - for (let value of thirdWasmMap.values()) { - value.model._TraceStreamer_In_ParseDataOver(); + } + let frontData = new Uint8Array(headArray.byteLength + commonTotalLength); // HeadArray + frontData.set(headArray, 0); + let lengthOffset = headArray.byteLength; + commonDataOffsetList.forEach((item) => { + let commonData = uint8Array.slice(item.startOffset, item.endOffset); + frontData.set(commonData, lengthOffset); + lengthOffset += commonData.byteLength; + }); + let freeData = uint8Array.slice(12); + let final = new Uint8Array(frontData.length + freeData.length); + final.set(frontData); + final.set(freeData, frontData.length); + wrSize = 0; + while (wrSize < final.length) { + const sliceLen = Math.min(final.length - wrSize, REQ_BUF_SIZE); + const dataSlice = final.subarray(wrSize, wrSize + sliceLen); + Module.HEAPU8.set(dataSlice, reqBufferAddr); + wrSize += sliceLen; + r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === final.length ? 1 : 0); + if (r2 === -1) { + break; } + } + return r2; +} + +function parseNormalTraceByOpenAction(wrSize: number, r2: number, uint8Array: Uint8Array): number { + while (wrSize < uint8Array.length) { + const sliceLen = Math.min(uint8Array.length - wrSize, REQ_BUF_SIZE); + const dataSlice = uint8Array.subarray(wrSize, wrSize + sliceLen); + Module.HEAPU8.set(dataSlice, reqBufferAddr); + wrSize += sliceLen; + r2 = Module._TraceStreamerParseDataEx(sliceLen, wrSize === uint8Array.length ? 1 : 0); if (r2 == -1) { - // @ts-ignore - self.postMessage({ - id: e.data.id, - action: e.data.action, - init: false, - msg: 'parse data error', + break; + } + } + return r2; +} + +function setThirdWasmMap(config: any, heapPtr: number, size: number, componentID: number) { + let thirdMode = initThirdWASM(config.wasmName); + let configPluginName = config.pluginName; + let pluginNameUintArray = enc.encode(configPluginName); + let pluginNameBuffer = thirdMode._InitPluginName(pluginNameUintArray.length); + thirdMode.HEAPU8.set(pluginNameUintArray, pluginNameBuffer); + thirdMode._TraceStreamerGetPluginNameEx(configPluginName.length); + let thirdQueryDataCallBack = (heapPtr: number, size: number, isEnd: number, isConfig: number) => { + if (isConfig == 1) { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + thirdJsonResult.set(componentID, { + jsonConfig: dec.decode(out), + disPlayName: config.disPlayName, + pluginName: config.pluginName, }); - return; + } else { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + bufferSlice.push(out); + if (isEnd == 1) { + arr = merged(); + bufferSlice.length = 0; + } } - temp_init_sql_list.forEach((item, index) => { - let r = createView(item); - // @ts-ignore - self.postMessage({ id: e.data.id, ready: true, index: index + 1 }); - }); - self.postMessage( - { - id: e.data.id, - action: e.data.action, - init: true, - msg: 'ok', - configSqlMap: thirdJsonResult, - buffer: e.data.buffer, - fileKey: ffrtFileCacheKey, - }, - // @ts-ignore - [e.data.buffer] - ); - } else if (e.data.action === 'exec') { - query(e.data.name, e.data.sql, e.data.params); - let jsonArray = convertJSON(); + }; + let fn = thirdMode.addFunction(thirdQueryDataCallBack, 'viiii'); + let thirdreqBufferAddr = thirdMode._Init(fn, REQ_BUF_SIZE); + let mm = initTraceRange(thirdMode); + thirdMode._TraceStreamer_In_JsonConfig(); + thirdMode.HEAPU8.set(headUnitArray, thirdreqBufferAddr); + thirdMode._ParserData(headUnitArray!.length, 100); + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + thirdMode.HEAPU8.set(out, thirdreqBufferAddr); + thirdMode._ParserData(out.length, componentID); + thirdWasmMap.set(componentID, { + model: thirdMode, + bufferAddr: thirdreqBufferAddr, + }); +} + +function postMessageByOpenAction(r2: number, e: MessageEvent): void { + if (r2 == -1) { // @ts-ignore self.postMessage({ id: e.data.id, action: e.data.action, - results: jsonArray, - }); - } else if (e.data.action === 'exec-proto') { - execProtoForWorker(e.data, (sql: string) => { - let sqlUintArray = enc.encode(sql); - if (e.data.params.trafic !== TraficEnum.ProtoBuffer) { - Module.HEAPU8.set(sqlUintArray, reqBufferAddr); - Module._TraceStreamerSqlQueryEx(sqlUintArray.length); - let jsonArray = convertJSON(); - return jsonArray; - } else { - let allArray = new Uint8Array(typeLength + sqlUintArray.length); - allArray[0] = e.data.name; - allArray.set(sqlUintArray, typeLength); - Module.HEAPU8.set(allArray, reqBufferAddr); - Module._TraceStreamerSqlQueryToProtoCallback(allArray.length); - let finalArrayBuffer = []; - if (protoDataMap.has(e.data.name)) { - finalArrayBuffer = protoDataMap.get(e.data.name); - protoDataMap.delete(e.data.name); - } - return finalArrayBuffer; - } + init: false, + msg: 'parse data error', }); - } else if (e.data.action == 'exec-buf') { - query(e.data.name, e.data.sql, e.data.params); - self.postMessage( - { id: e.data.id, action: e.data.action, results: arr!.buffer }, - // @ts-ignore - [arr.buffer] - ); - } else if (e.data.action.startsWith('exec-sdk')) { - querySdk(e.data.name, e.data.sql, e.data.params, e.data.action); - let jsonArray = convertJSON(); + return; + } + temp_init_sql_list.forEach((item, index) => { + let r = createView(item); // @ts-ignore - self.postMessage({ + self.postMessage({ id: e.data.id, ready: true, index: index + 1 }); + }); + self.postMessage( + { id: e.data.id, action: e.data.action, - results: jsonArray, - }); - } else if (e.data.action.startsWith('exec-metric')) { - queryMetric(e.data.sql); - let metricResult = dec.decode(arr); + init: true, + msg: 'ok', + configSqlMap: thirdJsonResult, + buffer: e.data.buffer, + fileKey: ffrtFileCacheKey, + }, // @ts-ignore - self.postMessage({ - id: e.data.id, - action: e.data.action, - results: metricResult, - }); - } else if (e.data.action == 'init-port') { - let port = e.ports[0]; - port.onmessage = (me) => { - query(me.data.action, me.data.sql, me.data.params); - let msg = { - id: me.data.id, - action: me.data.action, - results: arr!.buffer, - }; - port.postMessage(msg, [arr!.buffer]); + [e.data.buffer] + ); +} + +function initTraceRange(thirdMode: any): any { + let updateTraceTimeCallBack = (heapPtr: number, size: number) => { + let out: Uint8Array = thirdMode.HEAPU8.slice(heapPtr, heapPtr + size); + Module.HEAPU8.set(out, reqBufferAddr); + Module._UpdateTraceTime(out.length); + }; + let traceRangeFn = thirdMode.addFunction(updateTraceTimeCallBack, 'vii'); + let mm = thirdMode._InitTraceRange(traceRangeFn, 1024); + return mm; +} + +function onmessageByExecAction(e: MessageEvent): void { + query(e.data.name, e.data.sql, e.data.params); + let jsonArray = convertJSON(); + // @ts-ignore + self.postMessage({ + id: e.data.id, + action: e.data.action, + results: jsonArray, + }); +} + +function onmessageByExecProtoAction(e: MessageEvent): void { + let typeLength = 4; + execProtoForWorker(e.data, (sql: string) => { + let sqlUintArray = enc.encode(sql); + if (e.data.params.trafic !== TraficEnum.ProtoBuffer) { + Module.HEAPU8.set(sqlUintArray, reqBufferAddr); + Module._TraceStreamerSqlQueryEx(sqlUintArray.length); + let jsonArray = convertJSON(); + return jsonArray; + } else { + let allArray = new Uint8Array(typeLength + sqlUintArray.length); + allArray[0] = e.data.name; + allArray.set(sqlUintArray, typeLength); + Module.HEAPU8.set(allArray, reqBufferAddr); + Module._TraceStreamerSqlQueryToProtoCallback(allArray.length); + let finalArrayBuffer = []; + if (protoDataMap.has(e.data.name)) { + finalArrayBuffer = protoDataMap.get(e.data.name); + protoDataMap.delete(e.data.name); + } + return finalArrayBuffer; + } + }); +} + +function onmessageByExecBufAction(e: MessageEvent): void { + query(e.data.name, e.data.sql, e.data.params); + self.postMessage( + { id: e.data.id, action: e.data.action, results: arr!.buffer }, + // @ts-ignore + [arr.buffer] + ); +} + +function onmessageByExecSdkAction(e: MessageEvent): void { + querySdk(e.data.name, e.data.sql, e.data.params, e.data.action); + let jsonArray = convertJSON(); + // @ts-ignore + self.postMessage({ + id: e.data.id, + action: e.data.action, + results: jsonArray, + }); +} + +function onmessageByExecMetricAction(e: MessageEvent): void { + queryMetric(e.data.sql); + let metricResult = dec.decode(arr); + // @ts-ignore + self.postMessage({ + id: e.data.id, + action: e.data.action, + results: metricResult, + }); +} + +function onmessageByInitPortAction(e: MessageEvent): void { + let port = e.ports[0]; + port.onmessage = (me) => { + query(me.data.action, me.data.sql, me.data.params); + let msg = { + id: me.data.id, + action: me.data.action, + results: arr!.buffer, }; - } else if (e.data.action == 'download-db') { - let bufferSliceUint: Array = []; - let mergedUint = () => { - let length = 0; - bufferSliceUint.forEach((item) => { - length += item.length; - }); - let mergedArray = new Uint8Array(length); - let offset = 0; - bufferSliceUint.forEach((item) => { - mergedArray.set(item, offset); - offset += item.length; + port.postMessage(msg, [arr!.buffer]); + }; +} + +function onmessageByDownloadDBAction(e: MessageEvent): void { + let bufferSliceUint: Array = []; + let mergedUint = () => { + let length = 0; + bufferSliceUint.forEach((item) => { + length += item.length; + }); + let mergedArray = new Uint8Array(length); + let offset = 0; + bufferSliceUint.forEach((item) => { + mergedArray.set(item, offset); + offset += item.length; + }); + return mergedArray; + }; + let getDownloadDb = (heapPtr: number, size: number, isEnd: number) => { + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + bufferSliceUint.push(out); + if (isEnd == 1) { + let arr: Uint8Array = mergedUint(); + self.postMessage({ + id: e.data.id, + action: e.data.action, + results: arr, }); - return mergedArray; - }; - let getDownloadDb = (heapPtr: number, size: number, isEnd: number) => { - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - bufferSliceUint.push(out); - if (isEnd == 1) { - let arr: Uint8Array = mergedUint(); - self.postMessage({ - id: e.data.id, - action: e.data.action, - results: arr, + } + }; + let fn1 = Module.addFunction(getDownloadDb, 'viii'); + Module._WasmExportDatabase(fn1); +} + +function onmessageByUploadSoAction(e: MessageEvent): void { + uploadSoActionId = e.data.id; + let fileList = e.data.params as Array; + if (fileList) { + soFileList = fileList; + uploadFileIndex = 0; + if (!uploadSoCallbackFn) { + uploadSoCallbackFn = Module.addFunction(uploadSoCallBack, 'viii'); + } + uploadSoFile(soFileList[uploadFileIndex]).then(); + } +} + +async function saveDataToIndexDB( + currentChunk: Uint8Array, + currentChunkOffset: number, + fileType: string, + timStamp: number, + pageNum: number, + saveIndex: number, + saveStartOffset: number, +): Promise { + let freeArray = currentChunk.slice(0, currentChunkOffset); + await addDataToIndexeddb(indexDB, { + buf: freeArray, + id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, + fileType: `${fileType}_new`, + pageNum: pageNum, + startOffset: saveStartOffset, + endOffset: saveStartOffset + maxSize, + index: saveIndex, + timStamp: timStamp, + }); +} + +function cutLongTraceCallBackHandle( + traceFileType: string, + currentPageNum: number, + heapPtr: number, + size: number, + dataType: number, + newCutFilePageInfo: Map; dataTypes: string }] }> +) { + let key = `${traceFileType}_${currentPageNum}`; + let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); + if (DataTypeEnum.data === dataType) { + if (traceFileType === 'arkts') { + arkTsData.push(out); + arkTsDataSize += size; + } else { + if (newCutFilePageInfo.has(key)) { + let newVar = newCutFilePageInfo.get(key); + newVar?.dataArray.push({data: out, dataTypes: 'data'}); + } else { + newCutFilePageInfo.set(key, { + traceFileType: traceFileType, + dataArray: [{data: out, dataTypes: 'data'}], }); } - }; - let fn1 = Module.addFunction(getDownloadDb, 'viii'); - Module._WasmExportDatabase(fn1); - } else if (e.data.action === 'upload-so') { - uploadSoActionId = e.data.id; - let fileList = e.data.params as Array; - if (fileList) { - soFileList = fileList; - uploadFileIndex = 0; - if (!uploadSoCallbackFn) { - uploadSoCallbackFn = Module.addFunction(uploadSoCallBack, 'viii'); + } + } else if (DataTypeEnum.json === dataType) { + let cutFilePageInfo = newCutFilePageInfo.get(key); + if (cutFilePageInfo) { + let jsonStr: string = dec.decode(out); + let jsonObj = JSON.parse(jsonStr); + let valueArray: Array<{ offset: number; size: number }> = jsonObj.value; + cutFilePageInfo.dataArray.push({data: valueArray, dataTypes: 'json'}); + } + } +} + +function initSplitLongTraceModuleAndFun(headArray: Uint8Array, cutFileCallBack: (heapPtr: number, size: number, dataType: number, isEnd: number) => void): number { + splitReqBufferAddr = Module._InitializeSplitFile(Module.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); + Module.HEAPU8.set(headArray, splitReqBufferAddr); + Module._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); + return splitReqBufferAddr; +} + +async function handleDataTypeBySplitLongTrace( + receiveData: { data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }, + currentChunkOffset: number, + currentChunk: Uint8Array, + fileType: string, + timStamp: number, + pageNum: number, + saveIndex: number, + saveStartOffset: number +): Promise<[number, number, number, Uint8Array]> { + let receiveDataArray = receiveData.data as Uint8Array; + if (currentChunkOffset + receiveDataArray.length > maxSize) { + let freeSize = maxSize - currentChunkOffset; + let freeSaveData = receiveDataArray.slice(0, freeSize); + currentChunk.set(freeSaveData, currentChunkOffset); + await addDataToIndexeddb(indexDB, { + buf: currentChunk, + id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, + fileType: `${fileType}_new`, + pageNum: pageNum, + startOffset: saveStartOffset, + endOffset: saveStartOffset + maxSize, + index: saveIndex, + timStamp: timStamp, + }); + saveStartOffset += maxSize; + saveIndex++; + currentChunk = new Uint8Array(maxSize); + let remnantArray = receiveDataArray.slice(freeSize); + currentChunkOffset = 0; + currentChunk.set(remnantArray, currentChunkOffset); + currentChunkOffset += remnantArray.length; + } else { + currentChunk.set(receiveDataArray, currentChunkOffset); + currentChunkOffset += receiveDataArray.length; + } + return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; +} + +async function saveAllDataByLongTrace(range: IDBKeyRange, nowCutInfoList: Array, + searchDataInfo: { fileType: string; index: number; pageNum: number; startOffsetSize: number; endOffsetSize: number }[], + currentChunkOffset: number, currentChunk: Uint8Array, fileType: string, timStamp: number, pageNum: number, + saveIndex: number, saveStartOffset: number): Promise<[number, number, number, Uint8Array]> { + let transaction = indexDB.transaction(STORE_NAME, 'readonly'); + let store = transaction.objectStore(STORE_NAME); + let index = store.index('QueryCompleteFile'); + const getRequest = index.openCursor(range); + let queryAllData = await queryDataFromIndexeddb(getRequest); + let mergeData = indexedDataToBufferData(queryAllData); + for (let cutOffsetObjIndex = 0; cutOffsetObjIndex < nowCutInfoList.length; cutOffsetObjIndex++) { + let cutUseOffsetObj = nowCutInfoList[cutOffsetObjIndex]; + let endOffset = cutUseOffsetObj.offset + cutUseOffsetObj.size; + let sliceData = mergeData.slice( + cutUseOffsetObj.offset - searchDataInfo[0].startOffsetSize, + endOffset - searchDataInfo[0].startOffsetSize + ); + let sliceDataLength = sliceData.length; + if (currentChunkOffset + sliceDataLength >= maxSize) { + let handleCurrentData = new Uint8Array(currentChunkOffset + sliceDataLength); + let freeSaveArray = currentChunk.slice(0, currentChunkOffset); + handleCurrentData.set(freeSaveArray, 0); + handleCurrentData.set(sliceData, freeSaveArray.length); + let newSliceDataLength: number = Math.ceil(handleCurrentData.length / maxSize); + for (let newSliceIndex = 0; newSliceIndex < newSliceDataLength; newSliceIndex++) { + let newSliceSize = newSliceIndex * maxSize; + let number = Math.min(newSliceSize + maxSize, handleCurrentData.length); + let saveArray = handleCurrentData.slice(newSliceSize, number); + if (newSliceIndex === newSliceDataLength - 1 && number - newSliceSize < maxSize) { + currentChunk = new Uint8Array(maxSize); + currentChunkOffset = 0; + currentChunk.set(saveArray, currentChunkOffset); + currentChunkOffset += saveArray.length; + } else { + await addDataToIndexeddb(indexDB, { buf: saveArray, id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, + fileType: `${fileType}_new`, pageNum: pageNum, startOffset: saveStartOffset, + endOffset: saveStartOffset + maxSize, index: saveIndex, timStamp: timStamp}); + saveStartOffset += maxSize; + saveIndex++; + } } - uploadSoFile(soFileList[uploadFileIndex]).then(); + } else { + currentChunk.set(sliceData, currentChunkOffset); + currentChunkOffset += sliceDataLength; } - } else if (e.data.action === 'cut-file') { - cutFileByRange(e); - } else if (e.data.action === 'long_trace') { - await initWASM(); - let result = {}; - let headArray = e.data.params.headArray; - let timStamp = e.data.params.timeStamp; - let allIndexDataList = e.data.params.splitDataList; - let splitFileInfos = e.data.params.splitFileInfo as Array<{ - fileType: string; - startIndex: number; - endIndex: number; - size: number; - }>; - let maxSize = 48 * 1024 * 1024; - let maxPageNum = headArray.length / 1024; - let currentPageNum = 0; - let splitReqBufferAddr: number; - if (splitFileInfos) { - let splitFileInfo = splitFileInfos.filter((splitFileInfo) => splitFileInfo.fileType !== 'trace'); - if (splitFileInfo && splitFileInfo.length > 0) { - let traceFileType: string = ''; - let db = await openDB(); - let newCutFilePageInfo: Map< - string, - { - traceFileType: string; - dataArray: [{ data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }]; - } - > = new Map(); - let cutFileCallBack = (heapPtr: number, size: number, dataType: number, isEnd: number) => { - let key = `${traceFileType}_${currentPageNum}`; - let out: Uint8Array = Module.HEAPU8.slice(heapPtr, heapPtr + size); - if (DataTypeEnum.data === dataType) { - if (traceFileType === 'arkts') { - arkTsData.push(out); - arkTsDataSize += size; - } else { - if (newCutFilePageInfo.has(key)) { - let newVar = newCutFilePageInfo.get(key); - newVar?.dataArray.push({ data: out, dataTypes: 'data' }); - } else { - newCutFilePageInfo.set(key, { - traceFileType: traceFileType, - dataArray: [{ data: out, dataTypes: 'data' }], - }); - } - } - } else if (DataTypeEnum.json === dataType) { - let cutFilePageInfo = newCutFilePageInfo.get(key); - if (cutFilePageInfo) { - let jsonStr: string = dec.decode(out); - let jsonObj = JSON.parse(jsonStr); - let valueArray: Array<{ offset: number; size: number }> = jsonObj.value; - cutFilePageInfo.dataArray.push({ data: valueArray, dataTypes: 'json' }); - } - } - }; - splitReqBufferAddr = Module._InitializeSplitFile(Module.addFunction(cutFileCallBack, 'viiii'), REQ_BUF_SIZE); - Module.HEAPU8.set(headArray, splitReqBufferAddr); - Module._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); - for (let fileIndex = 0; fileIndex < splitFileInfo.length; fileIndex++) { - let fileInfo = splitFileInfo[fileIndex]; - traceFileType = fileInfo.fileType; - for (let pageNum = 0; pageNum < maxPageNum; pageNum++) { - currentPageNum = pageNum; - await splitFileAndSave( - timStamp, - fileInfo.fileType, - fileInfo.startIndex, - fileInfo.endIndex, - fileInfo.size, - db, - pageNum, - maxSize, - splitReqBufferAddr - ); - await initWASM(); - splitReqBufferAddr = Module._InitializeSplitFile( - Module.addFunction(cutFileCallBack, 'viiii'), - REQ_BUF_SIZE - ); - Module.HEAPU8.set(headArray, splitReqBufferAddr); - Module._TraceStreamerGetLongTraceTimeSnapEx(headArray.length); - } + } + return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; +} + +async function handleJsonTypeBySplitLongTrace( + receiveData: { data: Uint8Array | Array<{ offset: number; size: number }>; dataTypes: string }, + allIndexDataList: Array<{ fileType: string; index: number; pageNum: number; startOffsetSize: number; endOffsetSize: number }>, + fileType: string, + timStamp: number, + currentChunkOffset: number, + currentChunk: Uint8Array, + pageNum: number, + saveIndex: number, + saveStartOffset: number +): Promise<[number, number, number, Uint8Array]> { + let needCutMessage = receiveData.data as Array<{ offset: number; size: number }>; + let startOffset = needCutMessage[0].offset; + let nowCutInfoList: Array = []; + let isBeforeCutFinish = false; + for (let needCutIndex = 0; needCutIndex < needCutMessage.length; needCutIndex++) { + let cutInfo = needCutMessage[needCutIndex]; + if (isBeforeCutFinish) { + startOffset = cutInfo.offset; + isBeforeCutFinish = false; + nowCutInfoList.length = 0; + } + if (cutInfo.offset + cutInfo.size - startOffset >= maxSize * 10 || needCutIndex === needCutMessage.length - 1) { + nowCutInfoList.push(cutInfo); + let nowStartCutOffset = nowCutInfoList[0].offset; + let nowEndCutOffset = cutInfo.offset + cutInfo.size; + let searchDataInfo = allIndexDataList.filter( + (value: { fileType: string; index: number; pageNum: number; startOffsetSize: number; endOffsetSize: number;}) => { + return ( value.fileType === fileType && value.startOffsetSize <= nowEndCutOffset && + value.endOffsetSize >= nowStartCutOffset);}); + let startIndex = searchDataInfo[0].index; + let endIndex = searchDataInfo[searchDataInfo.length - 1].index; + let range = IDBKeyRange.bound([timStamp, fileType, 0, startIndex], + [timStamp, fileType, 0, endIndex],false,false); + [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = + await saveAllDataByLongTrace(range, nowCutInfoList, searchDataInfo, currentChunkOffset, currentChunk, fileType, + timStamp, pageNum, saveIndex, saveStartOffset); + isBeforeCutFinish = true; + } else { + nowCutInfoList.push(cutInfo); + } + } + return [currentChunkOffset, saveIndex, saveStartOffset, currentChunk]; +} + +async function handleAllTypeDataByLongTrace( + newCutFilePageInfo: Map; + dataTypes: string }] }>, + timStamp: number, + allIndexDataList: Array<{ + fileType: string; + index: number; + pageNum: number; + startOffsetSize: number; + endOffsetSize: number}> +): Promise { + for (const [fileTypePageNum, fileMessage] of newCutFilePageInfo) { + let fileTypePageNumArr = fileTypePageNum.split('_'); + let fileType = fileTypePageNumArr[0]; + let pageNum = Number(fileTypePageNumArr[1]); + let saveIndex = 0; + let saveStartOffset = 0; + let dataArray = fileMessage.dataArray; + let currentChunk = new Uint8Array(maxSize); + let currentChunkOffset = 0; + for (let fileDataIndex = 0; fileDataIndex < dataArray.length; fileDataIndex++) { + let receiveData = dataArray[fileDataIndex]; + if (receiveData.dataTypes === 'data') { + [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = + await handleDataTypeBySplitLongTrace(receiveData, currentChunkOffset, currentChunk, fileType, + timStamp, pageNum, saveIndex, saveStartOffset); + } else { + if (receiveData.data.length > 0) { + [currentChunkOffset, saveIndex, saveStartOffset, currentChunk] = + await handleJsonTypeBySplitLongTrace(receiveData, allIndexDataList, fileType, timStamp, + currentChunkOffset, currentChunk, pageNum, saveIndex, saveStartOffset); } - for (const [fileTypePageNum, fileMessage] of newCutFilePageInfo) { - let fileTypePageNumArr = fileTypePageNum.split('_'); - let fileType = fileTypePageNumArr[0]; - let pageNum = Number(fileTypePageNumArr[1]); - let saveIndex = 0; - let saveStartOffset = 0; - let dataArray = fileMessage.dataArray; - let currentChunk = new Uint8Array(maxSize); - let currentChunkOffset = 0; - for (let fileDataIndex = 0; fileDataIndex < dataArray.length; fileDataIndex++) { - let receiveData = dataArray[fileDataIndex]; - if (receiveData.dataTypes === 'data') { - let receiveDataArray = receiveData.data as Uint8Array; - if (currentChunkOffset + receiveDataArray.length > maxSize) { - let freeSize = maxSize - currentChunkOffset; - let freeSaveData = receiveDataArray.slice(0, freeSize); - currentChunk.set(freeSaveData, currentChunkOffset); - await addDataToIndexeddb(db, { - buf: currentChunk, - id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, - fileType: `${fileType}_new`, - pageNum: pageNum, - startOffset: saveStartOffset, - endOffset: saveStartOffset + maxSize, - index: saveIndex, - timStamp: timStamp, - }); - saveStartOffset += maxSize; - saveIndex++; - currentChunk = new Uint8Array(maxSize); - let remnantArray = receiveDataArray.slice(freeSize); - currentChunkOffset = 0; - currentChunk.set(remnantArray, currentChunkOffset); - currentChunkOffset += remnantArray.length; - } else { - currentChunk.set(receiveDataArray, currentChunkOffset); - currentChunkOffset += receiveDataArray.length; - } - } else { - if (receiveData.data.length > 0) { - let needCutMessage = receiveData.data as Array<{ offset: number; size: number }>; - let startOffset = needCutMessage[0].offset; - let nowCutInfoList: Array = []; - let isBeforeCutFinish = false; - for (let needCutIndex = 0; needCutIndex < needCutMessage.length; needCutIndex++) { - let cutInfo = needCutMessage[needCutIndex]; - if (isBeforeCutFinish) { - startOffset = cutInfo.offset; - isBeforeCutFinish = false; - nowCutInfoList.length = 0; - } - if ( - cutInfo.offset + cutInfo.size - startOffset >= maxSize * 10 || - needCutIndex === needCutMessage.length - 1 - ) { - nowCutInfoList.push(cutInfo); - let nowStartCutOffset = nowCutInfoList[0].offset; - let nowEndCutOffset = cutInfo.offset + cutInfo.size; - let searchDataInfo = allIndexDataList.filter( - (value: { - fileType: string; - index: number; - pageNum: number; - startOffsetSize: number; - endOffsetSize: number; - }) => { - return ( - value.fileType === fileType && - value.startOffsetSize <= nowEndCutOffset && - value.endOffsetSize >= nowStartCutOffset - ); - } - ); - let startIndex = searchDataInfo[0].index; - let endIndex = searchDataInfo[searchDataInfo.length - 1].index; - let transaction = db.transaction(STORE_NAME, 'readonly'); - let store = transaction.objectStore(STORE_NAME); - let index = store.index('QueryCompleteFile'); - let range = IDBKeyRange.bound( - [timStamp, fileType, 0, startIndex], - [timStamp, fileType, 0, endIndex], - false, - false - ); - const getRequest = index.openCursor(range); - let queryAllData = await queryDataFromIndexeddb(getRequest); - let mergeData = indexedDataToBufferData(queryAllData); - for (let cutOffsetObjIndex = 0; cutOffsetObjIndex < nowCutInfoList.length; cutOffsetObjIndex++) { - let cutUseOffsetObj = nowCutInfoList[cutOffsetObjIndex]; - let endOffset = cutUseOffsetObj.offset + cutUseOffsetObj.size; - let sliceData = mergeData.slice( - cutUseOffsetObj.offset - searchDataInfo[0].startOffsetSize, - endOffset - searchDataInfo[0].startOffsetSize - ); - let sliceDataLength = sliceData.length; - if (currentChunkOffset + sliceDataLength >= maxSize) { - let handleCurrentData = new Uint8Array(currentChunkOffset + sliceDataLength); - let freeSaveArray = currentChunk.slice(0, currentChunkOffset); - handleCurrentData.set(freeSaveArray, 0); - handleCurrentData.set(sliceData, freeSaveArray.length); - let newSliceDataLength: number = Math.ceil(handleCurrentData.length / maxSize); - for (let newSliceIndex = 0; newSliceIndex < newSliceDataLength; newSliceIndex++) { - let newSliceSize = newSliceIndex * maxSize; - let number = Math.min(newSliceSize + maxSize, handleCurrentData.length); - let saveArray = handleCurrentData.slice(newSliceSize, number); - if (newSliceIndex === newSliceDataLength - 1 && number - newSliceSize < maxSize) { - currentChunk = new Uint8Array(maxSize); - currentChunkOffset = 0; - currentChunk.set(saveArray, currentChunkOffset); - currentChunkOffset += saveArray.length; - } else { - await addDataToIndexeddb(db, { - buf: saveArray, - id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, - fileType: `${fileType}_new`, - pageNum: pageNum, - startOffset: saveStartOffset, - endOffset: saveStartOffset + maxSize, - index: saveIndex, - timStamp: timStamp, - }); - saveStartOffset += maxSize; - saveIndex++; - } - } - } else { - currentChunk.set(sliceData, currentChunkOffset); - currentChunkOffset += sliceDataLength; - } - } - isBeforeCutFinish = true; - } else { - nowCutInfoList.push(cutInfo); - } - } - } - } - } - if (currentChunkOffset !== 0) { - let freeArray = currentChunk.slice(0, currentChunkOffset); - await addDataToIndexeddb(db, { - buf: freeArray, - id: `${fileType}_new_${timStamp}_${pageNum}_${saveIndex}`, - fileType: `${fileType}_new`, - pageNum: pageNum, - startOffset: saveStartOffset, - endOffset: saveStartOffset + maxSize, - index: saveIndex, - timStamp: timStamp, - }); - saveStartOffset += maxSize; - saveIndex++; - } + } + } + if (currentChunkOffset !== 0) { + await saveDataToIndexDB(currentChunk, currentChunkOffset, fileType, timStamp, pageNum, saveIndex, saveStartOffset); + saveStartOffset += maxSize; + saveIndex++; + } + } +} + +async function onmessageByLongTraceAction(e: MessageEvent): Promise { + await initWASM(); + let result = {}; + let headArray = e.data.params.headArray; + let timStamp = e.data.params.timeStamp; + let allIndexDataList = e.data.params.splitDataList; + let splitFileInfos = e.data.params.splitFileInfo as Array<{ + fileType: string; startIndex: number; endIndex: number; size: number}>; + let maxPageNum = headArray.length / 1024; + let currentPageNum = 0; + let splitReqBufferAddr: number; + if (splitFileInfos) { + let splitFileInfo = splitFileInfos.filter((splitFileInfo) => splitFileInfo.fileType !== 'trace'); + if (splitFileInfo && splitFileInfo.length > 0) { + let traceFileType: string = ''; + indexDB = await openDB(); + let newCutFilePageInfo: Map; dataTypes: string }]}> = new Map(); + let cutFileCallBack = (heapPtr: number, size: number, dataType: number, isEnd: number) => { + cutLongTraceCallBackHandle(traceFileType, currentPageNum, heapPtr, size, dataType, newCutFilePageInfo); + }; + splitReqBufferAddr = initSplitLongTraceModuleAndFun(headArray, cutFileCallBack); + for (let fileIndex = 0; fileIndex < splitFileInfo.length; fileIndex++) { + let fileInfo = splitFileInfo[fileIndex]; + traceFileType = fileInfo.fileType; + for (let pageNum = 0; pageNum < maxPageNum; pageNum++) { + currentPageNum = pageNum; + await splitFileAndSave(timStamp, fileInfo, pageNum, splitReqBufferAddr); + await initWASM(); + splitReqBufferAddr = initSplitLongTraceModuleAndFun(headArray, cutFileCallBack); } } + await handleAllTypeDataByLongTrace(newCutFilePageInfo, timStamp, allIndexDataList); } - self.postMessage({ - id: e.data.id, - action: e.data.action, - results: result, - }); - return; + } + self.postMessage({ + id: e.data.id, + action: e.data.action, + results: result, + }); + return; +} + +self.onmessage = async (e: MessageEvent): Promise => { + currentAction = e.data.action; + currentActionId = e.data.id; + if (e.data.action === 'reset') { + clear(); + } else if (e.data.action === 'open') { + await onmessageByOpenAction(e); + } else if (e.data.action === 'exec') { + onmessageByExecAction(e); + } else if (e.data.action === 'exec-proto') { + onmessageByExecProtoAction(e); + } else if (e.data.action == 'exec-buf') { + onmessageByExecBufAction(e); + } else if (e.data.action.startsWith('exec-sdk')) { + onmessageByExecSdkAction(e); + } else if (e.data.action.startsWith('exec-metric')) { + onmessageByExecMetricAction(e); + } else if (e.data.action == 'init-port') { + onmessageByInitPortAction(e); + } else if (e.data.action == 'download-db') { + onmessageByDownloadDBAction(e); + } else if (e.data.action === 'upload-so') { + onmessageByUploadSoAction(e); + } else if (e.data.action === 'cut-file') { + cutFileByRange(e); + } else if (e.data.action === 'long_trace') { + await onmessageByLongTraceAction(e); } }; @@ -840,24 +946,22 @@ function indexedDataToBufferData(sourceData: any): Uint8Array { } async function splitFileAndSaveArkTs( - maxSize: number, currentChunkOffset: number, currentChunk: Uint8Array, fileType: string, pageNum: number, saveStartOffset: number, saveIndex: number, - timStamp: number, - db: IDBDatabase -) { + timStamp: number +): Promise { for (let arkTsAllDataIndex = 0; arkTsAllDataIndex < arkTsData.length; arkTsAllDataIndex++) { let currentArkTsData = arkTsData[arkTsAllDataIndex]; let freeSize = maxSize - currentChunkOffset; if (currentArkTsData.length > freeSize) { let freeSaveData = currentArkTsData.slice(0, freeSize); currentChunk.set(freeSaveData, currentChunkOffset); - let arg2 = setArg(currentChunk, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); - await addDataToIndexeddb(db, arg2); + let arg2 = setArg(currentChunk, fileType, pageNum, saveStartOffset, saveIndex, timStamp); + await addDataToIndexeddb(indexDB, arg2); saveStartOffset += maxSize; saveIndex++; let remnantData = currentArkTsData.slice(freeSize); @@ -872,8 +976,8 @@ async function splitFileAndSaveArkTs( currentChunk.set(saveArray, currentChunkOffset); currentChunkOffset += saveArray.length; } else { - let arg2 = setArg(saveArray, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); - await addDataToIndexeddb(db, arg2); + let arg2 = setArg(saveArray, fileType, pageNum, saveStartOffset, saveIndex, timStamp); + await addDataToIndexeddb(indexDB, arg2); saveStartOffset += maxSize; saveIndex++; } @@ -885,17 +989,11 @@ async function splitFileAndSaveArkTs( } } -const splitFileAndSave = async ( - timStamp: number, - fileType: string, - startIndex: number, - endIndex: number, - fileSize: number, - db: IDBDatabase, - pageNum: number, - maxSize: number, - splitReqBufferAddr?: any -): Promise => { +const splitFileAndSave = async (timStamp: number, fileInfo: any, pageNum: number, splitReqBufferAddr?: any): Promise => { + let fileType = fileInfo.fileType; + let fileSize = fileInfo.size; + let startIndex = fileInfo.startIndex; + let endIndex = fileInfo.endIndex; let queryStartIndex = startIndex; let queryEndIndex = startIndex; let saveIndex = 0; @@ -908,40 +1006,17 @@ const splitFileAndSave = async ( if (queryEndIndex > endIndex) { queryEndIndex = endIndex; } - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const index = store.index('QueryCompleteFile'); let range = getRange(timStamp, fileType, queryStartIndex, queryEndIndex); - const getRequest = index.openCursor(range); - let res = await queryDataFromIndexeddb(getRequest); + let res = await getIndexedDBQueryData(indexDB, range); queryStartIndex = queryEndIndex + 1; for (let i = 0; i < res.length; i++) { let arrayBuffer = res[i]; let uint8Array = new Uint8Array(arrayBuffer.buf); let cutFileSize = 0; while (cutFileSize < uint8Array.length) { - const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); - const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); - Module.HEAPU8.set(dataSlice, splitReqBufferAddr); - cutFileSize += sliceLen; - resultFileSize += sliceLen; - if (resultFileSize >= fileSize) { - Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 1, pageNum); - } else { - Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 0, pageNum); - } + [cutFileSize, resultFileSize] = execLongTraceSplitFileByModule(pageNum, fileSize, resultFileSize, cutFileSize, uint8Array, splitReqBufferAddr); if (arkTsDataSize > 0 && fileType === 'arkts') { - splitFileAndSaveArkTs( - maxSize, - currentChunkOffset, - currentChunk, - fileType, - pageNum, - saveStartOffset, - saveIndex, - timStamp, - db - ); + splitFileAndSaveArkTs(currentChunkOffset, currentChunk, fileType, pageNum, saveStartOffset, saveIndex, timStamp); } } } @@ -950,20 +1025,48 @@ const splitFileAndSave = async ( let remnantArray = new Uint8Array(currentChunkOffset); let remnantChunk = currentChunk.slice(0, currentChunkOffset); remnantArray.set(remnantChunk, 0); - let arg2 = setArg(remnantArray, fileType, pageNum, saveStartOffset, saveIndex, maxSize, timStamp); - await addDataToIndexeddb(db, arg2); + let arg2 = setArg(remnantArray, fileType, pageNum, saveStartOffset, saveIndex, timStamp); + await addDataToIndexeddb(indexDB, arg2); arkTsDataSize = 0; arkTsData.length = 0; } }; +async function getIndexedDBQueryData(db: IDBDatabase, range: IDBKeyRange): Promise { + const transaction = db.transaction(STORE_NAME, 'readonly'); + const store = transaction.objectStore(STORE_NAME); + const index = store.index('QueryCompleteFile'); + const getRequest = index.openCursor(range); + return await queryDataFromIndexeddb(getRequest) +} + +function execLongTraceSplitFileByModule( + pageNum: number, + fileSize: number, + resultFileSize: number, + cutFileSize: number, + uint8Array: Uint8Array, + splitReqBufferAddr?: any +): [number, number] { + const sliceLen = Math.min(uint8Array.length - cutFileSize, REQ_BUF_SIZE); + const dataSlice = uint8Array.subarray(cutFileSize, cutFileSize + sliceLen); + Module.HEAPU8.set(dataSlice, splitReqBufferAddr); + cutFileSize += sliceLen; + resultFileSize += sliceLen; + if (resultFileSize >= fileSize) { + Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 1, pageNum); + } else { + Module._TraceStreamerLongTraceSplitFileEx(sliceLen, 0, pageNum); + } + return [cutFileSize, resultFileSize]; +} + function setArg( remnantArray: Uint8Array, fileType: string, pageNum: number, saveStartOffset: number, saveIndex: number, - maxSize: number, timStamp: number ): any { return { @@ -1056,7 +1159,7 @@ function isRawTrace(uint8Array: Uint8Array): boolean { return rowTraceStr[0] === 57161; } -function cutFileBufferByOffSet(out: Uint8Array, uint8Array: Uint8Array) { +function cutFileBufferByOffSet(out: Uint8Array, uint8Array: Uint8Array): Uint8Array { let jsonStr: string = dec.decode(out); let jsonObj = JSON.parse(jsonStr); let valueArray: Array<{ type: number; offset: number; size: number }> = jsonObj.value; @@ -1108,7 +1211,7 @@ function cutFileBufferByOffSet(out: Uint8Array, uint8Array: Uint8Array) { return cutBuffer; } -function cutFileByRange(e: MessageEvent) { +function cutFileByRange(e: MessageEvent): void { let cutLeftTs = e.data.leftTs; let cutRightTs = e.data.rightTs; let uint8Array = new Uint8Array(e.data.buffer); @@ -1209,7 +1312,7 @@ function query(name: string, sql: string, params: any): void { Module._TraceStreamerSqlQueryEx(sqlUintArray.length); } -function querySdk(name: string, sql: string, sdkParams: any, action: string) { +function querySdk(name: string, sql: string, sdkParams: any, action: string): void { if (sdkParams) { Reflect.ownKeys(sdkParams).forEach((key: any) => { if (typeof sdkParams[key] === 'string') { diff --git a/ide/src/trace/database/data-trafic/CpuDataReceiver.ts b/ide/src/trace/database/data-trafic/CpuDataReceiver.ts index 8e77a6f530852e2216933675b09e596d432ef75c..9830fb70d6aae8a8be49e759a31c3969bfa3ac78 100644 --- a/ide/src/trace/database/data-trafic/CpuDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/CpuDataReceiver.ts @@ -84,7 +84,7 @@ export function searchDataHandler(data: any): void { let pidArr = data.params.pidArr as number[]; let tidArr = data.params.tidArr as number[]; for (let value of Array.from(cpuList.values())) { - res.push(...value.filter((cpuData) => pidArr.includes(cpuData.processId) || tidArr.includes(cpuData.tid))); + res.push(...value.filter((cpuData) => pidArr.includes(cpuData.pid || cpuData.processId) || tidArr.includes(cpuData.tid))); } res.sort((dataA, dataB) => dataA.startTime - dataB.startTime); arrayBufferHandler(data, res, true); @@ -107,7 +107,7 @@ function arrayBufferHandler(data: any, res: any[], transfer: boolean): void { cpu[i] = it.cpu; id[i] = it.id; nofinish[i] = it.nofinish; - processId[i] = it.processId; + processId[i] = it.pid || it.processId; argSetId[i] = it.argSetId; }); (self as unknown as Worker).postMessage( diff --git a/ide/src/trace/database/data-trafic/EBPFReceiver.ts b/ide/src/trace/database/data-trafic/EBPFReceiver.ts index ced67577128c93176cd7b0a56453be2f338569da..1f74edfdbcb60cbf2a5b1eb923716521351650d2 100644 --- a/ide/src/trace/database/data-trafic/EBPFReceiver.ts +++ b/ide/src/trace/database/data-trafic/EBPFReceiver.ts @@ -13,7 +13,6 @@ import { TraficEnum } from './utils/QueryEnum'; -let maxSize: number = 0; export const fileSystemDataGroupBy10MSProtoSql = (args: any): string => { return `SELECT startNs, endNs, max( count ) AS size, @@ -116,7 +115,6 @@ export const eBPFVmDataProtoSql = (args: any): string => { order by A.start_ts;`; }; -let eBPFMap = new Map(); /** * @param data * @param proc @@ -151,35 +149,20 @@ export function eBPFVmReceiver(data: any, proc: Function): void { let res = proc(sql); arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); } + function arrayBufferHandler(data: any, res: any[], transfer: boolean): void { let startNS = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startNS); let endNS = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.endNS); let size = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.size); let dur = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.dur); let height = new Int32Array(transfer ? res.length : data.params.sharedArrayBuffers.height); - let type: any; - - if (data.params.type) { - type = data.params.type; - } else if (data.params.typeArr) { - type = data.params.typeArr; - } else { - type = -1; - } - if (!eBPFMap!.get(type)) { - maxSize = Math.max( - ...res.map((it) => { - return it.size; - }) - ); - eBPFMap.set(type, maxSize); - } + let maxSize = Math.max(...res.map((it) => it.size)); res.forEach((it, i) => { startNS[i] = it.startNs; endNS[i] = it.endNs; size[i] = it.size; dur[i] = it.dur; - height[i] = Math.ceil((it.size / eBPFMap!.get(type)!) * 36); + height[i] = Math.ceil(it.size / maxSize * 36); }); (self as unknown as Worker).postMessage( { diff --git a/ide/src/trace/database/data-trafic/FrameDynamicEffectSender.ts b/ide/src/trace/database/data-trafic/FrameDynamicEffectSender.ts index 3b62caf4c3761188b253803cfba150ef478efe3e..54b653f92d2411a2e1714a26377508a276a332d0 100644 --- a/ide/src/trace/database/data-trafic/FrameDynamicEffectSender.ts +++ b/ide/src/trace/database/data-trafic/FrameDynamicEffectSender.ts @@ -52,6 +52,7 @@ export function frameAnimationSender(row: TraceRow): Promi } function animationBufferHandler(res: any, len: number): any[] { + let recordNs: number = (window as any).recordStartNS; let outArr = []; let animationId = new Uint16Array(res.animationId); let status = new Uint16Array(res.status); @@ -67,6 +68,8 @@ function animationBufferHandler(res: any, len: number): any[] { endTs: endTs[index], dur: dur[index], depth: depth[index], + inputTime: startTs[index] + recordNs, + endTime: endTs[index] + recordNs, }); } return outArr; diff --git a/ide/src/trace/database/data-trafic/SliceReceiver.ts b/ide/src/trace/database/data-trafic/SliceReceiver.ts new file mode 100644 index 0000000000000000000000000000000000000000..7fe612917e9c16c3fca50bfb9d4d75816746d476 --- /dev/null +++ b/ide/src/trace/database/data-trafic/SliceReceiver.ts @@ -0,0 +1,310 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { + cpuList, + processList, + sliceList, + threadStateList +} from './utils/AllMemoryCache'; + +export const sliceSqlMem = (args: any): string => { + return ` + SELECT B.pid, + B.cpu, + B.tid, + B.itid as id, + B.dur AS dur, + B.state, + B.ts - ${args.recordStartNS} AS startTime, + ifnull(B.arg_setid, -1) as argSetId + from thread_state AS B + where B.itid is not null and B.ts + ifnull(B.dur, 0) < ${args.recordEndNS}`; +}; + +export function sliceReceiver(data: any, proc: Function): void { + let count = { + cpu: new Map(), + }; + sliceList.clear(); + cpuList.clear(); + processList.clear(); + threadStateList.clear(); + let list: any[] = proc(sliceSqlMem(data.params)); + sliceList.set(0, list); + for (let i = 0; i < list.length; i++) { + let slice = list[i]; + if (slice.cpu !== null && slice.cpu !== undefined) { + if (cpuList.has(slice.cpu)) { + let arr = cpuList.get(slice.cpu) || []; + let last = arr[arr.length - 1]; + if (last && (last.dur === -1 || last.dur === null || last.dur === undefined)) { + last.dur = slice.startTime - last.startTime; + } + cpuList.get(slice.cpu)!.push(slice); + } else { + cpuList.set(slice.cpu,[slice]); + } + } + if (slice.pid >= 0 && slice.cpu !== null && slice.cpu !== undefined) { + if (processList.has(slice.pid)) { + processList.get(slice.pid)!.push(slice); + } else { + processList.set(slice.pid, [slice]); + } + } + if (slice.pid >= 0 && slice.tid >= 0) { + let key = `${slice.pid}-${slice.tid}`; + if (threadStateList.has(key)) { + threadStateList.get(key)!.push(slice); + } else { + threadStateList.set(key, [slice]); + } + } + } + for (let key of cpuList.keys()) { + let arr = cpuList.get(key) || []; + let last = arr[arr.length - 1]; + if (last && (last.dur === -1 || last.dur === null || last.dur === undefined)) { + let totalNs = data.params.recordEndNS - data.params.recordStartNS; + last.dur = totalNs - last.startTime; + } + count.cpu.set(key, arr.length); + } + postMsg(data, count); +} + +export function sliceSPTReceiver(data: any) { + if (data && data.params.func) { + switch (data.params.func) { + case 'spt-getPTS': + getPTS(data); + break; + case 'spt-getSPT': + getSPT(data); + break; + case 'spt-getCpuPriorityByTime': + sptGetCpuPriorityByTime(data); + break; + } + } +} + +function postMsg(data: any, res: any): void { + (self as unknown as Worker).postMessage( + { + id: data.id, + action: data.action, + results: res, + len: res.length, + transfer: false, + }, [] + ); +} + +function getSPT(data: any): void { + let threadSlice = sliceList.get(0) || []; + let sptFilter = threadSlice.filter( + (it) => + Math.max(data.params.leftNs, it.startTime!) < Math.min(data.params.rightNs, it.startTime! + it.dur!) && + (it.cpu === null || it.cpu === undefined || data.params.cpus.includes(it.cpu)) + ); + let group: any = {}; + sptFilter.forEach((slice) => { + let item = { + title: `T-${slice.tid}`, + count: 1, + state: slice.state, + pid: slice.pid, + tid: slice.tid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + }; + if (group[`${slice.state}`]) { + setSPTData(group, slice, item); + } else { + group[`${slice.state}`] = { + title: `S-${slice.state}`, + count: 1, + state: slice.state, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [ + { + title: `P-${slice.pid}`, + count: 1, + state: slice.state, + pid: slice.pid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [item], + }, + ], + }; + } + }); + postMsg(data, Object.values(group)); +} + +function getPTS(data: any): void { + let threadSlice = sliceList.get(0) || []; + let ptsFilter = threadSlice.filter( + (it) => + Math.max(data.params.leftNs, it.startTime!) < Math.min(data.params.rightNs, it.startTime! + it.dur!) && + (it.cpu === null || it.cpu === undefined || data.params.cpus.includes(it.cpu)) + ); + let group: any = {}; + ptsFilter.forEach((slice) => { + let title = `S-${slice.state}`; + let item = setStateData(slice, title); + if (group[`${slice.pid}`]) { + let process = group[`${slice.pid}`]; + process.count += 1; + process.wallDuration += slice.dur; + process.minDuration = Math.min(process.minDuration, slice.dur!); + process.maxDuration = Math.max(process.maxDuration, slice.dur!); + process.avgDuration = (process.wallDuration / process.count).toFixed(2); + let thread = process.children.find((child: any) => child.title === `T-${slice.tid}`); + if (thread) { + thread.count += 1; + thread.wallDuration += slice.dur; + thread.minDuration = Math.min(thread.minDuration, slice.dur!); + thread.maxDuration = Math.max(thread.maxDuration, slice.dur!); + thread.avgDuration = (thread.wallDuration / thread.count).toFixed(2); + let state = thread.children.find((child: any) => child.title === `S-${slice.state}`); + if (state) { + state.count += 1; + state.wallDuration += slice.dur; + state.minDuration = Math.min(state.minDuration, slice.dur!); + state.maxDuration = Math.max(state.maxDuration, slice.dur!); + state.avgDuration = (state.wallDuration / state.count).toFixed(2); + } else { + thread.children.push(item); + } + } else { + let processChild = setThreadData(slice, item); + process.children.push(processChild); + } + } else { + group[`${slice.pid}`] = setProcessData(slice, item); + } + }); + postMsg(data, Object.values(group)); +} + +function sptGetCpuPriorityByTime(data: any): void { + let threadSlice = sliceList.get(0) || []; + const result = threadSlice.filter((item: any) => { + return !(item.startTime + item.dur < data.params.leftNs || item.startTime! > data.params.rightNs); + }); + postMsg(data, result); +} + +function setStateData(slice: any, title: string): any { + return { + title: title, + count: 1, + state: slice.state, + tid: slice.tid, + pid: slice.pid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + }; +} + +function setThreadData(slice: any, item: any): any { + return { + title: `T-${slice.tid}`, + count: 1, + tid: slice.tid, + pid: slice.pid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [item], + }; +} + +function setProcessData(slice: any, item: any): any { + return { + title: `P-${slice.pid}`, + count: 1, + pid: slice.pid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [ + { + title: `T-${slice.tid}`, + count: 1, + pid: slice.pid, + tid: slice.tid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [item], + }, + ], + }; +} + +function setSPTData(group: any, slice: any, item: any): void { + let state = group[`${slice.state}`]; + state.count += 1; + state.wallDuration += slice.dur; + state.minDuration = Math.min(state.minDuration, slice.dur!); + state.maxDuration = Math.max(state.maxDuration, slice.dur!); + state.avgDuration = (state.wallDuration / state.count).toFixed(2); + let process = state.children.find((child: any) => child.title === `P-${slice.pid}`); + if (process) { + process.count += 1; + process.wallDuration += slice.dur; + process.minDuration = Math.min(process.minDuration, slice.dur!); + process.maxDuration = Math.max(process.maxDuration, slice.dur!); + process.avgDuration = (process.wallDuration / process.count).toFixed(2); + let thread = process.children.find((child: any) => child.title === `T-${slice.tid}`); + if (thread) { + thread.count += 1; + thread.wallDuration += slice.dur; + thread.minDuration = Math.min(thread.minDuration, slice.dur!); + thread.maxDuration = Math.max(thread.maxDuration, slice.dur!); + thread.avgDuration = (thread.wallDuration / thread.count).toFixed(2); + } else { + process.children.push(item); + } + } else { + state.children.push({ + title: `P-${slice.pid}`, + count: 1, + state: slice.state, + pid: slice.pid, + minDuration: slice.dur || 0, + maxDuration: slice.dur || 0, + wallDuration: slice.dur || 0, + avgDuration: `${slice.dur}`, + children: [item], + }); + } +} + diff --git a/ide/src/trace/database/data-trafic/SliceSender.ts b/ide/src/trace/database/data-trafic/SliceSender.ts new file mode 100644 index 0000000000000000000000000000000000000000..89c8d2d02cbf1a1f36564199853815d5268d6d58 --- /dev/null +++ b/ide/src/trace/database/data-trafic/SliceSender.ts @@ -0,0 +1,47 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { QueryEnum, TraficEnum } from './utils/QueryEnum'; +import { threadPool } from '../SqlLite'; +import { TraceRow } from '../../component/trace/base/TraceRow'; + +export function sliceSender(): Promise { + let trafic: number = TraficEnum.Memory; + return new Promise((resolve): void => { + threadPool.submitProto(QueryEnum.SliceData, { + trafic: trafic, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + recordStartNS: window.recordStartNS, + recordEndNS: window.recordEndNS, + }, (res: any): void => { + resolve(res); + }); + }); +} + +export function sliceSPTSender(leftNs: number, rightNs: number, cpus: Array, func: string): Promise { + return new Promise((resolve): void => { + threadPool.submitProto(QueryEnum.SliceSPTData, { + leftNs: leftNs, + rightNs: rightNs, + cpus: cpus, + func: func, + trafic: TraficEnum.Memory, + }, (res: any, len: number, transfer: boolean): void => { + resolve(res); + }); + }); +} + + diff --git a/ide/src/trace/database/data-trafic/cpu/CpuFreqLimitDataReceiver.ts b/ide/src/trace/database/data-trafic/cpu/CpuFreqLimitDataReceiver.ts index 1f7c5a643ca6d2d4b8f0c445f055921de4684047..acaa583d096a2f7a6cf15ad8246f8680fd1a249b 100644 --- a/ide/src/trace/database/data-trafic/cpu/CpuFreqLimitDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/cpu/CpuFreqLimitDataReceiver.ts @@ -65,7 +65,7 @@ export function cpuFreqLimitReceiver(data: any, proc: Function): void { if(i { return ` @@ -48,15 +48,13 @@ export const chartCpuStateDataSqlMem = (args: any): string => { `; }; - - export function cpuStateReceiver(data: any, proc: Function): void { if (data.params.trafic === TraficEnum.Memory) { let res: any[], list: any[]; if (!cpuStateList.has(data.params.filterId)) { list = proc(chartCpuStateDataSqlMem(data.params)); for (let i = 0; i < list.length; i++) { - if (list[i].dur === -1 || list[i].dur === null || list[i].dur === undefined){ + if (list[i].dur === -1 || list[i].dur === null || list[i].dur === undefined) { list[i].dur = data.params.recordEndNS - data.params.recordStartNS - list[i].startTs; } } @@ -64,16 +62,24 @@ export function cpuStateReceiver(data: any, proc: Function): void { } else { list = cpuStateList.get(data.params.filterId) || []; } - res = filterDataByGroup(list || [], 'startTs', 'dur', data.params.startNS, data.params.endNS, data.params.width, "value"); - arrayBufferHandler(data, res,true); + res = filterDataByGroup( + list || [], + 'startTs', + 'dur', + data.params.startNS, + data.params.endNS, + data.params.width, + 'value' + ); + arrayBufferHandler(data, res, true); } else { let sql = chartCpuStateDataSql(data.params); let res = proc(sql); - arrayBufferHandler(data, res,data.params.trafic !== TraficEnum.SharedArrayBuffer); + arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer); } } -let heights = [4, 12, 21, 30]; +let heights = [4, 8, 12, 16, 20, 24, 28, 32]; function arrayBufferHandler(data: any, res: any[], transfer: boolean): void { let startTs = new Float64Array(transfer ? res.length : data.params.sharedArrayBuffers.startTs); diff --git a/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartReceiver.ts b/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartReceiver.ts index 480cc236e2a9249c82d10c48063172b80d6f995d..bd5a9d99f25392abcc08e3997dd8728e2a045e49 100644 --- a/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartReceiver.ts +++ b/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartReceiver.ts @@ -73,11 +73,11 @@ export function hiPerfCallChartDataHandler(data: any, proc: Function): void { if (res[i].cpuId === res[i - 1].cpuId) { res[i - 1].dur = res[i].startTs - res[i - 1].startTs; } else { - res[i - 1].dur = data.params.endNS - res[i - 1].startTs; + res[i - 1].dur = data.params.recordEndNS - data.params.recordStartNS - res[i - 1].startTs; } } if (i === res.length - 1) { - res[i].dur = data.params.endNS - res[i].startTs; + res[i].dur = data.params.recordEndNS - data.params.recordStartNS - res[i].startTs; } } dataCache.sampleList = res; diff --git a/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartSender.ts b/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartSender.ts index af73b9475b24eac0d90e9cd8c54bbcfa0371da07..95e38930b6f96f91db05e21e07d1805c6c874d0c 100644 --- a/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartSender.ts +++ b/ide/src/trace/database/data-trafic/hiperf/HiperfCallChartSender.ts @@ -69,9 +69,9 @@ export function hiperfCallChartDataCacheSender(): Promise { QueryEnum.HiperfCallChart, { recordStartNS: window.recordStartNS, + recordEndNS: window.recordEndNS, trafic: TraficEnum.TransferArrayBuffer, isCache: true, - endNS: (TraceRow.range?.endNS || 0) - (TraceRow.range?.startNS || 0), }, (res: any, len: number): void => { resolve('ok'); diff --git a/ide/src/trace/database/data-trafic/process/FuncDataReceiver.ts b/ide/src/trace/database/data-trafic/process/FuncDataReceiver.ts index f91f3dc57d532951e6fee092fe587ebe20b09e7d..efdd0fe960ecbbb7157d656f57d70f60ee3a9b72 100644 --- a/ide/src/trace/database/data-trafic/process/FuncDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/process/FuncDataReceiver.ts @@ -67,7 +67,8 @@ export function funcDataReceiver(data: any, proc: Function):void { for (let i = 0; i < list.length; i++) { if (list[i].dur === -1 || list[i].dur === null || list[i].dur === undefined) { list[i].nofinish = 1; - list[i].dur = data.params.endNS - list[i].startTs; + let totalNs = data.params.recordEndNS - data.params.recordStartNS; + list[i].dur = totalNs - list[i].startTs; } else { list[i].nofinish = 0; } diff --git a/ide/src/trace/database/data-trafic/process/ThreadDataReceiver.ts b/ide/src/trace/database/data-trafic/process/ThreadDataReceiver.ts index f1fa735337ccfd2275ddfcefc112d92f483c1fe2..b11dca41d769fd76f27fdcdb4304f83320b341f9 100644 --- a/ide/src/trace/database/data-trafic/process/ThreadDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/process/ThreadDataReceiver.ts @@ -50,7 +50,7 @@ export const sqlMem = (args: any): string => { export function threadDataReceiver(data: any, proc: Function): void { if (data.params.trafic === TraficEnum.Memory) { - let key = `${data.params.pid}${data.params.tid}`; + let key = `${data.params.pid}-${data.params.tid}`; if (!threadStateList.has(key)) { threadStateList.set(key, proc(sqlMem(data.params))); } diff --git a/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts b/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts index 71c00e883a0ba482b22dffe150fd83ff0495ad34..46ef28c4697b47d3c528af2050d5c4c92b865e09 100644 --- a/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts +++ b/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts @@ -18,6 +18,8 @@ import { resetAbilityMonitor } from '../AbilityMonitorReceiver'; import { resetAbility } from '../VmTrackerDataReceiver'; import { resetDynamicEffect } from '../FrameDynamicEffectReceiver'; import { resetEnergyEvent } from '../EnergySysEventReceiver'; +// thread_state 表缓存 +export const sliceList: Map> = new Map(); //cpu 泳道 memory 缓存 export const cpuList: Map> = new Map(); //clock 泳道 memory 模式缓存 @@ -52,6 +54,7 @@ export const hiLogList: Map> = new Map(); //energy 泳道图 memory 模式缓存 export const energyList: Map> = new Map(); export function clearMemoryCache(data: any, proc: Function) { + sliceList.clear(); cpuList.clear(); clockList.clear(); cpuFreqList.clear(); diff --git a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts index 649f53f013b98b1516fa12e5a691b6062e844ac5..6f03cdb963a0137d1a33a8537c19f82e67e30210 100644 --- a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts +++ b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts @@ -74,9 +74,10 @@ import { hiSysEnergyAnomalyDataReceiver, hiSysEnergyPowerReceiver, hiSysEnergyStateReceiver } from '../EnergySysEventReceiver'; -import {clearMemoryCache} from "./AllMemoryCache"; +import { clearMemoryCache } from "./AllMemoryCache"; import { cpuFreqDataReceiver } from '../cpu/CpuFreqDataReceiver'; import { lostFrameReceiver } from './../LostFrameReceiver' +import { sliceReceiver, sliceSPTReceiver } from '../SliceReceiver'; const traficHandlers: Map = new Map([]); export const execProtoForWorker = (data: any, proc: Function): void => traficHandlers.get(data.name)?.(data, proc); @@ -147,3 +148,5 @@ traficHandlers.set(QueryEnum.FrameDynamicData, frameDynamicReceiver); traficHandlers.set(QueryEnum.FrameSpacingData, frameSpacingReceiver); traficHandlers.set(QueryEnum.EnergySystemData, energySysEventReceiver); traficHandlers.set(QueryEnum.LostFrameData, lostFrameReceiver); +traficHandlers.set(QueryEnum.SliceData, sliceReceiver); +traficHandlers.set(QueryEnum.SliceSPTData, sliceSPTReceiver); diff --git a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts index d793ad90ef353ccd27f42897b59f4a4dd7077201..4f268ff8ea7e9e40734ab190c0ea05aedf0c7ff1 100644 --- a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts +++ b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts @@ -84,6 +84,8 @@ export enum QueryEnum { SearchCpuData = 163, LostFrameData = 164, HitchTime = 165, + SliceData = 300, + SliceSPTData = 301, } export const MAX_COUNT = 2000; export enum TraficEnum { diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts index 86c6aeda592e06b075e860123c69c9ced9351ee6..1592c9c628184bedb9813639354427e9e28455d4 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts @@ -499,6 +499,18 @@ export function getProbablyTime(ns: number): string { return res; } +export function getThreadUsageProbablyTime(ns: number): string { + let currentNs = ns; + let microsecond1 = 1_000; + let res = ''; + if (currentNs > 0) { + res += (currentNs / microsecond1).toFixed(2); + } else if (res == '') { + res = ns + ''; + } + return res; +} + export function timeMsFormat2p(timeNs: number): string { let currentNs = timeNs; let oneHour = 3600_000; diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts index b3a241d3683ced37f7b40d9c5b84c927e4d86c19..976fec78d053c71bacecba2b50a04e13499016da 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerNativeNemory.ts @@ -25,6 +25,8 @@ import { setFileName, } from './ProcedureLogicWorkerCommon'; +const HAP_TYPE = ['.hap', '.har', '.hsp']; + export class ProcedureLogicWorkerNativeMemory extends LogicHandler { selectTotalSize = 0; selectTotalCount = 0; @@ -1046,9 +1048,18 @@ export class ProcedureLogicWorkerNativeMemory extends LogicHandler { node.path = match[2].replace(/^url:/, ''); } + private isHap(path: string): boolean { + for (const name of HAP_TYPE) { + if (path.endsWith(name)) { + return true; + } + } + return false; + } + setMerageName(currentNode: NativeHookCallInfo): void { currentNode.path = this.dataCache.dataDict.get(currentNode.fileId) || 'unknown'; - if (currentNode.path.endsWith('.hap')) { + if (this.isHap(currentNode.path)) { const fullName = this.dataCache.dataDict.get(currentNode.symbolId); this.extractSymbolAndPath(currentNode, fullName); } else { diff --git a/ide/src/trace/database/sql/Func.sql.ts b/ide/src/trace/database/sql/Func.sql.ts index 4ce750e12cf3e47c4792180feac7f4bd0f90db75..4218cd9d3b0b064ea85272b9791b12d506899e87 100644 --- a/ide/src/trace/database/sql/Func.sql.ts +++ b/ide/src/trace/database/sql/Func.sql.ts @@ -114,6 +114,7 @@ export const queryAllFuncNames = (): Promise> => { select id,name from callstack;` ); }; + export const queryProcessAsyncFunc = (_funName?: string): Promise> => query( 'queryProcessAsyncFunc', @@ -158,6 +159,7 @@ left join callstack C on A.id = C.callid where startTs not null and c.cookie is null and tid = $tid and A.ipid = $ipid`, { $tid: tid, $ipid: ipid } ); + export const getMaxDepthByTid = (): Promise> => query( 'getMaxDepthByTid', @@ -171,6 +173,7 @@ left join callstack C on A.id = C.callid where c.ts not null and c.cookie is null group by tid,ipid`, {} ); + export const querySearchFuncData = ( funcName: string, tIds: number, @@ -179,98 +182,87 @@ export const querySearchFuncData = ( ): Promise> => query( 'querySearchFuncData', - ` - select - c.ts - r.start_ts as startTime, - c.dur - from - callstack c - left join - thread t - on - c.callid = t.id - left join - process p - on - t.ipid = p.id - left join - trace_range r - where - c.name like '${funcName}%' - and - t.tid = ${tIds} - and - not ((startTime < ${leftNS}) or (startTime > ${rightNS})); - ` + `select + c.ts - r.start_ts as startTime, + c.dur + from + callstack c + left join + thread t + on + c.callid = t.id + left join + process p + on + t.ipid = p.id + left join + trace_range r + where + c.name like '${funcName}%' + and + t.tid = ${tIds} + and + not ((startTime < ${leftNS}) or (startTime > ${rightNS})); + ` ); -export const queryFuncRowData = ( - funcName: string, - tIds: number, - leftNS: number, - rightNS: number -): Promise> => + +export const queryFuncRowData = (funcName: string, tIds: number): Promise> => query( 'queryFuncRowData', - ` - select - c.name as funName, - c.ts - r.start_ts as startTime - from - callstack c - left join - thread t - on - c.callid = t.id - left join - process p - on - t.ipid = p.id - left join - trace_range r - where - c.name like '${funcName}%' - and - t.tid = ${tIds} - and - not ((startTime < ${leftNS}) or (startTime > ${rightNS})); - `, + `select + c.name as funName, + c.ts - r.start_ts as startTime, + t.tid as tid + from + callstack c + left join + thread t + on + c.callid = t.id + left join + process p + on + t.ipid = p.id + left join + trace_range r + where + c.name like '${funcName}%' + and + t.tid = ${tIds} + `, { $search: funcName } ); -export const fuzzyQueryFuncRowData = ( - funcName: string, - tIds: number, - leftNS: number, - rightNS: number -): Promise> => - query( - 'fuzzyQueryFuncRowData', - ` - select - c.name as funName, - c.ts - r.start_ts as startTime, - c.ts - r.start_ts + c.dur as endTime - from - callstack c - left join - thread t - on - c.callid = t.id - left join - process p - on - t.ipid = p.id - left join - trace_range r - where - c.name like '%${funcName}%' - and - t.tid = ${tIds} - and - not ((endTime < ${leftNS}) or (endTime > ${rightNS})); - `, - { $search: funcName } - ); + export const fuzzyQueryFuncRowData = ( + funcName: string, + tIds: number + ): Promise> => + query( + 'fuzzyQueryFuncRowData', + `select + c.name as funName, + c.ts - r.start_ts as startTime, + c.ts - r.start_ts + c.dur as endTime, + t.tid as tid + from + callstack c + left join + thread t + on + c.callid = t.id + left join + process p + on + t.ipid = p.id + left join + trace_range r + where + c.name like '%${funcName}%' + and + t.tid = ${tIds} + `, + { $search: funcName } + ); export const getTabSlicesAsyncFunc = ( asyncNames: Array, @@ -311,6 +303,7 @@ export const getTabSlicesAsyncFunc = ( wallDuration desc;`, { $leftNS: leftNS, $rightNS: rightNS } ); + export const querySearchFunc = (search: string): Promise> => query( 'querySearchFunc', @@ -354,12 +347,14 @@ export const querySceneSearchFunc = (search: string, processList: Array) `, { $search: search } ); + export const queryHeapFunction = (fileId: number): Promise> => query( 'queryHeapFunction', `SELECT function_index as index ,function_id as id ,name,script_name as scriptName,script_id as scriptId,line,column FROM js_heap_trace_function_info WHERE file_id = ${fileId}` ); + export const queryHeapTraceNode = (fileId: number): Promise> => query( 'queryHeapTraceNode', @@ -397,6 +392,7 @@ export const queryHeapTraceNode = (fileId: number): Promise> => ORDER BY N.id` ); + export const queryTaskPoolOtherRelationData = (ids: Array, tid: number): Promise> => { let sqlStr = `select c.ts-D.start_ts as startTs, @@ -487,7 +483,7 @@ export const queryLoopFuncNameCycle = ( ON t.ipid = p.id WHERE - c.name = '${funcName}' + c.name like '${funcName}%' AND t.tid = ${tIds} AND NOT @@ -531,7 +527,7 @@ export const querySingleFuncNameCycleStates = ( ON t.ipid = p.id WHERE - c.name = '${funcName}' + c.name like '${funcName}%' AND t.tid = ${tIds} AND NOT diff --git a/ide/src/trace/database/sql/SqlLite.sql.ts b/ide/src/trace/database/sql/SqlLite.sql.ts index 199ab5c144947ea6b3bd01abe1b033a12135f3f9..9429ab81fdcb0467893155b7360663091c8591ab 100644 --- a/ide/src/trace/database/sql/SqlLite.sql.ts +++ b/ide/src/trace/database/sql/SqlLite.sql.ts @@ -1352,4 +1352,33 @@ export const queryLogAllData = (oneDayTime: number, leftNs: number, rightNs: num ORDER BY l.ts;`, { $oneDayTime: oneDayTime } - ); \ No newline at end of file + ); + + export const queryFpsSourceList = (inputTime:number,endTime:number,name:string):Promise> => + query( + 'queryFpsSourceList', + ` + SELECT + t.tid, + c.dur, + c.depth, + c.ts, + c.name + FROM + callstack c + INNER JOIN thread t ON c.callid = t.itid + WHERE + c.name LIKE '%${name}%' + AND + c.ts BETWEEN ${ inputTime } and ${ endTime } + AND + t.name = 'render_service'; + ` + ) \ No newline at end of file diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts index b1da0b6e2f5bbb70949cfc66946add51a036ccbb..949c8a8bad907dc8514b516d915b4b3f9a3894ba 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerAppStartup.ts @@ -67,7 +67,7 @@ export function AppStartupStructOnClick(clickRowType: string, sp: SpSystemTrace, return new Promise((resolve,reject) => { if (clickRowType === TraceRow.ROW_TYPE_APP_STARTUP && AppStartupStruct.hoverStartupStruct) { AppStartupStruct.selectStartupStruct = AppStartupStruct.hoverStartupStruct; - sp.traceSheetEL?.displayStartupData(AppStartupStruct.selectStartupStruct, scrollToFuncHandler); + sp.traceSheetEL?.displayStartupData(AppStartupStruct.selectStartupStruct, scrollToFuncHandler, sp.currentRow!.dataListCache); sp.timerShaftEL?.modifyFlagList(undefined); reject(new Error()); }else{ @@ -89,7 +89,7 @@ export class AppStartupStruct extends BaseStruct { 'First Frame - Render Phase', ]; startTs: number | undefined; - startName: number | undefined; + startName: number = 0; dur: number | undefined; value: string | undefined; pid: number | undefined; @@ -98,6 +98,8 @@ export class AppStartupStruct extends BaseStruct { itid: number | undefined; endItid: number | undefined; stepName: string | undefined; + StartSlice: string | undefined; + EndSlice: string | undefined; static draw(ctx: CanvasRenderingContext2D, data: AppStartupStruct): void { if (data.frame) { diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts index 61e0ed5e60abf283d5d5d10a8a9a6dabe731ae9f..3f4166258f0865f4303a585afb4f201aa5b23de0 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerCommon.ts @@ -890,23 +890,24 @@ function handleTextCoordinate(arrList: Array, selectParams: TraceRow, ctx: any, selectParams: TraceRow): void { +export function drawAvgFrameRate(arrList: Array, ctx: any, selectParams: TraceRow): void { let rateList: Array = [...new Set(arrList)]; let startX = changeFrameRatePoint(rateList, selectParams)[0]; let endX = changeFrameRatePoint(rateList, selectParams)[1]; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts index c4625d49bf0fb2e16c3992541850c429bf40bdb2..d96ce20215d46d39aae99e41b53827b761dc37af 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFrameAnimation.ts @@ -106,12 +106,12 @@ export class FrameAnimationRender extends Render { } } } -export function FrameAnimationStructOnClick(clickRowType: string, sp: SpSystemTrace, row: TraceRow) { +export function FrameAnimationStructOnClick(clickRowType: string, sp: SpSystemTrace,scrollToFuncHandler:any, row: TraceRow) { return new Promise((resolve,reject) => { if (clickRowType === TraceRow.ROW_TYPE_FRAME_ANIMATION) { FrameAnimationStruct.selectFrameAnimationStruct = FrameAnimationStruct.hoverFrameAnimationStruct || row.getHoverStruct(); if (FrameAnimationStruct.selectFrameAnimationStruct) { - sp.traceSheetEL?.displayFrameAnimationData(FrameAnimationStruct.selectFrameAnimationStruct); + sp.traceSheetEL?.displayFrameAnimationData(FrameAnimationStruct.selectFrameAnimationStruct,scrollToFuncHandler); sp.timerShaftEL?.modifyFlagList(undefined); } reject(new Error()); @@ -132,6 +132,8 @@ export class FrameAnimationStruct extends BaseStruct { endTs: number = 0; frameInfo: string | undefined; name: string | undefined; + inputTime:number = 0; + endTime:number = 0; static setFrameAnimation( animationNode: FrameAnimationStruct, diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts index 13d9fefc368818a327fa76284a8798c2940c9ce6..76c71c82a3aa2eab300a3c16f4c71fd95e88c469 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFreqExtend.ts @@ -16,7 +16,12 @@ import { ColorUtils } from '../../component/trace/base/ColorUtils'; import { BaseStruct, dataFilterHandler, isFrameContainPoint, Render, RequestMessage } from './ProcedureWorkerCommon'; import { TraceRow } from '../../component/trace/base/TraceRow'; - +import { SpSegmentationChart } from '../../component/chart/SpSegmentationChart'; +import { ns2x, Rect } from './ProcedureWorkerCommon'; +import { Flag } from '../../component/trace/timer-shaft/Flag'; +import { BinderStruct } from './procedureWorkerBinder'; +import { ThreadStruct } from './ProcedureWorkerThread'; +import { TabPaneFreqStatesDataCut } from '../../component/trace/sheet/states/TabPaneFreqStatesDataCut'; export class FreqExtendRender extends Render { renderMainThread( freqReq: { @@ -49,12 +54,29 @@ export class FreqExtendRender extends Render { CpuFreqExtendStruct.isTabHover = false; } freqReq.context.beginPath(); - for (let re of freqExtendFilter) { + for (let re of freqExtendList) { if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { CpuFreqExtendStruct.hoverCpuFreqStruct = re; } - if (!row.isHover && !CpuFreqExtendStruct.isTabHover) CpuFreqExtendStruct.hoverCpuFreqStruct = undefined; - CpuFreqExtendStruct.draw(freqReq.context, re, freqReq.type); + CpuFreqExtendStruct.draw(freqReq.context, re, freqReq.type, row); + } + // tab页不高亮也没有悬浮泳道,取消竖线 + if(!CpuFreqExtendStruct.isTabHover && + CpuFreqExtendStruct.hoverCpuFreqStruct === undefined && + CpuFreqExtendStruct.selectCpuFreqStruct === undefined && + !BinderStruct.isTabHover && + !BinderStruct.selectCpuFreqStruct && + !BinderStruct.hoverCpuFreqStruct && + !ThreadStruct.hoverThreadStruct && + !TabPaneFreqStatesDataCut.isStateTabHover){ + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; + } + // 鼠标不在tab页内,取消所有tab页联动的参数 + if(!SpSegmentationChart.trace.isMousePointInSheet) { + CpuFreqExtendStruct.isTabHover = false; + CpuFreqExtendStruct.cpuCycle = -1; + CpuFreqExtendStruct.schedCycle = -1; + CpuFreqExtendStruct.gpuCycle = -1; } freqReq.context.closePath(); } @@ -72,12 +94,12 @@ export class CpuFreqExtendStruct extends BaseStruct { static hoverCpuFreqStruct: CpuFreqExtendStruct | undefined; static selectCpuFreqStruct: CpuFreqExtendStruct | undefined; value: number = 0; - startNS: number | undefined; + startNS: number = 0; dur: number | undefined; //自补充,数据库没有返回 cycle: number | undefined; colorIndex: number = 0; - static draw(freqContext: CanvasRenderingContext2D, data: CpuFreqExtendStruct, type: string) { + static draw(freqContext: CanvasRenderingContext2D, data: CpuFreqExtendStruct, type: string, row: TraceRow) { if (data.frame) { let width = data.frame.width || 0; let index = data.colorIndex || 0; @@ -92,10 +114,28 @@ export class CpuFreqExtendStruct extends BaseStruct { (data.cycle === CpuFreqExtendStruct.gpuCycle && CpuFreqExtendStruct.gpuCycle !== -1) || (data.cycle === CpuFreqExtendStruct.schedCycle && CpuFreqExtendStruct.schedCycle !== -1))) ) { - freqContext.fillStyle = '#ff0000'; - freqContext.strokeStyle = '#ff0000'; - freqContext.lineWidth = 3; - freqContext.globalAlpha = 0.6; + if(data === CpuFreqExtendStruct.hoverCpuFreqStruct || CpuFreqExtendStruct.isTabHover){ + let pointX: number = ns2x( + data.startNS || 0, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) + ); + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag( + Math.floor(pointX), + 0, + 0, + 0, + data.startNS, + '#666666', + '', + true, + '' + ); + } else { + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; + } let drawHeight: number = Math.floor( ((data.value || 0) * (data.frame.height || 0) * 1.0) / (type === 'CPU-FREQ' ? CpuFreqExtendStruct.cpuMaxValue : type === 'GPU-FREQ' @@ -105,8 +145,6 @@ export class CpuFreqExtendStruct extends BaseStruct { drawHeight = 1; } freqContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); - freqContext.globalAlpha = 0.8; - freqContext.strokeRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width, drawHeight); } else { freqContext.globalAlpha = 0.6; freqContext.lineWidth = 1; diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts index 38ae14b314070f763daf63640352eb73ef2a1ed2..d84934a2a6a94fc17353b6e647bf2186a8177693 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerFunc.ts @@ -126,27 +126,28 @@ export function func( }); } } -export function FuncStructOnClick(clickRowType: string, sp:any,row:TraceRow|undefined, scrollToFuncHandler: any) { +export function FuncStructOnClick(clickRowType: string, sp:any, row:TraceRow|undefined, scrollToFuncHandler: any, entry?: any) { return new Promise((resolve, reject) => { - if (clickRowType === TraceRow.ROW_TYPE_FUNC && FuncStruct.hoverFuncStruct) { - TabPaneTaskFrames.TaskArray = []; - sp.removeLinkLinesByBusinessType('task'); - FuncStruct.selectFuncStruct = FuncStruct.hoverFuncStruct; - let hoverFuncStruct = FuncStruct.hoverFuncStruct; - sp.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, 'inverted'); - FuncStruct.selectFuncStruct = hoverFuncStruct; - let flagConfig = FlagsConfig.getFlagsConfig('TaskPool'); - let showTabArray: Array = ['current-selection']; - if (flagConfig!.TaskPool === 'Enabled') { - if (FuncStruct.selectFuncStruct?.funName) { - if (FuncStruct.selectFuncStruct.funName.indexOf('H:Task ') >= 0) { - showTabArray.push('box-task-frames'); - sp.drawTaskPollLine(row); + if (clickRowType === TraceRow.ROW_TYPE_FUNC && (FuncStruct.hoverFuncStruct || entry)) { + if (FuncStruct.funcSelect) { + TabPaneTaskFrames.TaskArray = []; + sp.removeLinkLinesByBusinessType('task'); + let hoverFuncStruct = entry || FuncStruct.hoverFuncStruct; + FuncStruct.selectFuncStruct = hoverFuncStruct; + sp.timerShaftEL?.drawTriangle(FuncStruct.selectFuncStruct!.startTs || 0, 'inverted'); + let flagConfig = FlagsConfig.getFlagsConfig('TaskPool'); + let showTabArray: Array = ['current-selection']; + if (flagConfig!.TaskPool === 'Enabled') { + if (FuncStruct.selectFuncStruct?.funName) { + if (FuncStruct.selectFuncStruct.funName.indexOf('H:Task ') >= 0) { + showTabArray.push('box-task-frames'); + sp.drawTaskPollLine(row); + } } } + sp.traceSheetEL?.displayFuncData(showTabArray, FuncStruct.selectFuncStruct, scrollToFuncHandler); + sp.timerShaftEL?.modifyFlagList(undefined); } - sp.traceSheetEL?.displayFuncData(showTabArray, FuncStruct.selectFuncStruct, scrollToFuncHandler); - sp.timerShaftEL?.modifyFlagList(undefined); reject(new Error()); } else { resolve(null); @@ -158,6 +159,7 @@ export class FuncStruct extends BaseFuncStruct { static selectFuncStruct: FuncStruct | undefined; flag: string | undefined; // 570000 textMetricsWidth: number | undefined; + static funcSelect: boolean = true; static setFuncFrame(funcNode: any, padding: number, startNS: number, endNS: number, totalNS: number, frame: any) { let x1: number, x2: number; if ((funcNode.startTs || 0) > startNS && (funcNode.startTs || 0) <= endNS) { diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerJank.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerJank.ts index e9b9ec4a9b82748c8783ba0da0f0add6fd06c0d5..b3b67d5cded6b652a631243fa924cd8e30faa3e5 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerJank.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerJank.ts @@ -136,7 +136,7 @@ export function JankStructOnClick(clickRowType: string, sp: SpSystemTrace, row: `trace-row[row-id='frameTime'][row-type='janks']` ); } else { - endParentRow = sp.shadowRoot?.querySelector>(`trace-row[row-id='${data.pid}'][folder]`); + endParentRow = sp.shadowRoot?.querySelector>(`trace-row[row-type='process'][row-id='${data.pid}'][folder]`); } sp.drawJankLine(endParentRow, JankStruct.selectJankStruct!, data); }); diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts index c02dc4958d25296783f9a7efe7e36539d909725a..a021f3e82a4cfdcd5d810f4dc554b0bc13f5f95c 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerProcess.ts @@ -14,23 +14,15 @@ */ import { ColorUtils } from '../../component/trace/base/ColorUtils'; -import { - BaseStruct, - drawFlagLine, - drawLines, - drawLoading, - drawLoadingFrame, - drawSelection, - drawWakeUp, - ns2x, - Render, - RequestMessage, -} from './ProcedureWorkerCommon'; +import { BaseStruct, drawLoadingFrame, ns2x, Render } from './ProcedureWorkerCommon'; import { CpuStruct } from './cpu/ProcedureWorkerCPU'; import { TraceRow } from '../../component/trace/base/TraceRow'; export class ProcessRender extends Render { renderMainThread(req: any, row: TraceRow) { + if (row.expansion) { + return; + } let list = row.dataList; let filter = row.dataListCache; proc( diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts index aaaac459414a3eedb3deef1399c21b9517978273..e384ab68bb1508051ec4eb39f257441614af00fb 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerThread.ts @@ -26,7 +26,13 @@ import { import { TraceRow } from '../../component/trace/base/TraceRow'; import { Utils } from '../../component/trace/base/Utils'; import { ThreadStruct as BaseThreadStruct } from '../../bean/ThreadStruct'; -import {SpSystemTrace} from "../../component/SpSystemTrace"; +import { SpSystemTrace } from "../../component/SpSystemTrace"; +import { SpSegmentationChart } from '../../component/chart/SpSegmentationChart'; +import { ns2x } from './ProcedureWorkerCommon'; +import { Flag } from '../../component/trace/timer-shaft/Flag'; +import { CpuFreqExtendStruct } from './ProcedureWorkerFreqExtend'; +import { BinderStruct } from './procedureWorkerBinder'; +import { TabPaneFreqStatesDataCut } from '../../component/trace/sheet/states/TabPaneFreqStatesDataCut'; export class ThreadRender extends Render { renderMainThread( threadReq: { @@ -51,20 +57,35 @@ export class ThreadRender extends Render { }); drawLoadingFrame(threadReq.context, threadFilter, row); threadReq.context.beginPath(); + let find: boolean = false; for (let re of threadFilter) { re.translateY = threadReq.translateY; ThreadStruct.drawThread(threadReq.context, re); if (row.isHover && re.frame && isFrameContainPoint(re.frame!, row.hoverX, row.hoverY)) { ThreadStruct.hoverThreadStruct = re; + find = true } } + if (row.rowId === 'statesrow' && + (!row.isHover || !find) && + !CpuFreqExtendStruct.isTabHover && + CpuFreqExtendStruct.hoverCpuFreqStruct === undefined && + CpuFreqExtendStruct.selectCpuFreqStruct === undefined && + !BinderStruct.isTabHover && + !BinderStruct.selectCpuFreqStruct && + !BinderStruct.hoverCpuFreqStruct && + !TabPaneFreqStatesDataCut.isStateTabHover) { + ThreadStruct.hoverThreadStruct = undefined; + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; + find = false; + } threadReq.context.closePath(); } - render(threadReq: RequestMessage, threadList: Array, threadFilter: Array) {} + render(threadReq: RequestMessage, threadList: Array, threadFilter: Array) { } } -export function ThreadStructOnClick(clickRowType:string,sp:SpSystemTrace,threadClickHandler:any,cpuClickHandler:any){ +export function ThreadStructOnClick(clickRowType: string, sp: SpSystemTrace, threadClickHandler: any, cpuClickHandler: any) { return new Promise((resolve, reject) => { if (clickRowType === TraceRow.ROW_TYPE_THREAD && ThreadStruct.hoverThreadStruct) { sp.removeLinkLinesByBusinessType('thread'); @@ -73,7 +94,7 @@ export function ThreadStructOnClick(clickRowType:string,sp:SpSystemTrace,threadC sp.traceSheetEL?.displayThreadData(ThreadStruct.selectThreadStruct, threadClickHandler, cpuClickHandler); sp.timerShaftEL?.modifyFlagList(undefined); reject(new Error()); - }else{ + } else { resolve(null); } }); @@ -87,7 +108,7 @@ export class ThreadStruct extends BaseThreadStruct { static hoverThreadStruct: ThreadStruct | undefined; static selectThreadStruct: ThreadStruct | undefined; static selectThreadStructList: Array = new Array(); - static firstselectThreadStruct: ThreadStruct | undefined; + static firstselectThreadStruct: ThreadStruct | undefined; argSetID: number | undefined; translateY: number | undefined; textMetricsWidth: number | undefined; @@ -122,7 +143,7 @@ export class ThreadStruct extends BaseThreadStruct { if ( ThreadStruct.selectThreadStruct && ThreadStruct.equals(ThreadStruct.selectThreadStruct, data) && - (ThreadStruct.selectThreadStruct.state !== 'S'|| data.name === 'all-state') + (ThreadStruct.selectThreadStruct.state !== 'S' || data.name === 'all-state') ) { threadContext.strokeStyle = '#232c5d'; threadContext.lineWidth = 2; @@ -133,6 +154,26 @@ export class ThreadStruct extends BaseThreadStruct { data.frame.height ); } + if (ThreadStruct.hoverThreadStruct === data && data.name === 'all-state') { + let pointX: number = ns2x( + data.startTime || 0, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) + ); + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag( + Math.floor(pointX), + 0, + 0, + 0, + data.startTime || 0, + '#000000', + '', + true, + '' + ); + } } } } diff --git a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCpuState.ts b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCpuState.ts index 2110d20b001b18d9977ac2f80d8967d9fcbacfda..28d5035546ca416bf1037102fb82f1c2d2fa6909 100644 --- a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCpuState.ts +++ b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCpuState.ts @@ -58,7 +58,7 @@ export class CpuStateRender extends PerfRender { let path = new Path2D(); let find = false; let offset = 3; - let heights = [4, 12, 21, 30]; + let heights = [4, 8, 12, 16, 20, 24, 28, 32]; for (let re of filter) { re.height = heights[(re as any).value]; CpuStateStruct.draw(req.cpuStateContext, path, re); diff --git a/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts index 2b8e15fd29904ee8254442d6e768e292ba98490b..b138fe0ae9a4aea23b305ec2aaad456dbbe0b8a7 100644 --- a/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts +++ b/ide/src/trace/database/ui-worker/procedureWorkerBinder.ts @@ -16,7 +16,12 @@ import { ColorUtils } from '../../component/trace/base/ColorUtils'; import { BaseStruct, dataFilterHandler, isFrameContainPoint, Render, RequestMessage } from './ProcedureWorkerCommon'; import { TraceRow } from '../../component/trace/base/TraceRow'; -import { drawString, Rect } from './ProcedureWorkerCommon'; +import { drawString, Rect, ns2x } from './ProcedureWorkerCommon'; +import { SpSegmentationChart } from '../../component/chart/SpSegmentationChart'; +import { Flag } from '../../component/trace/timer-shaft/Flag'; +import { CpuFreqExtendStruct } from './ProcedureWorkerFreqExtend'; +import { ThreadStruct } from './ProcedureWorkerThread'; +import { TabPaneFreqStatesDataCut } from '../../component/trace/sheet/states/TabPaneFreqStatesDataCut'; export class BinderRender extends Render { renderMainThread( freqReq: { @@ -39,16 +44,30 @@ export class BinderRender extends Render { useCache: freqReq.useCache || !(TraceRow.range?.refresh ?? false), }); freqReq.context.beginPath(); - for (let re of binderFilter) { + for (let re of binderList) { if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { BinderStruct.hoverCpuFreqStruct = re; } - if (!row.isHover) { +if (!row.isHover) { BinderStruct.hoverCpuFreqStruct = undefined; } BinderStruct.draw(freqReq.context, re); } freqReq.context.closePath(); + if (!BinderStruct.isTabHover && + !BinderStruct.hoverCpuFreqStruct && + !BinderStruct.selectCpuFreqStruct && + !CpuFreqExtendStruct.isTabHover && + !CpuFreqExtendStruct.hoverCpuFreqStruct && + !CpuFreqExtendStruct.selectCpuFreqStruct && + !ThreadStruct.hoverThreadStruct && + !TabPaneFreqStatesDataCut.isStateTabHover) { + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined; + } + if (!SpSegmentationChart.trace.isMousePointInSheet) { + BinderStruct.hoverCycle = -1; + BinderStruct.isTabHover = false; + } } } export class BinderStruct extends BaseStruct { @@ -56,9 +75,10 @@ export class BinderStruct extends BaseStruct { static selectCpuFreqStruct: BinderStruct | undefined; static maxHeight: number = 0; static hoverCycle: number = -1; + static isTabHover: boolean = false; value: number = 0; cycle: number = 0; - startNS: number | undefined; + startNS: number = 0; dur: number | undefined; //自补充,数据库没有返回 name: string | undefined; depth: number = 0; @@ -83,14 +103,34 @@ export class BinderStruct extends BaseStruct { data === BinderStruct.selectCpuFreqStruct || data.cycle === BinderStruct.hoverCycle ) { - freqContext.globalAlpha = 1; - freqContext.lineWidth = 1; - freqContext.fillRect( - data.frame.x, - BinderStruct.maxHeight * 20 - data.depth * 20 + 20, - data.frame.width, - data.value * 20 + let pointX: number = ns2x( + data.startNS || 0, + TraceRow.range!.startNS, + TraceRow.range!.endNS, + TraceRow.range!.totalNS, + new Rect(0, 0, TraceRow.FRAME_WIDTH, 0) ); + if (BinderStruct.isTabHover || data === BinderStruct.hoverCpuFreqStruct) { + SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag( + Math.floor(pointX), + 0, + 0, + 0, + data.startNS, + '#999999', + '', + true, + '' + ); + freqContext.globalAlpha = 1; + freqContext.lineWidth = 1; + freqContext.fillRect( + data.frame.x, + BinderStruct.maxHeight * 20 - data.depth * 20 + 20, + data.frame.width, + data.value * 20 + ); + } } else { freqContext.globalAlpha = 0.6; freqContext.lineWidth = 1; diff --git a/ide/src/trace/enums/helpDocEnums.ts b/ide/src/trace/enums/helpDocEnums.ts new file mode 100644 index 0000000000000000000000000000000000000000..86f0914dab6597182403fb13665e863dc163344e --- /dev/null +++ b/ide/src/trace/enums/helpDocEnums.ts @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const events = { + RECORD_EVENT: 'record', + ONLINE_RECORD_EVENT: 'online_record', + LOAD_EVENT: 'load', + JS_MEMORY_EVENT: 'js_memory', + NATIVE_EVENT: 'native', + VIRTUAL_MEMORY_EVENT: 'virtual_memory', + MEMORY_TEMPLATE_EVENT: 'memory_template', + PERF_EVENT: 'perf', + ARKTS_EVENT: 'arkts', + FRAME_RECORD_EVENT: 'frame_record', + ANIMATION_EVENT: 'animation', + TASKPOOL_EVENT: 'taskpool', + APP_STARTUP_EVENT: 'app_startup', + SCHEDULING_RECORD_EVENT: 'scheduling_record', + FILE_SYSTEM_EVENT: 'file_system', + BIO_EVENT: 'bio', + SQL_EVENT: 'sql', + HISYS_EVENT: 'hisys', + SDK_RECORD_EVENT: 'sdk_record', + IMPORT_SO_EVENT: 'import_so', + HILOG_EVENT: 'hilog', + ABILITY_EVENT: 'ability', + TRACE_PARSING_EVENT: 'trace_parsing', + OPERATION_SKILLS_EVENT: 'operation_skills', + KEYWORDS_SHORTCUTS_EVENT: 'keywords_shortcuts', + TRACE_STREAMER_EXPLAIN_EVENT: 'trace_streamer_explain' +}; + +interface EventDefinition { + event: string; + name: string; + index: number; + }; + +export const eventDefinitions:{ [key: string]: EventDefinition } = { + quickstart_device_record: { + event: events.RECORD_EVENT, + name: 'quickstart_device_record', + index: 1 + }, + quickstart_web_record: { + event: events.ONLINE_RECORD_EVENT, + name: 'quickstart_web_record', + index: 2 + }, + quickstart_systemtrace: { + event: events.LOAD_EVENT, + name: 'quickstart_systemtrace', + index: 3 + }, + quickstart_Js_memory: { + event: events.JS_MEMORY_EVENT, + name: 'quickstart_Js_memory', + index: 4 + }, + quickstart_native_memory: { + event: events.NATIVE_EVENT, + name: 'quickstart_native_memory', + index: 5 + }, + quickstart_page_fault: { + event: events.VIRTUAL_MEMORY_EVENT, + name: 'quickstart_page_fault', + index: 6 + }, + quickstart_memory_template: { + event: events.MEMORY_TEMPLATE_EVENT, + name: 'quickstart_memory_template', + index: 7 + }, + quickstart_hiperf: { + event: events.PERF_EVENT, + name: 'quickstart_hiperf', + index: 8 + }, + quickstart_arkts: { + event: events.ARKTS_EVENT, + name: 'quickstart_arkts', + index: 9 + }, + quickstart_Frametimeline: { + event: events.FRAME_RECORD_EVENT, + name: 'quickstart_Frametimeline', + index: 10 + }, + quickstart_animation: { + event: events.ANIMATION_EVENT, + name: 'quickstart_animation', + index: 11 + }, + quickstart_taskpool: { + event: events.TASKPOOL_EVENT, + name: 'quickstart_taskpool', + index: 12 + }, + quickstart_app_startup: { + event: events.APP_STARTUP_EVENT, + name: 'quickstart_app_startup', + index: 13 + }, + quickstart_schedulinganalysis: { + event: events.SCHEDULING_RECORD_EVENT, + name: 'quickstart_schedulinganalysis', + index: 14 + }, + quickstart_filesystem: { + event: events.FILE_SYSTEM_EVENT, + name: 'quickstart_filesystem', + index: 15 + }, + quickstart_bio: { + event: events.BIO_EVENT, + name: 'quickstart_bio', + index: 16 + }, + quickstart_sql_metrics: { + event: events.SQL_EVENT, + name: 'quickstart_sql_metrics', + index: 17 + }, + quickstart_hisystemevent: { + event: events.HISYS_EVENT, + name: 'quickstart_hisystemevent', + index: 18 + }, + quickstart_sdk: { + event: events.SDK_RECORD_EVENT, + name: 'quickstart_sdk', + index: 19 + }, + quickstart_Import_so: { + event: events.IMPORT_SO_EVENT, + name: 'quickstart_Import_so', + index: 20 + }, + quickstart_hilog: { + event: events.HILOG_EVENT, + name: 'quickstart_hilog', + index: 21 + }, + quickstart_ability_monitor: { + event: events.ABILITY_EVENT, + name: 'quickstart_ability_monitor', + index: 22 + }, + quickstart_parsing_ability: { + event: events.TRACE_PARSING_EVENT, + name: 'quickstart_parsing_ability', + index: 23 + }, + quickstart_Application_operation_skills: { + event: events.OPERATION_SKILLS_EVENT, + name: 'quickstart_Application_operation_skills', + index: 24 + }, + quickstart_keywords_shortcuts: { + event: events.KEYWORDS_SHORTCUTS_EVENT, + name: 'quickstart_keywords_shortcuts', + index: 25 + }, + des_tables: { + event: events.TRACE_STREAMER_EXPLAIN_EVENT, + name: 'des_tables', + index: 26 + }, +}; \ No newline at end of file diff --git a/trace_streamer/pare_third_party.sh b/trace_streamer/pare_third_party.sh index 56e5380baa4a714acd2d5fb681c2ce70612bf635..9fcc027b7b4b177c6b73a672b1ed7754d9cd9f72 100755 --- a/trace_streamer/pare_third_party.sh +++ b/trace_streamer/pare_third_party.sh @@ -84,13 +84,6 @@ if [ ! -f "perf_include/libbpf/linux/perf_event.h" ];then $patch -p0 perf_include/libbpf/linux/perf_event.h ../prebuilts/patch_perf_event/perf_event.h.patch fi -if [ ! -f "perf_include/musl/elf.h" ];then - mkdir -p perf_include/musl - rm -rf elf.h - curl https://gitee.com/openharmony/third_party_musl/raw/master/include/elf.h > elf.h - mv elf.h perf_include/musl/elf.h -fi - if [ ! -d "perf_include/hiviewdfx/hilog" ];then rm -rf hiviewdfx_hilog perf_include/hiviewdfx/hilog mkdir -p perf_include/hiviewdfx/hilog diff --git a/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp b/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp index 3f1e90b6a7825f97c266be3cd356f90054c70c28..3e47428fbd8d2bc4e5a9c022d44346d3a3b7fe82 100644 --- a/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp +++ b/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp @@ -131,33 +131,37 @@ void NativeHookFilter::UpdateMap(std::unordered_map& sourceMap, T1 key, } std::unique_ptr NativeHookFilter::ParseFrame(uint64_t row, const ProtoReader::DataArea& frame) { + auto frameInfo = std::make_unique(); + ProtoReader::Frame_Reader reader(frame.Data(), frame.Size()); - uint64_t symbolIndex = INVALID_UINT64; - uint64_t filePathIndex = INVALID_UINT64; auto curCacheIpid = traceDataCache_->GetNativeHookData()->Ipids()[row]; if (isSingleProcData_) { curCacheIpid = SINGLE_PROC_IPID; } if (isStringCompressedMode_) { - symbolIndex = ipidToSymIdToSymIndex_.Find(curCacheIpid, reader.symbol_name_id()); - TS_CHECK_TRUE(symbolIndex != INVALID_UINT64, nullptr, "Native hook ParseFrame find symbol id failed!!!"); - filePathIndex = ipidToFilePathIdToFileIndex_.Find(curCacheIpid, reader.file_path_id()); - TS_CHECK_TRUE(filePathIndex != INVALID_UINT64, nullptr, "Native hook ParseFrame find file path id failed!!!"); + frameInfo->symbolIndex_ = ipidToSymIdToSymIndex_.Find(curCacheIpid, reader.symbol_name_id()); + TS_CHECK_TRUE(frameInfo->symbolIndex_ != INVALID_UINT64, nullptr, + "Native hook ParseFrame find symbol id failed!!!"); + frameInfo->filePathIndex_ = ipidToFilePathIdToFileIndex_.Find(curCacheIpid, reader.file_path_id()); + TS_CHECK_TRUE(frameInfo->filePathIndex_ != INVALID_UINT64, nullptr, + "Native hook ParseFrame find file path id failed!!!"); } else { - symbolIndex = traceDataCache_->dataDict_.GetStringIndex(reader.symbol_name().ToStdString()); - filePathIndex = traceDataCache_->dataDict_.GetStringIndex(reader.file_path().ToStdString()); + frameInfo->symbolIndex_ = traceDataCache_->dataDict_.GetStringIndex(reader.symbol_name().ToStdString()); + frameInfo->filePathIndex_ = traceDataCache_->dataDict_.GetStringIndex(reader.file_path().ToStdString()); } - uint64_t frameSp = INVALID_UINT64; // 0 is meaningful, but it is not displayed. Other data is still needed - auto frameIp = reader.has_ip() && reader.ip() ? reader.ip() : INVALID_UINT64; + if (reader.has_ip()) { + frameInfo->ip_ = reader.ip(); + } if (reader.has_sp()) { - frameSp = reader.sp(); + frameInfo->sp_ = reader.sp(); + } + if (reader.has_offset()) { + frameInfo->offset_ = reader.offset(); + } + if (reader.has_symbol_offset()) { + frameInfo->symbolOffset_ = reader.symbol_offset(); } - auto frameOffset = reader.has_offset() && reader.offset() ? reader.offset() : INVALID_UINT64; - auto frameSymbolOffset = - reader.has_symbol_offset() && reader.symbol_offset() ? reader.symbol_offset() : INVALID_UINT64; - auto frameInfo = std::make_unique(frameIp, frameSp, symbolIndex, filePathIndex, frameOffset, - frameSymbolOffset); return frameInfo; } @@ -615,6 +619,35 @@ std::tuple NativeHookFilter::GetNeedUpdateProcessMapsAddrRan return std::make_tuple(start, end); } +std::shared_ptr NativeHookFilter::ParseArktsOfflineSymbolization(uint64_t ipid, uint64_t arktsIp) +{ + auto arktsFrameInfo = std::make_shared(); + // Under offline symbolization, there is no need to symbolize js data + uint64_t arktsFrame = arktsIp & (~JS_IP_MASK); + auto arktsReaderFrameInfo = ipidToFrameIdToFrameBytes_.Find(ipid, arktsFrame); + if (arktsReaderFrameInfo == nullptr) { + TS_LOGE("Can not to find Frame_map.id for js(arkts)!!!"); + return nullptr; + } + ProtoReader::Frame_Reader reader(*arktsReaderFrameInfo); + // 0 is meaningful, but it is not displayed. Other data is still needed + // For js, the last 5 bytes of stack.ip and the outgoing frame member IP are reserved + if (reader.has_ip()) { + arktsFrameInfo->ip_ = reader.ip(); + } + if (reader.has_symbol_name_id()) { + arktsFrameInfo->symbolIndex_ = ipidToSymIdToSymIndex_.Find(ipid, reader.symbol_name_id()); + } + if (reader.has_file_path_id()) { + arktsFrameInfo->filePathId_ = reader.file_path_id(); + } + if (reader.has_offset()) { + arktsFrameInfo->offset_ = reader.offset(); + } + // Unchanged data is the default value + return arktsFrameInfo; +} + std::shared_ptr>> NativeHookFilter::OfflineSymbolization( const std::shared_ptr> ips) { @@ -622,36 +655,11 @@ std::shared_ptr>> NativeHookFilter::Offli auto result = std::make_shared>>(); for (auto itor = ips->begin(); (itor + 1) != ips->end(); itor++) { if (JS_IP_MASK == (*itor & ALLOC_IP_MASK)) { - auto aktsFrameInfo = std::make_shared(); - // Under offline symbolization, there is no need to symbolize js data - uint64_t aktsFrame = *itor & (~JS_IP_MASK); - auto aktsReaderFrameInfo = ipidToFrameIdToFrameBytes_.Find(ipid, aktsFrame); - if (aktsReaderFrameInfo == nullptr) { - TS_LOGE("Can not to find Frame_map.id for js(akts)!!!"); - continue; - } - ProtoReader::Frame_Reader reader(*aktsReaderFrameInfo); - // 0 is meaningful, but it is not displayed. Other data is still needed - // For js, the last 5 bytes of stack.ip and the outgoing frame member IP are reserved - auto aktsIp = reader.has_ip() && reader.ip() ? reader.ip() & IP_BIT_OPERATION : INVALID_UINT64; - if (!reader.has_symbol_name_id()) { - TS_LOGI("Can not to find symbol_name_id for js(akts)!!!"); - continue; - } - auto symbolIndex = ipidToSymIdToSymIndex_.Find(ipid, reader.symbol_name_id()); - if (!reader.has_file_path_id()) { - TS_LOGI("Can not to find has_file_path_id for js(akts)!!!"); - continue; + auto arktsFrameInfo = ParseArktsOfflineSymbolization(ipid, *itor); + if (!arktsFrameInfo) { + break; } - auto fileIndex = reader.file_path_id(); - auto offset = reader.has_offset() && reader.offset() ? reader.offset() : INVALID_UINT64; - aktsFrameInfo->filePathId_ = fileIndex; - aktsFrameInfo->ip_ = aktsIp; - aktsFrameInfo->symbolIndex_ = symbolIndex; - aktsFrameInfo->offset_ = offset; - aktsFrameInfo->symbolOffset_ = INVALID_UINT64; - aktsFrameInfo->symVaddr_ = INVALID_UINT64; - result->emplace_back(aktsFrameInfo); + result->emplace_back(arktsFrameInfo); continue; } auto frameInfo = OfflineSymbolizationByIp(ipid, *itor); @@ -877,19 +885,6 @@ void NativeHookFilter::MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStam lastAnyEventRaw = row; } -void NativeHookFilter::UpdateSymbolIdsForCallChainIdLastCallStack(size_t index) -{ - auto ip = traceDataCache_->GetNativeHookFrameData()->Ips()[index]; - // ip & 0xFFFFFFFFFF - uint64_t ipBitOperation = ip & IP_BIT_OPERATION; - std::ostringstream newSymbol; - // alloc size ( (ip & 0xFFFFFFFFFF) bytes) 0xip(Convert IP to hexadecimal) - newSymbol << "alloc size(" << base::number(ipBitOperation, base::INTEGER_RADIX_TYPE_DEC) << "bytes)" - << "0x" << base::number(ip, base::INTEGER_RADIX_TYPE_HEX); - traceDataCache_->GetNativeHookFrameData()->UpdateSymbolId( - index, traceDataCache_->dataDict_.GetStringIndex(newSymbol.str())); -} - // when symbolization failed, use filePath + vaddr as symbol name void NativeHookFilter::UpdateSymbolIdsForSymbolizationFailed() { @@ -945,15 +940,9 @@ void NativeHookFilter::GetNativeHookFrameVaddrs() // Traverse every piece of native_hook frame data for (size_t i = 0; i < size; i++) { auto symbolOffset = traceDataCache_->GetNativeHookFrameData()->SymbolOffsets()[i]; - // When the symbol offset is not 0, vaddr=offset+symbol offset - if (symbolOffset) { - if (symbolOffset == INVALID_UINT64) { - // The stack does not exist, so vaddr does not exist and needs to be skipped - // Add empty value placeholders - vaddrs_.emplace_back(""); - continue; - } - auto fileOffset = traceDataCache_->GetNativeHookFrameData()->Offsets()[i]; + auto fileOffset = traceDataCache_->GetNativeHookFrameData()->Offsets()[i]; + // When the symbol offset not is INVALID_UINT64, vaddr=offset+symbol offset + if (symbolOffset != INVALID_UINT64 && fileOffset != INVALID_UINT64) { auto vaddr = base::Uint64ToHexText(fileOffset + symbolOffset); vaddrs_.emplace_back(vaddr); continue; @@ -1010,10 +999,9 @@ void NativeHookFilter::ParseFramesInCallStackCompressedMode() } // IP may not exist // 0 is meaningful, but it is not displayed. Other data is still needed - auto frameIp = reader.has_ip() && reader.ip() ? reader.ip() : INVALID_UINT64; - auto frameOffset = reader.has_offset() && reader.offset() ? reader.offset() : INVALID_UINT64; - auto frameSymbolOffset = - reader.has_symbol_offset() && reader.symbol_offset() ? reader.symbol_offset() : INVALID_UINT64; + auto frameIp = reader.has_ip() ? reader.ip() : INVALID_UINT64; + auto frameOffset = reader.has_offset() ? reader.offset() : INVALID_UINT64; + auto frameSymbolOffset = reader.has_symbol_offset() ? reader.symbol_offset() : INVALID_UINT64; auto row = traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame( stackIdToFramesItor->first, depth++, frameIp, symbolIndex, filePathIndex, frameOffset, frameSymbolOffset); @@ -1174,8 +1162,11 @@ bool NativeHookFilter::NativeHookReloadElfSymbolTable(const std::vector(vaddrs[row], base::INTEGER_RADIX_TYPE_HEX).value(); - auto dfxSymbol = symbolsFile->GetSymbolWithVaddr(symVaddr); + auto symVaddr = base::StrToInt(vaddrs[row], base::INTEGER_RADIX_TYPE_HEX); + if (!symVaddr.has_value()) { + continue; + } + auto dfxSymbol = symbolsFile->GetSymbolWithVaddr(symVaddr.value()); if (dfxSymbol.IsValid()) { auto newSymbolIndex = traceDataCache_->GetDataIndex(dfxSymbol.GetName()); nativeHookFrame->UpdateSymbolId(row, newSymbolIndex); diff --git a/trace_streamer/src/filter/hook_filter/native_hook_filter.h b/trace_streamer/src/filter/hook_filter/native_hook_filter.h index a40c97b7bc2e432ff9f586762640244273db82d5..5f0b51809cf5510baf6a9f85f1530c5d334a6904 100644 --- a/trace_streamer/src/filter/hook_filter/native_hook_filter.h +++ b/trace_streamer/src/filter/hook_filter/native_hook_filter.h @@ -90,6 +90,11 @@ public: { return isSingleProcData_; } + void UpdataOfflineSymbolizationMode(bool isOfflineSymbolizationMode) + { + // Ut testing the offline symbolic use of native_hook,do not delete!!! + isOfflineSymbolizationMode_ = isOfflineSymbolizationMode; + } private: void ProcSymbolTable(uint32_t ipid, uint32_t filePathId, std::shared_ptr reader); @@ -118,7 +123,6 @@ private: void UpdateThreadNameWithNativeHookData() const; void GetCallIdToLastLibId(); void GetNativeHookFrameVaddrs(); - void UpdateSymbolIdsForCallChainIdLastCallStack(size_t index); void UpdateSymbolIdsForSymbolizationFailed(); void ParseFramesInOfflineSymbolizationMode(); void ParseFramesInCallStackCompressedMode(); @@ -130,6 +134,7 @@ private: std::shared_ptr reader); std::shared_ptr>> OfflineSymbolization( const std::shared_ptr> ips); + std::shared_ptr ParseArktsOfflineSymbolization(uint64_t ipid, uint64_t arktsIp); void FillOfflineSymbolizationFrames(std::map>>::iterator mapItor); void ReparseStacksWithAddrRange(uint64_t start, uint64_t end); void ReparseStacksWithDifferentMeans(); diff --git a/trace_streamer/src/parser/pbreader_parser/native_hook_parser/pbreader_native_hook_parser.h b/trace_streamer/src/parser/pbreader_parser/native_hook_parser/pbreader_native_hook_parser.h index 9c1e2e219791425447bb29bdc4c716001bc2b1b7..62dae9f5f8fb4ee2f146f38d2cb07b9f6e55a091 100644 --- a/trace_streamer/src/parser/pbreader_parser/native_hook_parser/pbreader_native_hook_parser.h +++ b/trace_streamer/src/parser/pbreader_parser/native_hook_parser/pbreader_native_hook_parser.h @@ -41,6 +41,11 @@ public: { return nativeHookFilter_->NativeHookReloadElfSymbolTable(symbolsFile); } + void UpdataOfflineSymbolizationMode(bool isOfflineSymbolizationMode) + { + // Ut testing the offline symbolic use of native_hook,do not delete!!! + nativeHookFilter_->UpdataOfflineSymbolizationMode(isOfflineSymbolizationMode); + } private: void ParseNativeHookAuxiliaryEvent(std::unique_ptr& nativeHookMetaData); diff --git a/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp b/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp index 73e92bd1ee2af2f2133b57ca41223e80bdad984f..33d4adb7742fe4e7c4c25c12674ce759f3d9ba38 100644 --- a/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp @@ -159,7 +159,7 @@ void CpuDetailParser::ResizeStandAloneCpuEventList(uint32_t cpuNum) bool CpuDetailParser::SortStandAloneCpuEventList(bool isFinished) { while (curRawTraceEventNum_ > 0) { - uint32_t minTimeCpuId = 0; + uint32_t minTimeCpuId = INVALID_UINT32; uint64_t curMinTs = INVALID_UINT64; // select a min time from one of the cpu caches for (int curCpuId = 0; curCpuId < cpuCoreMax_; curCpuId++) { @@ -174,6 +174,9 @@ bool CpuDetailParser::SortStandAloneCpuEventList(bool isFinished) minTimeCpuId = curCpuId; } } + if (INVALID_UINT32 == minTimeCpuId) { + break; + } rawTraceEventList_.emplace_back(std::move(standAloneCpuEventList_[minTimeCpuId].front())); standAloneCpuEventList_[minTimeCpuId].pop(); curRawTraceEventNum_--; diff --git a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp index cb9afa03e450d897ff828879425f40e95fa800a5..2d660abc25bdd8169d1fd77ff6687f809e33e02c 100644 --- a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp @@ -109,7 +109,7 @@ bool FtraceProcessor::HandleHeaderPageFormat(const std::string& formatInfo) } } - TS_LOGD("page header details:"); + TS_LOGI("page header details:"); PrintedFieldDetails(pageHeaderFormat_.timestamp); PrintedFieldDetails(pageHeaderFormat_.commit); PrintedFieldDetails(pageHeaderFormat_.overwrite); @@ -207,7 +207,7 @@ static std::string GetProtoTypeName(ProtoFieldType type) void FtraceProcessor::PrintedFieldDetails(const FieldFormat& info) { - TS_LOGD( + TS_LOGI( "FieldFormat { offset: %u, size:%u, sign: %u fieldType: %s, " "protoType:%s, typeName: %s, name: %s}", info.offset, info.size, info.isSigned, GetFieldTypeName(info.filedType).c_str(), diff --git a/trace_streamer/src/parser/rawtrace_parser/kernel_symbols_processor.cpp b/trace_streamer/src/parser/rawtrace_parser/kernel_symbols_processor.cpp index 0964318c313569ff80c1de8e8f2f52ca5a2e4c3d..f945f228eb72dc95d9e67e21d6f036c233aec5bb 100644 --- a/trace_streamer/src/parser/rawtrace_parser/kernel_symbols_processor.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/kernel_symbols_processor.cpp @@ -73,6 +73,7 @@ bool KernelSymbolsProcessor::HandleKallSyms(const std::string& kallsyms) traceDataCache_->GetSymbolsData()->UpdateSymbol(symbol.addr, traceDataCache_->GetDataIndex(symbol.name)); } } + TS_LOGI("kernel symbolsData size = %" PRIu64 "", traceDataCache_->GetSymbolsData()->Size()); return true; } } // namespace TraceStreamer diff --git a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp index 37b000358323ab02fd91a950a030eeeb6f180464..248b888ff8e8069d0daeeb35640d0293763cf07f 100644 --- a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp @@ -117,15 +117,21 @@ bool RawTraceParser::UpdateCpuCoreMax(uint32_t cpuId) bool RawTraceParser::ParseCpuRawData(uint32_t cpuId, const std::string& buffer, uint32_t curType) { UpdateCpuCoreMax(cpuId); - TS_CHECK_TRUE(buffer.size() > 0, true, "cur cpu(%u) raw data is null!", cpuId); - auto startPtr = reinterpret_cast(buffer.c_str()); - auto endPtr = startPtr + buffer.size(); - cpuDetail_->set_cpu(cpuId); // splice the data curType adn size of each cup that matches the timestamp uint32_t curFileOffset = curFileOffset_ + sizeof(curType) + sizeof(uint32_t); uint32_t splitOffset = 0; uint32_t splitSize = 0; bool isSplitPosition = false; + if (0 == buffer.size() && traceDataCache_->isSplitFile_) { + // For rawtrace. fileType_=0, in order to count the number of CPUs and maintain the CPU data structure (which + // will also be passed to data types with CPU size 0), it is necessary to save the data during the cutting + // process and exit the buffer directly. + rawTraceSplitCpuData_.emplace_back(SpliteDataInfo(curFileOffset, 0, curType)); + } + TS_CHECK_TRUE(buffer.size() > 0, true, "cur cpu(%u) raw data is null!", cpuId); + auto startPtr = reinterpret_cast(buffer.c_str()); + auto endPtr = startPtr + buffer.size(); + cpuDetail_->set_cpu(cpuId); for (uint8_t* page = const_cast(startPtr); page < endPtr; page += FTRACE_PAGE_SIZE) { bool haveSplitSeg = false; TS_CHECK_TRUE(ftraceProcessor_->HandlePage(*cpuDetail_.get(), *cpuDetailParser_.get(), page, haveSplitSeg), @@ -144,6 +150,11 @@ bool RawTraceParser::ParseCpuRawData(uint32_t cpuId, const std::string& buffer, // Skip parsing data for timestamp or non timestamp compliant data if (splitSize > 0) { rawTraceSplitCpuData_.emplace_back(SpliteDataInfo(splitOffset, splitSize, curType)); + } else { + // For rawtrace. fileType_=0,In order to count the number of CPUs and maintain the CPU data structure (also + // through For CPU data types with a size of 0, it is necessary to set the size to 0 during the cutting + // process to save CPU data that does not meet the cutting event stamp + rawTraceSplitCpuData_.emplace_back(SpliteDataInfo(curFileOffset, 0, curType)); } return true; } @@ -183,6 +194,8 @@ bool RawTraceParser::HmParseCpuRawData(const std::string& buffer, uint32_t curTy } if (traceDataCache_->isSplitFile_ && splitSize > 0) { rawTraceSplitCpuData_.emplace_back(SpliteDataInfo(splitOffset, splitSize, curType)); + // For rawtrace. fileType_=1,There is no need to record the total number of CPUs, so for data that does not meet + // the cutting timestamp, there is no need to record and save it return true; } TS_LOGD("mark.debug. HmParseCpuRawData end success"); @@ -195,20 +208,29 @@ bool RawTraceParser::ParseLastCommData(uint8_t type, const std::string& buffer) switch (type) { case static_cast(RawTraceContentType::CONTENT_TYPE_CMDLINES): TS_CHECK_TRUE(ftraceProcessor_->HandleCmdlines(buffer), false, "parse cmdlines failed"); - ++restCommDataCnt_; - return true; + break; case static_cast(RawTraceContentType::CONTENT_TYPE_TGIDS): TS_CHECK_TRUE(ftraceProcessor_->HandleTgids(buffer), false, "parse tgid failed"); - ++restCommDataCnt_; - return true; - default: break; - } + case static_cast(RawTraceContentType::CONTENT_TYPE_HEADER_PAGE): + TS_CHECK_TRUE(ftraceProcessor_->HandleHeaderPageFormat(buffer), false, "init header page failed"); + break; + case static_cast(RawTraceContentType::CONTENT_TYPE_PRINTK_FORMATS): + TS_CHECK_TRUE(PrintkFormatsProcessor::GetInstance().HandlePrintkSyms(buffer), false, + "init printk_formats failed"); + break; + case static_cast(RawTraceContentType::CONTENT_TYPE_KALLSYMS): + TS_CHECK_TRUE(ksymsProcessor_->HandleKallSyms(buffer), false, "init printk_formats failed"); + break; + default: #ifdef IS_WASM - return false; + return false; #else - return true; + break; #endif + } + ++restCommDataCnt_; + return true; } void RawTraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size, bool isFinish) @@ -242,13 +264,6 @@ bool RawTraceParser::ProcessRawTraceContent(std::string& bufferLine, uint8_t cur } } else if (curType == static_cast(RawTraceContentType::CONTENT_TYPE_EVENTS_FORMAT)) { TS_CHECK_TRUE(InitEventFormats(bufferLine), false, "init event format failed"); - } else if (curType == static_cast(RawTraceContentType::CONTENT_TYPE_HEADER_PAGE)) { - TS_CHECK_TRUE(ftraceProcessor_->HandleHeaderPageFormat(bufferLine), false, "init header page failed"); - } else if (curType == static_cast(RawTraceContentType::CONTENT_TYPE_PRINTK_FORMATS)) { - TS_CHECK_TRUE(PrintkFormatsProcessor::GetInstance().HandlePrintkSyms(bufferLine), false, - "init printk_formats failed"); - } else if (curType == static_cast(RawTraceContentType::CONTENT_TYPE_KALLSYMS)) { - TS_CHECK_TRUE(ksymsProcessor_->HandleKallSyms(bufferLine), false, "init printk_formats failed"); } else { TS_LOGW("Raw Trace Type(%d) Unknown or has been parsed.", curType); } diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index dc6210e58f1adec1317e95656d5db38b90d73d23..cacb61b8edf26954aa1a924636c8cf50736d767c 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -257,51 +257,62 @@ bool TraceStreamerSelector::BatchParseTraceDataSegment(std::unique_ptrParseTraceDataSegment(std::move(data), size); return true; } -bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, - size_t size, - bool isSplitFile, - int32_t isFinish) -{ - if (size == 0) { - return true; + +void TraceStreamerSelector::GetMarkPositionData(std::unique_ptr& data, size_t& size) +{ + if (!markHeard_) { + std::string markStr(reinterpret_cast(data.get()), size); + auto foundPos = markStr.find("MarkPositionJSON->"); + if (foundPos == std::string::npos) { + // trace not MarkPosition,parse trace data + hasGotMarkFinish_ = true; + return; + } + // found MarkPosition + markHeard_ = true; } - if (fileType_ == TRACE_FILETYPE_UN_KNOW) { - fileType_ = GuessFileType(data.get(), size); - if (fileType_ == TRACE_FILETYPE_H_TRACE || fileType_ == TRACE_FILETYPE_PERF) { - pbreaderParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + auto pos = std::find(data.get(), data.get() + size, '\n'); + if (pos != data.get() + size) { + hasGotMarkFinish_ = true; + // Calculate the size of mark position information (include '\n') + auto curMarkSize = pos - data.get() + 1; + // Move the data pointer to the starting position of the remaining data + // The remaining data size is equal to the data size minus the current markinfo size + size -= curMarkSize; + std::unique_ptr remainingData(new uint8_t[size]); + memcpy_s(remainingData.get(), size, data.get() + curMarkSize, size); + data.reset(remainingData.release()); + } +} +void TraceStreamerSelector::InitializeParser() +{ + if (fileType_ == TRACE_FILETYPE_H_TRACE || fileType_ == TRACE_FILETYPE_PERF) { + pbreaderParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); #ifdef ENABLE_ARKTS - pbreaderParser_->EnableFileSeparate(enableFileSeparate_); + pbreaderParser_->EnableFileSeparate(enableFileSeparate_); #endif - } else if (fileType_ == TRACE_FILETYPE_BY_TRACE || fileType_ == TRACE_FILETYPE_HI_SYSEVENT || - fileType_ == TRACE_FILETYPE_HILOG) { - ptreaderParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get(), fileType_); + } else if (fileType_ == TRACE_FILETYPE_BY_TRACE || fileType_ == TRACE_FILETYPE_HI_SYSEVENT || + fileType_ == TRACE_FILETYPE_HILOG) { + ptreaderParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get(), fileType_); #ifdef ENABLE_BYTRACE - ptreaderParser_->EnableBytrace(fileType_ == TRACE_FILETYPE_BY_TRACE); + ptreaderParser_->EnableBytrace(fileType_ == TRACE_FILETYPE_BY_TRACE); #endif - } + } #ifdef ENABLE_RAWTRACE - else if (fileType_ == TRACE_FILETYPE_RAW_TRACE) { - rawTraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); - } -#endif - if (fileType_ == TRACE_FILETYPE_UN_KNOW) { - SetAnalysisResult(TRACE_PARSER_FILE_TYPE_ERROR); - TS_LOGI( - "File type is not supported!,\nthe head content is:%s\n ---warning!!!---\n" - "File type is not supported!,\n", - data.get()); - return false; - } + else if (fileType_ == TRACE_FILETYPE_RAW_TRACE) { + rawTraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); } - traceDataCache_->SetSplitFileMinTime(minTs_); - traceDataCache_->SetSplitFileMaxTime(maxTs_); - traceDataCache_->isSplitFile_ = isSplitFile; +#endif +} + +void TraceStreamerSelector::ProcessTraceData(std::unique_ptr data, size_t size, int32_t isFinish) +{ if (fileType_ == TRACE_FILETYPE_H_TRACE) { pbreaderParser_->ParseTraceDataSegment(std::move(data), size); } else if (fileType_ == TRACE_FILETYPE_BY_TRACE || fileType_ == TRACE_FILETYPE_HI_SYSEVENT || fileType_ == TRACE_FILETYPE_HILOG) { ptreaderParser_->ParseTraceDataSegment(std::move(data), size, isFinish); - return true; + return; } #ifdef ENABLE_HIPERF else if (fileType_ == TRACE_FILETYPE_PERF) { @@ -314,6 +325,50 @@ bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr dat } #endif SetAnalysisResult(TRACE_PARSER_NORMAL); +} + +bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, + size_t size, + bool isSplitFile, + int32_t isFinish) +{ + if (size == 0) { + return true; + } +#if !IS_WASM + // if in the linux,hasGotMarkFinish_ = fasle, get markinfo + if (!hasGotMarkFinish_) { + GetMarkPositionData(data, size); + if (!hasGotMarkFinish_) { + // Believing that the markInfo data has not been sent completely,Waiting for next send + return true; + } + } +#endif + + if (fileType_ == TRACE_FILETYPE_UN_KNOW) { + fileType_ = GuessFileType(data.get(), size); + if (fileType_ == TRACE_FILETYPE_UN_KNOW) { + SetAnalysisResult(TRACE_PARSER_FILE_TYPE_ERROR); + TS_LOGI( + "File type is not supported!,\nthe head content is:%s\n ---warning!!!---\n" + "File type is not supported!,\n", + data.get()); + return false; + } + InitializeParser(); + } + traceDataCache_->SetSplitFileMinTime(minTs_); + traceDataCache_->SetSplitFileMaxTime(maxTs_); + traceDataCache_->isSplitFile_ = isSplitFile; + ProcessTraceData(std::move(data), size, isFinish); + +#if !IS_WASM + // in the linux,isFinish = 1,clear markinfo + if (isFinish) { + ClearMarkPositionInfo(); + } +#endif return true; } void TraceStreamerSelector::EnableMetaTable(bool enabled) diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/trace_streamer/src/trace_streamer/trace_streamer_selector.h index 9bd575f9ba2b0af0390f54e88e9952127c6f7482..00cbd00a6a2402cdf50a75dda2469b88cde5cdb3 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -93,6 +93,17 @@ public: { return streamFilters_.get(); } + void InitializeParser(); + void ProcessTraceData(std::unique_ptr data, size_t size, int32_t isFinish); + + // Used to obtain markinfo,skip under Linux + void ClearMarkPositionInfo() + { + hasGotMarkFinish_ = false; + markHeard_ = false; + }; + void GetMarkPositionData(std::unique_ptr& data, size_t& size); + int32_t CreatEmptyBatchDB(const std::string dbPath); int32_t BatchExportDatabase(const std::string& outputName); bool BatchParseTraceDataSegment(std::unique_ptr data, size_t size); @@ -112,6 +123,10 @@ private: std::unique_ptr rawTraceParser_; #endif bool enableFileSeparate_ = false; + + // Used to get markinfo,skip under Linux + bool hasGotMarkFinish_ = false; + bool markHeard_ = false; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp index d71b986455de4282f364e92c18bde8974c23c5aa..c5313dc2f5820c4bd49a96c50e25b0630c06f4be 100644 --- a/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp @@ -33,6 +33,9 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { bool ParseTraceFile(TraceStreamerSelector& ts_, const std::string& tracePath); +const uint32_t INDEX_SIZE_02 = 2; +const uint32_t INDEX_SIZE_03 = 3; +const uint32_t INDEX_SIZE_04 = 4; const uint64_t SEC_01 = 1632675525; const uint64_t SEC_02 = 1632675526; const uint64_t SEC_03 = 1632675527; @@ -53,16 +56,25 @@ const uint64_t ADDR_02 = 10453089; const uint64_t ADDR_03 = 10453090; const int64_t SIZE_01 = 4096; const int64_t SIZE_02 = 2048; +const uint64_t STACK_MAP_ALLOC_IP = 18446742974197923848ULL; +const uint64_t STACK_MAP_JS_IP_01 = 18446741874686296087ULL; +const uint64_t STACK_MAP_JS_IP_02 = 18446741874686296086ULL; const uint64_t IP_01 = 4154215627; const uint64_t IP_02 = 4154215630; +const uint64_t IP_03 = 5483396524; const uint64_t SP_01 = 4146449696; const uint64_t SP_02 = 4146449698; const std::string SYMBOL_NAME_01 = "__aeabi_read_tp"; const std::string SYMBOL_NAME_02 = "ThreadMmap"; +const std::string SYMBOL_NAME_03 = "napicallback_arkts"; +const std::string SYMBOL_NAME_04 = "unknown 0xf79c4cce"; +const std::string SYMBOL_NAME_05 = "alloc size(8bytes)0xffffff0000000008"; const std::string FILE_PATH_01 = "/system/lib/ld-musl-arm.so.1"; const std::string FILE_PATH_02 = "/system/bin/nativetest_c"; +const std::string FILE_PATH_03 = "/entry/src/main/ets/pages/Index.ets:47:5"; const uint64_t OFFSET_01 = 359372; const uint64_t OFFSET_02 = 17865; +const uint64_t OFFSET_03 = 89456; const uint64_t SYMBOL_OFFSET_01 = 255; const uint64_t SYMBOL_OFFSET_02 = 33; const std::string ALLOCEVENT = "AllocEvent"; @@ -109,6 +121,81 @@ public: frame->set_symbol_offset(frameStruct.symbolOffset); } + void SetOfflineFrameEvent(BatchNativeHookData& hookData) + { + // construct FrameEvent + auto frameMapData = hookData.add_events(); + FrameMap* frameMap = new FrameMap(); + frameMap->set_id(STACK_MAP_JS_IP_01 & (~JS_IP_MASK)); + frameMap->set_pid(PID); + frameMapData->set_allocated_frame_map(frameMap); + + // construct Frame + Frame* frame = new Frame(); + frame->set_ip(IP_03); + frame->set_sp(0); + frame->set_symbol_name_id(1); + frame->set_file_path_id(1); + frame->set_offset(OFFSET_03); + frame->set_symbol_offset(0); + frameMap->set_allocated_frame(frame); + + // construct SymbolMap + auto symbolMapData = hookData.add_events(); + SymbolMap* symbolMap = new SymbolMap(); + symbolMap->set_id(1); + symbolMap->set_name(SYMBOL_NAME_03); + symbolMap->set_pid(PID); + symbolMapData->set_allocated_symbol_name(symbolMap); + + // construct FilePathMap + auto filePathMapData = hookData.add_events(); + FilePathMap* filePathMap = new FilePathMap(); + filePathMap->set_id(1); + filePathMap->set_name(FILE_PATH_03); + filePathMap->set_pid(PID); + filePathMapData->set_allocated_file_path(filePathMap); + } + + void SetOfflineAllocEvent(BatchNativeHookData& hookData, + HookDataStruct dataStruct, + bool isJsMixedStack = false, + bool isJsStackAbnormal = false) + { + auto stackMapData = hookData.add_events(); + // Construct JavaScript stack data + StackMap* stackMap = new StackMap(); + stackMap->set_id(1); + + if (isJsMixedStack) { + // add stackMap.ip: alloc + stackMap->add_ip(STACK_MAP_ALLOC_IP); + // add stackMap.ip: Offline symbolization failed + stackMap->add_ip(IP_02); + // add stackMap.ip :js + stackMap->add_ip(STACK_MAP_JS_IP_01); + SetOfflineFrameEvent(hookData); + } + if (isJsStackAbnormal) { + // add stackMap.ip :jsStackAbnormal + stackMap->add_ip(STACK_MAP_JS_IP_02); + } + stackMap->set_pid(PID); + stackMapData->set_allocated_stack_map(stackMap); + + // construct AllocEvent + auto nativeHookData = hookData.add_events(); + AllocEvent* allocEvent = new AllocEvent(); + allocEvent->set_stack_id(1); + allocEvent->set_pid(PID); + allocEvent->set_tid(dataStruct.tid); + allocEvent->set_addr(dataStruct.addr); + allocEvent->set_size(dataStruct.size); + + nativeHookData->set_tv_sec(dataStruct.sec); + nativeHookData->set_tv_nsec(dataStruct.nsec); + nativeHookData->set_allocated_alloc_event(allocEvent); + } void SetAllocEvent(BatchNativeHookData& hookData, HookDataStruct dataStruct, bool isRepeated = false, @@ -681,7 +768,7 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleFree, TestSize.Le auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); - EXPECT_TRUE(2 == eventCount); + EXPECT_TRUE(INDEX_SIZE_02 == eventCount); } /** @@ -732,21 +819,21 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOnePairsMallocAndFree, Te // Verification parse Free event results expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); - NativeHookCache expectNativeHookCache(2, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_02, - 0, 0, ADDR_01, SIZE_01, 0, 0); + NativeHookCache expectNativeHookCache(INDEX_SIZE_02, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_02, 0, 0, ADDR_01, SIZE_01, 0, 0); NativeHookCache resultNativeHookCache(nativeHook, 1); EXPECT_TRUE(expectNativeHookCache == resultNativeHookCache); // Verification parse Free Event Frame results expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); - NativeHookFrameCache expectFrameCache(2, 0, IP_02, expectSymbolData, expectFilePathData, OFFSET_02, + NativeHookFrameCache expectFrameCache(INDEX_SIZE_02, 0, IP_02, expectSymbolData, expectFilePathData, OFFSET_02, SYMBOL_OFFSET_02); NativeHookFrameCache resultFrameCache(nativeHookFrame, 1); EXPECT_TRUE(expectFrameCache == resultFrameCache); auto size = nativeHookFrame.Size(); - EXPECT_EQ(2, size); + EXPECT_EQ(INDEX_SIZE_02, size); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED)); @@ -855,18 +942,18 @@ HWTEST_F(NativeHookParserTest, ParseTwoMallocAndFreeEventMatched, TestSize.Level NativeHookCache secondExpectMallocCache(INVALID_UINT32, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, ADDR_02, SIZE_02, SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); - NativeHookCache secondResultMallocCache(nativeHook, 2); + NativeHookCache secondResultMallocCache(nativeHook, INDEX_SIZE_02); EXPECT_TRUE(secondExpectMallocCache == secondResultMallocCache); // Verification parse first Free event results NativeHookCache secondExpectFreeCache(INVALID_UINT32, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_04, 0, 0, ADDR_02, SIZE_02, 0, 0); - NativeHookCache secondResultFreeCache(nativeHook, 3); + NativeHookCache secondResultFreeCache(nativeHook, INDEX_SIZE_03); EXPECT_TRUE(secondExpectFreeCache == secondResultFreeCache); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED)); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); } /** @@ -918,12 +1005,12 @@ HWTEST_F(NativeHookParserTest, ParseTwoMallocAndFreeEventPartialMatched, TestSiz expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); NativeHookCache secondExpectMallocCache(INVALID_UINT32, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, TIMESTAMP_03, 0, 0, ADDR_02, SIZE_02, SIZE_02, 0); - NativeHookCache secondResultMallocCache(nativeHook, 2); + NativeHookCache secondResultMallocCache(nativeHook, INDEX_SIZE_02); EXPECT_TRUE(secondExpectMallocCache == secondResultMallocCache); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED)); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); } /** @@ -1053,10 +1140,10 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMmap, TestSize.Le expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(TYPE_02); - NativeHookCache secondExpectNativeHookCache(2, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + NativeHookCache secondExpectNativeHookCache(INDEX_SIZE_02, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, TIMESTAMP_02, 0, 0, ADDR_02, SIZE_02, SIZE_01 + SIZE_02, 0); EXPECT_TRUE(secondExpectNativeHookCache == NativeHookCache(nativeHook, 1)); - EXPECT_EQ(2, stream_.traceDataCache_->GetConstNativeHookData().Size()); + EXPECT_EQ(INDEX_SIZE_02, stream_.traceDataCache_->GetConstNativeHookData().Size()); const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); @@ -1066,11 +1153,12 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMmap, TestSize.Le expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); - NativeHookFrameCache expectFrameCache(2, 0, IP_02, expectSymbolData, expectFilePathData, OFFSET_02, + NativeHookFrameCache expectFrameCache(INDEX_SIZE_02, 0, IP_02, expectSymbolData, expectFilePathData, OFFSET_02, SYMBOL_OFFSET_02); EXPECT_TRUE(expectFrameCache == NativeHookFrameCache(nativeHookFrame, 1)); - EXPECT_EQ(2, nativeHookFrame.Size()); - EXPECT_EQ(2, stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); + EXPECT_EQ(INDEX_SIZE_02, nativeHookFrame.Size()); + EXPECT_EQ(INDEX_SIZE_02, + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); } /** @@ -1110,7 +1198,7 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMunmap, TestSize. auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); - EXPECT_TRUE(2 == eventCount); + EXPECT_TRUE(INDEX_SIZE_02 == eventCount); } /** @@ -1154,7 +1242,7 @@ HWTEST_F(NativeHookParserTest, ParseOnePairsMmapAndMunmapEvent, TestSize.Level1) mmapSubType, TIMESTAMP_02, 0, 0, ADDR_01, SIZE_01, 0, 0); NativeHookCache secondResultNativeHookCache(nativeHook, 1); EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); - EXPECT_EQ(2, stream_.traceDataCache_->GetConstNativeHookData().Size()); + EXPECT_EQ(INDEX_SIZE_02, stream_.traceDataCache_->GetConstNativeHookData().Size()); // Verification parse NativeHook Frame results const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); @@ -1171,7 +1259,7 @@ HWTEST_F(NativeHookParserTest, ParseOnePairsMmapAndMunmapEvent, TestSize.Level1) SYMBOL_OFFSET_01); NativeHookFrameCache secondResultFrameCache(nativeHookFrame, 1); EXPECT_TRUE(secondExpectFrameCache == secondResultFrameCache); - EXPECT_EQ(2, nativeHookFrame.Size()); + EXPECT_EQ(INDEX_SIZE_02, nativeHookFrame.Size()); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); @@ -1234,7 +1322,7 @@ HWTEST_F(NativeHookParserTest, ParseNotMatchMmapAndMunmapEvent, TestSize.Level1) EXPECT_TRUE(secondExpectFrameCache == secondResultFrameCache); size = nativeHookFrame.Size(); - EXPECT_EQ(2, size); + EXPECT_EQ(INDEX_SIZE_02, size); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); @@ -1291,20 +1379,20 @@ HWTEST_F(NativeHookParserTest, ParseTwoPairsMatchedMmapAndMunmapEvent, TestSize. NativeHookCache thirdExpectNativeHookCache(INVALID_UINT32, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, ADDR_02, SIZE_02, SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); - NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + NativeHookCache thirdResultNativeHookCache(nativeHook, INDEX_SIZE_02); EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); NativeHookCache fourthExpectNativeHookCache(INVALID_UINT32, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), mmapSubType, TIMESTAMP_04, 0, 0, ADDR_02, SIZE_02, 0, 0); - NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + NativeHookCache fourthResultNativeHookCache(nativeHook, INDEX_SIZE_03); EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); - EXPECT_EQ(4, size); + EXPECT_EQ(INDEX_SIZE_04, size); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED)); } /** @@ -1356,20 +1444,20 @@ HWTEST_F(NativeHookParserTest, ParsePartialMatchedMmapAndMunmapEvent, TestSize.L mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(TYPE_02); NativeHookCache thirdExpectNativeHookCache(INVALID_UINT32, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, TIMESTAMP_03, 0, 0, ADDR_02, SIZE_02, SIZE_02, 0); - NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + NativeHookCache thirdResultNativeHookCache(nativeHook, INDEX_SIZE_02); EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); NativeHookCache fourthExpectNativeHookCache(INVALID_UINT32, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), mmapSubType, TIMESTAMP_04, 0, 0, ADDR_03, SIZE_02, SIZE_02, 0); - NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + NativeHookCache fourthResultNativeHookCache(nativeHook, INDEX_SIZE_03); EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); - EXPECT_EQ(3, size); + EXPECT_EQ(INDEX_SIZE_03, size); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); - EXPECT_TRUE(2 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); + EXPECT_TRUE(INDEX_SIZE_02 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED)); } /** @@ -1417,19 +1505,19 @@ HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithAllTypesEvents, TestSize. EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); - NativeHookCache thirdExpectNativeHookCache(2, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, - TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, ADDR_02, - SIZE_02, SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); - NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + NativeHookCache thirdExpectNativeHookCache(INDEX_SIZE_02, expect_ipid, expect_itid, ALLOCEVENT.c_str(), + INVALID_UINT64, TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, + ADDR_02, SIZE_02, SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); + NativeHookCache thirdResultNativeHookCache(nativeHook, INDEX_SIZE_02); EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); - NativeHookCache fourthExpectNativeHookCache(2, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, - TIMESTAMP_04, 0, 0, ADDR_02, SIZE_02, 0, 0); - NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + NativeHookCache fourthExpectNativeHookCache(INDEX_SIZE_02, expect_ipid, expect_itid, FREEEVENT.c_str(), + INVALID_UINT64, TIMESTAMP_04, 0, 0, ADDR_02, SIZE_02, 0, 0); + NativeHookCache fourthResultNativeHookCache(nativeHook, INDEX_SIZE_03); EXPECT_TRUE(fourthExpectNativeHookCache == fourthResultNativeHookCache); auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); - EXPECT_EQ(4, size); + EXPECT_EQ(INDEX_SIZE_04, size); auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED)); @@ -1459,5 +1547,97 @@ HWTEST_F(NativeHookParserTest, ParseCallStackCompressionData, TestSize.Level1) TS_LOGI("test24-20"); EXPECT_TRUE(ParseTraceFile(stream_, path)); } +/** + * @ts.name: ParseOfflineSymJsAbnormal + * @ts.desc: Parse Abnormal Js Stack Data in Offline Sym + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseOfflineSymJsAbnormal, TestSize.Level1) +{ + TS_LOGI("test24-21"); + BatchNativeHookData nativeHookJsAbnormalData; + SetOfflineAllocEvent(nativeHookJsAbnormalData, {TID_01, ADDR_01, SIZE_01, "", SEC_01, NSEC_01}, false, true); + // start parse + PbreaderNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.UpdataOfflineSymbolizationMode(true); + std::string hookJsAbnormalStrMsg = ""; + nativeHookJsAbnormalData.SerializeToString(&hookJsAbnormalStrMsg); + PbreaderDataSegment dataSeg; + dataSeg.seg = std::make_shared(hookJsAbnormalStrMsg); + ProtoReader::BytesView hookBytesView(reinterpret_cast(hookJsAbnormalStrMsg.data()), + hookJsAbnormalStrMsg.size()); + dataSeg.protoData = hookBytesView; + bool hasJsAbnormalSplit = false; + htraceNativeHookParser.Parse(dataSeg, hasJsAbnormalSplit); + htraceNativeHookParser.FinishParseNativeHookData(); + // Verification parse Malloc event results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache expectNativeHookEventCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, 0, 0, ADDR_01, SIZE_01, SIZE_01, 0); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache resultNativeHookEventCache(nativeHook, 0); + EXPECT_TRUE(expectNativeHookEventCache == resultNativeHookEventCache); + + // Verification parse Malloc Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto size = nativeHookFrame.Size(); + EXPECT_EQ(0, size); + auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); + EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); +} +/** + * @ts.name: ParseOfflineSymHybridStack + * @ts.desc: Parse Native Hook and Arkts Mixed Stack Data in Offline Sym + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseOfflineSymMixedStack, TestSize.Level1) +{ + TS_LOGI("test24-22"); + BatchNativeHookData nativeHookMixedStackData; + SetOfflineAllocEvent(nativeHookMixedStackData, {TID_01, ADDR_01, SIZE_01, "", SEC_01, NSEC_01}, true, false); + // start parse + PbreaderNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.UpdataOfflineSymbolizationMode(true); + std::string hookStrMsg = ""; + nativeHookMixedStackData.SerializeToString(&hookStrMsg); + PbreaderDataSegment dataSeg; + dataSeg.seg = std::make_shared(hookStrMsg); + ProtoReader::BytesView hookBytesView(reinterpret_cast(hookStrMsg.data()), hookStrMsg.size()); + dataSeg.protoData = hookBytesView; + bool hasMixedStackSplit = false; + htraceNativeHookParser.Parse(dataSeg, hasMixedStackSplit); + htraceNativeHookParser.FinishParseNativeHookData(); + // Verification parse Malloc event results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache expectNativeHookEventCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, 0, 0, ADDR_01, SIZE_01, SIZE_01, 0); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache resultNativeHookEventCache(nativeHook, 0); + EXPECT_TRUE(expectNativeHookEventCache == resultNativeHookEventCache); + // Verification parse Malloc Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_03); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_03); + NativeHookFrameCache jsExpectFrameCache(1, 0, IP_03, expectSymbolData, expectFilePathData, OFFSET_03, + INVALID_UINT64); + NativeHookFrameCache jsResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(jsExpectFrameCache == jsResultFrameCache); + auto expectSymFailedSymName = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_04); + NativeHookFrameCache symFailedExpectFrameCache(1, 1, IP_02, expectSymFailedSymName, INVALID_UINT64, INVALID_UINT64, + INVALID_UINT64); + NativeHookFrameCache symFailedResultFrameCache(nativeHookFrame, 1); + EXPECT_TRUE(symFailedExpectFrameCache == symFailedResultFrameCache); + auto expectAllocSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_05); + NativeHookFrameCache allocExpectFrameCache(1, INDEX_SIZE_02, STACK_MAP_ALLOC_IP, expectAllocSymbolData, + INVALID_UINT64, INVALID_UINT64, INVALID_UINT64); + NativeHookFrameCache allocResultFrameCache(nativeHookFrame, INDEX_SIZE_02); + EXPECT_TRUE(allocExpectFrameCache == allocResultFrameCache); + auto size = nativeHookFrame.Size(); + EXPECT_EQ(INDEX_SIZE_03, size); + auto& statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); + EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); +} } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file