1/* 2 * Copyright (C) 2023 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'; 17import '../../../../../base-ui/checkbox/LitCheckBox'; 18import { LitTable } from '../../../../../base-ui/table/lit-table'; 19import '../../../../../base-ui/popover/LitPopoverV'; 20import { LitPopover } from '../../../../../base-ui/popover/LitPopoverV'; 21import { SelectionData, SelectionParam } from '../../../../bean/BoxSelection'; 22import { queryRunningThread, queryCoreRunningThread } from '../../../../database/sql/ProcessThread.sql'; 23import { ClassifyCoreSettingHtml } from '../TabPaneTime.html'; 24import { HanldParalLogic, MeterHeaderClick } from './ParallelUtil'; 25import { TabPaneFilter } from '../TabPaneFilter'; 26import { Utils } from '../../base/Utils'; 27 28 29const UNIT: number = 1000000.0; 30const NUM_DIGITS: number = 3; 31const CORE_NUM: number = 12; 32const LITTLE_CPU_NUM: Array<number> = [0, 1, 2, 3]; 33const MID_CPU_NUM12: Array<number> = [4, 5, 6, 7, 8, 9]; 34const BIG_CPU_NUM12: Array<number> = [10, 11]; 35 36@element('tabpane-time-parallel') 37export class TabPaneTimeParallel extends BaseElement { 38 private bottomFilterEl: TabPaneFilter | undefined | null; 39 private parallelTable: LitTable | null | undefined; 40 private coreParallelTable: LitTable | null | undefined; 41 private litPopoverEl: LitPopover | null | undefined; 42 private selectionParam: SelectionParam | undefined; 43 private initMap: Map<string, unknown> = new Map<string, unknown>(); 44 private leftStartNs: number = 0; 45 private rightEndNs: number = 0; 46 private midCores: Array<number> = []; 47 private bigCores: Array<number> = []; 48 private littleCores: Array<number> = []; 49 private initStatus: boolean = true; 50 51 set data(threadStatesParam: SelectionParam) { 52 if (this.selectionParam === threadStatesParam) { return; }; 53 this.selectionParam = threadStatesParam; 54 this.leftStartNs = this.selectionParam!.leftNs + this.selectionParam!.recordStartNs; 55 this.rightEndNs = this.selectionParam!.rightNs + this.selectionParam!.recordStartNs; 56 //每次新款选线程时清空Map对象 57 this.initMap.clear(); 58 this.initStatus = true; 59 this.initDefaultConfig(); 60 this.parallelTable!.recycleDataSource = []; 61 this.coreParallelTable!.recycleDataSource = []; 62 this.switchTableInfo(); 63 } 64 initElements(): void { 65 this.parallelTable = this.shadowRoot!.querySelector<LitTable>('#tb-parallel'); 66 this.coreParallelTable = this.shadowRoot!.querySelector<LitTable>('#tb-core-parallel'); 67 this.bottomFilterEl = this.shadowRoot?.querySelector('#filter'); 68 this.litPopoverEl = this.bottomFilterEl?.shadowRoot?.querySelector('#data-core-popover'); 69 this.litPopoverEl!.querySelector<HTMLDivElement>('#core-mining')!.onclick = (e): void => { 70 if (this.initStatus) { 71 this.initDefaultConfig(); 72 this.initStatus = false; 73 this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.littleCores, this.midCores, this.bigCores); 74 } 75 }; 76 this.litPopoverEl!.querySelector<HTMLDivElement>('.confirm-button')!.addEventListener('click', (e: unknown) => { 77 this.switchTableInfo(); 78 }); 79 this.litPopoverEl!.querySelector<HTMLDivElement>('.reset-button')!.addEventListener('click', (e: unknown) => { 80 this.initStatus = true; 81 this.reset(); 82 }); 83 } 84 switchTableInfo(): void { 85 // @ts-ignore 86 this.litPopoverEl!.visible = false; 87 //当大中小核未分组时,默认查询所有核 88 if (!this.midCores.length && !this.bigCores.length && !this.littleCores.length) { 89 this.assignAllCore(); 90 } else { 91 this.assignGroupCore(); 92 } 93 } 94 95 reset(): void { 96 // @ts-ignore 97 this.litPopoverEl!.visible = false; 98 if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { 99 this.coreParallelTable!.style.display = 'grid'; 100 this.parallelTable!.style.display = 'none'; 101 this.coreParallelTable!.loading = true; 102 this.coreParallelTable!.recycleDataSource = [...this.initMap.values()]; 103 this.coreParallelTable!.loading = false; 104 MeterHeaderClick(this.coreParallelTable, [...this.initMap.values()]); 105 } else { 106 this.parallelTable!.style.display = 'grid'; 107 this.coreParallelTable!.style.display = 'none'; 108 this.parallelTable!.loading = true; 109 this.parallelTable!.recycleDataSource = [...this.initMap.values()]; 110 this.parallelTable!.loading = false; 111 } 112 } 113 114 assignAllCore(): void { 115 this.parallelTable!.style.display = 'grid'; 116 this.coreParallelTable!.style.display = 'none'; 117 this.parallelTable!.loading = true; 118 this.getAllCoreData().then((res) => { 119 // @ts-ignore 120 if (this.initMap.size === 0) { this.initMap = res; } 121 // @ts-ignore 122 this.parallelTable!.recycleDataSource = [...res.values()]; 123 this.parallelTable!.loading = false; 124 }); 125 } 126 127 assignGroupCore(): void { 128 this.coreParallelTable!.style.display = 'grid'; 129 this.parallelTable!.style.display = 'none'; 130 this.coreParallelTable!.loading = true; 131 this.getCoreGroupData().then((res) => { 132 // @ts-ignore 133 if (this.initMap.size === 0) { this.initMap = res; } 134 // @ts-ignore 135 this.coreParallelTable!.recycleDataSource = [...res.values()]; 136 this.coreParallelTable!.loading = false; 137 // @ts-ignore 138 MeterHeaderClick(this.coreParallelTable, [...res.values()]); 139 }); 140 } 141 142 initDefaultConfig(): void { 143 if (this.initStatus) { 144 if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { 145 this.littleCores = [...LITTLE_CPU_NUM]; 146 this.midCores = [...MID_CPU_NUM12]; 147 this.bigCores = [...BIG_CPU_NUM12]; 148 } else { 149 this.littleCores = []; 150 this.midCores = []; 151 this.bigCores = []; 152 } 153 } 154 } 155 156 //获取每次被框选线程对应的state数据 157 async getAllCoreData(): Promise<unknown> { 158 let dataSourceMap: Map<string, unknown> = new Map<string, unknown>(); 159 let processIds: Array<number> = [...new Set(this.selectionParam!.processIds)]; 160 let res: unknown = await queryRunningThread(processIds, this.selectionParam!.threadIds, this.leftStartNs, this.rightEndNs); 161 this.handleAllParallelData(res, dataSourceMap); 162 return dataSourceMap; 163 } 164 //获取核分类数据 165 async getCoreGroupData(): Promise<unknown> { 166 let dataSourceMap: Map<string, unknown> = new Map<string, unknown>(); 167 let processIds: Array<number> = [...new Set(this.selectionParam!.processIds)]; 168 let cpuObj: Object = { 169 'B': this.bigCores, 170 'M': this.midCores, 171 'L': this.littleCores 172 }; 173 for (const [key, val] of Object.entries(cpuObj)) { 174 if (val.length) { 175 let res: unknown = await queryCoreRunningThread(processIds, this.selectionParam!.threadIds, val, this.leftStartNs, this.rightEndNs); 176 this.hanldeGroupParalleData(res, key, dataSourceMap); 177 }; 178 } 179 //转换最外层数据单位即保留三位小数 180 for (const [i, item] of dataSourceMap) { 181 // @ts-ignore 182 item.dur = (item.dur / UNIT).toFixed(NUM_DIGITS); 183 // @ts-ignore 184 item.load = item.load.toFixed(NUM_DIGITS); 185 } 186 return dataSourceMap; 187 } 188 //处理未按核分组的数据 189 handleAllParallelData(param: unknown, dataSourceMap: Map<string, unknown>): void { 190 // @ts-ignore 191 for (let i = 0; i < param.length; i++) { 192 // @ts-ignore 193 let stateItem = param[i]; 194 if (stateItem.ts < this.leftStartNs) { 195 stateItem.ts = this.leftStartNs; 196 } 197 if (stateItem.endTs > this.rightEndNs) { 198 stateItem.endTs = this.rightEndNs; 199 } 200 let dur = stateItem.endTs - stateItem.ts; 201 if (dataSourceMap.has(`${stateItem.pid}`)) { 202 let obj = dataSourceMap.get(`${stateItem.pid}`); 203 // @ts-ignore 204 let setArr = new Set(obj.tidArr); 205 if (!(setArr.has(stateItem.tid))) { 206 setArr.add(stateItem.tid); 207 // @ts-ignore 208 obj.tidArr.push(stateItem.tid); 209 } 210 // @ts-ignore 211 obj.dur += dur; 212 // @ts-ignore 213 obj!.stateItem.push(stateItem); 214 } else { 215 dataSourceMap.set(`${stateItem.pid}`, { 216 pid: stateItem.pid, 217 tid: stateItem.tid, 218 title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`, 219 tidArr: [stateItem.tid], 220 dur: dur, 221 parallelNum: null, 222 allParallel: null, 223 stateItem: [stateItem], 224 tCount: null, 225 load: null, 226 pDur: null, 227 children: [] 228 }); 229 }; 230 }; 231 this.showTreeChart(dataSourceMap); 232 } 233 //处理核分组数据 234 hanldeGroupParalleData(val: unknown, key: string, dataSourceMap: Map<string, unknown>): void { 235 let coreMap: Map<string, unknown> = new Map<string, unknown>(); 236 // @ts-ignore 237 for (let i = 0; i < val.length; i++) { 238 // @ts-ignore 239 let stateItem = val[i]; 240 if (stateItem.ts < this.leftStartNs) { 241 stateItem.ts = this.leftStartNs; 242 } 243 if (stateItem.endTs > this.rightEndNs) { 244 stateItem.endTs = this.rightEndNs; 245 } 246 let dur = stateItem.endTs - stateItem.ts; 247 if (!dataSourceMap.has(`${stateItem.pid}`)) { 248 dataSourceMap.set(`${stateItem.pid}`, { 249 pid: stateItem.pid, 250 tid: stateItem.tid, 251 title: stateItem.pName ? `${stateItem.pName} ${stateItem.pid}` : `[NULL] ${stateItem.pid}`, 252 dur: null, 253 parallelNum: null, 254 parallelDur: null, 255 allParallel: null, 256 tCount: null, 257 load: null, 258 pDur: null, 259 children: [] 260 }); 261 }; 262 if (coreMap.has(`${stateItem.pid} ${key}`)) { 263 let obj = coreMap.get(`${stateItem.pid} ${key}`); 264 // @ts-ignore 265 let setArr = new Set(obj.tidArr); 266 if (!(setArr.has(stateItem.tid))) { 267 setArr.add(stateItem.tid); 268 // @ts-ignore 269 obj.tidArr.push(stateItem.tid); 270 } 271 // @ts-ignore 272 obj.dur += dur; 273 // @ts-ignore 274 obj!.stateItem.push(stateItem); 275 } else { 276 coreMap.set(`${stateItem.pid} ${key}`, { 277 pid: stateItem.pid, 278 tid: stateItem.tid, 279 title: `${key}`, 280 tidArr: [stateItem.tid], 281 dur: dur, 282 parallelNum: null, 283 parallelDur: null, 284 allParallel: null, 285 stateItem: [stateItem], 286 tCount: null, 287 load: null, 288 pDur: null, 289 children: [] 290 }); 291 }; 292 }; 293 this.showCoreTreeChart(coreMap, dataSourceMap); 294 } 295 296 showTreeChart(param: Map<string, unknown>): void { 297 for (let [key, value] of param) { 298 let pMap: Map<string, unknown> = new Map<string, unknown>(); 299 HanldParalLogic(this.hanldMapLogic, value, pMap); 300 // @ts-ignore 301 value.tCount = value.tidArr.length; 302 // @ts-ignore 303 value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount())).toFixed(NUM_DIGITS); 304 // @ts-ignore 305 value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS); 306 if (pMap.size === 0) { 307 // @ts-ignore 308 value.allParallel = 0.000.toFixed(NUM_DIGITS); 309 } else { 310 for (const [i, item] of pMap) { 311 // @ts-ignore 312 value.allParallel += item.allParallel; 313 // @ts-ignore 314 item.allParallel = item.allParallel.toFixed(NUM_DIGITS); 315 } 316 // @ts-ignore 317 value.allParallel = value.allParallel.toFixed(NUM_DIGITS); 318 // @ts-ignore 319 value.children = [...pMap.values()]; 320 } 321 } 322 } 323 324 showCoreTreeChart(param: unknown, dataSourceMap: Map<string, unknown>): void { 325 // @ts-ignore 326 for (let [key, value] of param) { 327 let pMap: Map<string, unknown> = new Map<string, unknown>(); 328 // @ts-ignore 329 pMap = HanldParalLogic(this.hanldMapLogic, value, pMap); 330 value.load = (value.dur / ((100 * UNIT) * Utils.getInstance().getWinCpuCount())); 331 if (pMap.size === 0) { 332 value.allParallel = 0.000; 333 value.parallelNum = '-'; 334 value.parallelDur = '-'; 335 } else { 336 for (const [i, item] of pMap) { 337 // @ts-ignore 338 value.allParallel += item.allParallel; 339 // @ts-ignore 340 item.allParallel = item.allParallel; 341 // @ts-ignore 342 item.allParallel = item.allParallel.toFixed(NUM_DIGITS); 343 } 344 value.children = [...pMap.values()]; 345 } 346 if (dataSourceMap.has(`${value.pid}`)) { 347 let obj = dataSourceMap.get(`${value.pid}`); 348 value.tCount = value.tidArr.length; 349 // @ts-ignore 350 obj.dur += value.dur; 351 // @ts-ignore 352 obj.load += value.load; 353 value.allParallel = value.allParallel.toFixed(NUM_DIGITS); 354 value.dur = (value.dur / UNIT).toFixed(NUM_DIGITS); 355 value.load = value.load.toFixed(NUM_DIGITS); 356 // @ts-ignore 357 obj.children.push(value); 358 } 359 } 360 } 361 //每次stateItem计算的的结果,处理对应map的值 362 hanldMapLogic(dumpObj: unknown, value?: unknown, pMap?: unknown): unknown { 363 // @ts-ignore 364 let pDur = dumpObj.endTs - dumpObj.ts; 365 // @ts-ignore 366 let pSlice = ((dumpObj.len * pDur) / value.dur) * 100; 367 // @ts-ignore 368 if (pMap!.has(dumpObj.len.toString())) { 369 // @ts-ignore 370 let pObj = pMap!.get(dumpObj.len.toString()); 371 pObj.allParallel += pSlice; 372 pObj.pDur += pDur; 373 pObj.parallelDur = `${((pObj.pDur) / UNIT).toFixed(NUM_DIGITS)}`; 374 } else { 375 // @ts-ignore 376 if (dumpObj.len !== 1) { 377 // @ts-ignore 378 pMap!.set(dumpObj.len.toString(), { 379 pid: null, 380 tid: null, 381 title: '', 382 // @ts-ignore 383 tidArr: value.tidArr, 384 dur: null, 385 allParallel: pSlice, 386 // @ts-ignore 387 parallelNum: dumpObj.len, 388 parallelDur: ((pDur) / UNIT).toFixed(NUM_DIGITS), 389 pDur: pDur, 390 // @ts-ignore 391 stateItem: value.stateItem, 392 tCount: null, 393 load: '-', 394 children: [] 395 }); 396 } 397 } 398 return pMap; 399 } 400 401 //回调函数,首次插入DOM时执行的初始化回调 402 connectedCallback(): void { 403 super.connectedCallback(); 404 new ResizeObserver(() => { 405 if (this.parentElement?.clientHeight !== 0) { 406 // @ts-ignore 407 this.parallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight - 31}px`; 408 this.parallelTable?.reMeauseHeight(); 409 // @ts-ignore 410 this.coreParallelTable!.shadowRoot!.querySelector('.table')!.style.height = `${this.parentElement!.clientHeight - 31}px`; 411 this.coreParallelTable?.reMeauseHeight(); 412 if (this.parentElement!.clientHeight >= 0 && this.parentElement!.clientHeight <= 31) { 413 this.bottomFilterEl!.style.display = 'none'; 414 } else { 415 this.bottomFilterEl!.style.display = 'flex'; 416 } 417 } 418 }).observe(this.parentElement!); 419 } 420 initHtml(): string { 421 return ClassifyCoreSettingHtml; 422 } 423} 424