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 {SelectionData, SelectionParam} from "../../../bean/BoxSelection.js"; 19import "../../StackBar.js" 20import {getTabThreadStates} from "../../../database/SqlLite.js"; 21import {Utils} from "../base/Utils.js"; 22import {StackBar} from "../../StackBar"; 23 24@element('tabpane-thread-states') 25export class TabPaneThreadStates extends BaseElement { 26 private tbl: LitTable | null | undefined; 27 private range: HTMLLabelElement | null | undefined; 28 private stackBar: StackBar | null | undefined; 29 private source: Array<SelectionData> = [] 30 31 set data(val: SelectionParam | any) { 32 this.range!.textContent = "Selected range: " + ((val.rightNs - val.leftNs) / 1000000.0).toFixed(7) + " ms" 33 getTabThreadStates(val.threadIds, val.leftNs, val.rightNs).then((result) => { 34 if (result != null && result.length > 0) { 35 let sumWall = 0.0; 36 let sumOcc = 0; 37 for (let e of result) { 38 e.process = e.process == null || e.process.length == 0 ? "[NULL]" : e.process 39 e.thread = e.thread == null || e.thread.length == 0 ? "[NULL]" : e.thread 40 sumWall += e.wallDuration 41 sumOcc += e.occurrences 42 e.stateJX = e.state 43 e.state = Utils.getEndState(e.stateJX); 44 e.wallDuration = parseFloat((e.wallDuration / 1000000.0).toFixed(5)); 45 e.avgDuration = parseFloat((e.avgDuration / 1000000.0).toFixed(5)); 46 } 47 let count = new SelectionData() 48 count.process = " " 49 count.state = " " 50 count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); 51 count.occurrences = sumOcc; 52 result.splice(0, 0, count) 53 this.source = result; 54 this.tbl!.dataSource = result 55 this.stackBar!.data = result; 56 } else { 57 this.source = [] 58 this.stackBar!.data = [] 59 this.tbl!.dataSource = [] 60 } 61 }) 62 } 63 64 initElements(): void { 65 this.tbl = this.shadowRoot?.querySelector<LitTable>('#tb-thread-states'); 66 this.range = this.shadowRoot?.querySelector('#time-range'); 67 this.stackBar = this.shadowRoot?.querySelector('#stack-bar'); 68 this.tbl!.addEventListener('column-click', (evt: any) => { 69 this.sortByColumn(evt.detail) 70 }); 71 } 72 73 initHtml(): string { 74 return ` 75<style> 76:host{ 77 display: flex; 78 flex-direction: column; 79 padding: 10px 10px; 80} 81</style> 82<div style="display: flex;height: 20px;align-items: center;flex-direction: row;margin-bottom: 5px"> 83 <stack-bar id="stack-bar" style="flex: 1"></stack-bar> 84 <label id="time-range" style="width: auto;text-align: end;font-size: 10pt;">Selected range:0.0 ms</label> 85</div> 86<lit-table id="tb-thread-states" style="height: auto"> 87 <lit-table-column width="25%" title="Process" data-index="process" key="process" align="flex-start" order></lit-table-column> 88 <lit-table-column width="1fr" title="PID" data-index="pid" key="pid" align="flex-start" order ></lit-table-column> 89 <lit-table-column width="25%" title="Thread" data-index="thread" key="thread" align="flex-start" order ></lit-table-column> 90 <lit-table-column width="1fr" title="TID" data-index="tid" key="tid" align="flex-start" order ></lit-table-column> 91 <lit-table-column width="1fr" title="State" data-index="state" key="state" align="flex-start" order ></lit-table-column> 92 <lit-table-column width="1fr" title="Wall duration(ms)" data-index="wallDuration" key="wallDuration" align="flex-start" order ></lit-table-column> 93 <lit-table-column width="1fr" title="Avg Wall duration(ms)" data-index="avgDuration" key="avgDuration" align="flex-start" order ></lit-table-column> 94 <lit-table-column width="1fr" title="Occurrences" data-index="occurrences" key="occurrences" align="flex-start" order ></lit-table-column> 95</lit-table> 96 `; 97 } 98 99 sortByColumn(detail: any) { 100 function compare(property: any, sort: any, type: any) { 101 return function (a: SelectionData | any, b: SelectionData | any) { 102 if (a.process == " " || b.process == " ") { 103 return 0; 104 } 105 if (type === 'number') { 106 return sort === 2 ? parseFloat(b[property]) - parseFloat(a[property]) : parseFloat(a[property]) - parseFloat(b[property]); 107 } else { 108 if (b[property] > a[property]) { 109 return sort === 2 ? 1 : -1; 110 } else if (b[property] == a[property]) { 111 return 0; 112 } else { 113 return sort === 2 ? -1 : 1; 114 } 115 } 116 } 117 } 118 119 if (detail.key === "name" || detail.key === "thread" || detail.key === "state") { 120 this.source.sort(compare(detail.key, detail.sort, 'string')) 121 } else { 122 this.source.sort(compare(detail.key, detail.sort, 'number')) 123 } 124 this.tbl!.dataSource = this.source; 125 } 126 127}