1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import {BaseElement, element} from "../../../../../base-ui/BaseElement.js"; 17import {LitTable} from "../../../../../base-ui/table/lit-table.js"; 18import {SelectionParam} from "../../../../bean/BoxSelection.js"; 19import { 20 getStatesProcessThreadDataByRange 21 22} from "../../../../database/SqlLite.js"; 23import {SPT, StateProcessThread} from "../../../../bean/StateProcessThread.js"; 24import {Utils} from "../../base/Utils.js"; 25import {SpSystemTrace} from "../../../SpSystemTrace.js"; 26 27@element('tabpane-context-switch') 28export class TabPaneContextSwitch extends BaseElement { 29 private tbl: LitTable | null | undefined; 30 private range: HTMLLabelElement | null | undefined; 31 private loadDataInCache: boolean = true; 32 private selectionParam:SelectionParam | null | undefined; 33 34 set data(val: SelectionParam | any) { 35 if(val == this.selectionParam){ 36 return; 37 } 38 this.selectionParam = val; 39 // @ts-ignore 40 this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" 41 this.range!.textContent = "Selected range: " + parseFloat(((val.rightNs - val.leftNs) / 1000000.0).toFixed(5)) + " ms" 42 if (this.loadDataInCache) { 43 this.getDataBySPT(val.leftNs,val.rightNs,SpSystemTrace.SPT_DATA) 44 } else { 45 this.queryDataByDB(val) 46 } 47 } 48 49 initElements(): void { 50 this.tbl = this.shadowRoot?.querySelector<LitTable>('#tb-cs'); 51 this.range = this.shadowRoot?.querySelector('#time-range') 52 } 53 54 connectedCallback() { 55 super.connectedCallback(); 56 new ResizeObserver((entries) => { 57 if (this.parentElement?.clientHeight != 0) { 58 // @ts-ignore 59 this.tbl?.shadowRoot.querySelector(".table").style.height = (this.parentElement.clientHeight - 45) + "px" 60 this.tbl?.reMeauseHeight() 61 } 62 }).observe(this.parentElement!) 63 } 64 65 getDataBySPT(leftNs:number,rightNs:number,source:Array<SPT>){ 66 let pMap: Map<string, StateProcessThread> = new Map<string, StateProcessThread>(); 67 let ptMap: Map<string, StateProcessThread> = new Map<string, StateProcessThread>(); 68 let ptsMap: Map<string, StateProcessThread> = new Map<string, StateProcessThread>(); 69 source.map((d) => { 70 if (!(d.end_ts < leftNs || d.start_ts > rightNs)) { 71 if (pMap.has(d.processId + "")) { 72 let obj1 = pMap.get(d.processId + ""); 73 obj1!.count++; 74 obj1!.wallDuration += d.dur; 75 obj1!.avgDuration = (obj1!.wallDuration / obj1!.count).toFixed(2); 76 if (d.dur > obj1!.maxDuration) { 77 obj1!.maxDuration = d.dur; 78 } 79 if (d.dur < obj1!.minDuration) { 80 obj1!.minDuration = d.dur; 81 } 82 } else { 83 let obj1 = new StateProcessThread(); 84 obj1.id = "p" + d.processId; 85 obj1.title = (d.process == null || d.process == "" ? "Process" : d.process) + "(" + d.processId + ")"; 86 obj1.process = d.process; 87 obj1.processId = d.processId; 88 obj1.minDuration = d.dur; 89 obj1.maxDuration = d.dur; 90 obj1.count = 1; 91 obj1.avgDuration = d.dur + ""; 92 obj1.wallDuration = d.dur; 93 pMap.set(d.processId + "", obj1); 94 } 95 if (ptMap.has(d.processId + "_" + d.threadId)) { 96 let obj2 = ptMap.get(d.processId + "_" + d.threadId); 97 obj2!.count++; 98 obj2!.wallDuration += d.dur; 99 obj2!.avgDuration = (obj2!.wallDuration / obj2!.count).toFixed(2); 100 if (d.dur > obj2!.maxDuration) { 101 obj2!.maxDuration = d.dur; 102 } 103 if (d.dur < obj2!.minDuration) { 104 obj2!.minDuration = d.dur; 105 } 106 } else { 107 let obj2 = new StateProcessThread(); 108 obj2.id = "p" + d.processId + "_" + "t" + d.threadId; 109 obj2.pid = "p" + d.processId; 110 obj2.title = (d.thread == null || d.thread == "" ? "Thread" : d.thread) + "(" + d.threadId + ")" 111 obj2.processId = d.processId; 112 obj2.process = d.process; 113 obj2.thread = d.thread; 114 obj2.threadId = d.threadId; 115 obj2.minDuration = d.dur; 116 obj2.maxDuration = d.dur; 117 obj2.count = 1; 118 obj2.avgDuration = d.dur + ""; 119 obj2.wallDuration = d.dur; 120 ptMap.set(d.processId + "_" + d.threadId, obj2); 121 } 122 if (ptsMap.has(d.processId + "_" + d.threadId + "_" + d.state)) { 123 let obj3 = ptsMap.get(d.processId + "_" + d.threadId + "_" + d.state); 124 obj3!.count++; 125 obj3!.wallDuration += d.dur; 126 obj3!.avgDuration = (obj3!.wallDuration / obj3!.count).toFixed(2); 127 if (d.dur > obj3!.maxDuration) { 128 obj3!.maxDuration = d.dur; 129 } 130 if (d.dur < obj3!.minDuration) { 131 obj3!.minDuration = d.dur; 132 } 133 } else { 134 let obj3 = new StateProcessThread(); 135 obj3.id = "p" + d.processId + "_" + "t" + d.threadId + "_" + (d.state == "R+" ? "RP" : d.state) 136 obj3.pid = "p" + d.processId + "_" + "t" + d.threadId; 137 obj3.title = Utils.getEndState(d.state) 138 obj3.processId = d.processId; 139 obj3.process = d.process; 140 obj3.thread = d.thread; 141 obj3.threadId = d.threadId; 142 obj3.state = d.state; 143 obj3.minDuration = d.dur; 144 obj3.maxDuration = d.dur; 145 obj3.count = 1; 146 obj3.avgDuration = d.dur + ""; 147 obj3.wallDuration = d.dur; 148 ptsMap.set(d.processId + "_" + d.threadId + "_" + d.state, obj3); 149 } 150 } 151 }) 152 let arr: Array<StateProcessThread> = []; 153 for (let key of pMap.keys()) { 154 let s = pMap.get(key); 155 s!.children = []; 156 for (let ks of ptMap.keys()) { 157 if (ks.startsWith(key + "_")) { 158 let sp = ptMap.get(ks) 159 sp!.children = []; 160 for (let kst of ptsMap.keys()) { 161 if (kst.startsWith(ks + "_")) { 162 let spt = ptsMap.get(kst) 163 sp!.children.push(spt!); 164 } 165 } 166 s!.children.push(sp!) 167 } 168 } 169 arr.push(s!) 170 } 171 this.tbl!.recycleDataSource = arr; 172 } 173 174 queryDataByDB(val: SelectionParam | any) { 175 getStatesProcessThreadDataByRange(val.leftNs,val.rightNs).then(result => { 176 this.getDataBySPT(val.leftNs,val.rightNs,result); 177 }) 178 } 179 180 initHtml(): string { 181 return ` 182 <style> 183 :host{ 184 display: flex; 185 flex-direction: column; 186 padding: 10px 10px; 187 } 188 </style> 189 <label id="time-range" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;margin-bottom: 5px">Selected range:0.0 ms</label> 190 <lit-table id="tb-cs" style="height: auto" tree> 191 <lit-table-column width="500px" title="Process/Thread/Event" data-index="title" key="title" align="flex-start"> 192 </lit-table-column> 193 <lit-table-column width="1fr" title="Count" data-index="count" key="count" align="flex-start" > 194 </lit-table-column> 195 </lit-table> 196 `; 197 } 198}