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'; 17import { LitTable, RedrawTreeForm } from '../../../../../base-ui/table/lit-table'; 18import { SelectionParam } from '../../../../bean/BoxSelection'; 19import { resizeObserver } from '../SheetUtils'; 20import { Utils } from '../../base/Utils'; 21import { Priority } from '../../../../bean/StateProcessThread'; 22import { queryArgsById, queryThreadStateArgsById } from '../../../../database/sql/ProcessThread.sql'; 23import { FlagsConfig } from '../../../SpFlags'; 24import { sliceSPTSender } from '../../../../database/data-trafic/SliceSender'; 25 26@element('tabpane-sched-priority') 27export class TabPaneSchedPriority extends BaseElement { 28 private priorityTbl: LitTable | null | undefined; 29 private range: HTMLLabelElement | null | undefined; 30 private selectionParam: SelectionParam | null | undefined; 31 private strValueMap: Map<number, string> = new Map<number, string>(); 32 33 set data(sptValue: SelectionParam) { 34 if (sptValue === this.selectionParam) { 35 return; 36 } 37 this.selectionParam = sptValue; 38 if (this.priorityTbl) { 39 // @ts-ignore 40 this.priorityTbl.shadowRoot.querySelector('.table').style.height = `${this.parentElement!.clientHeight - 45}px`; 41 } 42 this.range!.textContent = `Selected range: ${parseFloat( 43 ((sptValue.rightNs - sptValue.leftNs) / 1000000.0).toFixed(5) 44 )} ms`; 45 this.queryDataByDB(sptValue); 46 } 47 48 public initElements(): void { 49 this.priorityTbl = this.shadowRoot?.querySelector<LitTable>('#priority-tbl'); 50 this.range = this.shadowRoot?.querySelector('#priority-time-range'); 51 } 52 53 public connectedCallback(): void { 54 super.connectedCallback(); 55 resizeObserver(this.parentElement!, this.priorityTbl!); 56 } 57 58 private async queryDataByDB(sptParam: SelectionParam | unknown): Promise<void> { 59 this.priorityTbl!.loading = true; 60 const resultData: Array<Priority> = []; 61 await this.fetchAndProcessData(); 62 63 const filterList = ['0', '0x0']; //next_info第2字段不为0 || next_info第3字段不为0 64 // 通过priority与next_info结合判断优先级等级 65 function setPriority(item: Priority, strArg: string[]): void { 66 let flagsItem = window.localStorage.getItem(FlagsConfig.FLAGS_CONFIG_KEY); 67 let flagsItemJson = JSON.parse(flagsItem!); 68 let hmKernel = flagsItemJson.HMKernel; 69 if (hmKernel === 'Enabled') { 70 if (item.priority >= 0 && item.priority <= 40) { 71 item.priorityType = 'CFS'; 72 } else { 73 item.priorityType = 'RT'; 74 } 75 } else { 76 if (item.priority >= 0 && item.priority <= 88) { 77 item.priorityType = 'RT'; 78 } else if (item.priority >= 89 && item.priority <= 99) { 79 item.priorityType = 'VIP2.0'; 80 } else if ( 81 item.priority >= 100 && 82 strArg.length > 1 && 83 (!filterList.includes(strArg[1]) || !filterList.includes(strArg[2])) 84 ) { 85 item.priorityType = 'STATIC_VIP'; 86 } else { 87 item.priorityType = 'CFS'; 88 } 89 } 90 } 91 // thread_state表中runnable数据的Map 92 const runnableMap = new Map<string, Priority>(); 93 // @ts-ignore 94 sliceSPTSender(sptParam.leftNs, sptParam.rightNs, [], 'spt-getCpuPriorityByTime', sptParam.traceId).then(res => { 95 for (const item of res) { 96 //@ts-ignore 97 if (['R', 'R+'].includes(item.state)) { 98 //@ts-ignore 99 runnableMap.set(`${item.id}_${item.startTime + item.dur}`, item); 100 } 101 // @ts-ignore 102 if (item.cpu === null || !sptParam.cpus.includes(item.cpu)) { 103 continue; 104 } 105 this.fetchData(item, setPriority, resultData, runnableMap); 106 } 107 this.getDataByPriority(resultData); 108 }); 109 } 110 111 private fetchData( 112 item: any, 113 setPriority: (item: Priority, strArg: string[]) => void, 114 resultData: Array<Priority>, 115 runnableMap: Map<string, Priority> 116 ): void { 117 let strArg: string[] = []; 118 const args = this.strValueMap.get(item.argSetId); 119 if (args) { 120 strArg = args!.split(','); 121 } 122 const slice = Utils.getInstance().getSchedSliceMap(Utils.currentSelectTrace).get(`${item.id}-${item.startTime}`); 123 if (slice) { 124 const runningPriority = new Priority(); 125 runningPriority.priority = slice.priority; 126 runningPriority.state = 'Running'; 127 runningPriority.dur = item.dur; 128 setPriority(runningPriority, strArg); 129 resultData.push(runningPriority); 130 131 const runnableItem = runnableMap.get(`${item.id}_${item.startTime}`); 132 if (runnableItem) { 133 const runnablePriority = new Priority(); 134 runnablePriority.priority = slice.priority; 135 runnablePriority.state = 'Runnable'; 136 runnablePriority.dur = runnableItem.dur; 137 setPriority(runnablePriority, strArg); 138 resultData.push(runnablePriority); 139 } 140 } 141 } 142 143 private async fetchAndProcessData(): Promise<void> { 144 if (this.strValueMap.size === 0) { 145 let res = await queryArgsById('next_info', this.selectionParam?.traceId || undefined); 146 await queryThreadStateArgsById(res[0].id, this.selectionParam?.traceId || undefined). 147 then((value): void => { 148 for (const item of value) { 149 this.strValueMap.set(item.argset, item.strValue); 150 } 151 }); 152 } 153 } 154 155 private getDataByPriority(source: Array<Priority>): void { 156 const priorityMap: Map<string, Priority> = new Map<string, Priority>(); 157 const stateMap: Map<string, Priority> = new Map<string, Priority>(); 158 this.prepareMaps(source, priorityMap, stateMap); 159 160 const priorityArr: Array<Priority> = []; 161 for (const key of priorityMap.keys()) { 162 const ptsValues = priorityMap.get(key); 163 ptsValues!.children = []; 164 for (const itemKey of stateMap.keys()) { 165 if (itemKey.startsWith(`${key}_`)) { 166 const sp = stateMap.get(itemKey); 167 ptsValues!.children.push(sp!); 168 } 169 } 170 priorityArr.push(ptsValues!); 171 } 172 this.priorityTbl!.loading = false; 173 this.priorityTbl!.recycleDataSource = priorityArr; 174 this.theadClick(priorityArr); 175 } 176 177 private prepareMaps( 178 source: Array<Priority>, 179 priorityMap: Map<string, Priority>, 180 stateMap: Map<string, Priority> 181 ): void { 182 source.map((priorityItem): void => { 183 if (priorityMap.has(`${priorityItem.priorityType}`)) { 184 const priorityMapObj = priorityMap.get(`${priorityItem.priorityType}`); 185 priorityMapObj!.count++; 186 priorityMapObj!.wallDuration += priorityItem.dur; 187 priorityMapObj!.avgDuration = (priorityMapObj!.wallDuration / priorityMapObj!.count).toFixed(2); 188 if (priorityItem.dur > priorityMapObj!.maxDuration) { 189 priorityMapObj!.maxDuration = priorityItem.dur; 190 } 191 if (priorityItem.dur < priorityMapObj!.minDuration) { 192 priorityMapObj!.minDuration = priorityItem.dur; 193 } 194 } else { 195 const stateMapObj = new Priority(); 196 stateMapObj.title = priorityItem.priorityType; 197 stateMapObj.minDuration = priorityItem.dur; 198 stateMapObj.maxDuration = priorityItem.dur; 199 stateMapObj.count = 1; 200 stateMapObj.avgDuration = `${priorityItem.dur}`; 201 stateMapObj.wallDuration = priorityItem.dur; 202 priorityMap.set(`${priorityItem.priorityType}`, stateMapObj); 203 } 204 if (stateMap.has(`${priorityItem.priorityType}_${priorityItem.state}`)) { 205 const ptsPtMapObj = stateMap.get(`${priorityItem.priorityType}_${priorityItem.state}`); 206 ptsPtMapObj!.count++; 207 ptsPtMapObj!.wallDuration += priorityItem.dur; 208 ptsPtMapObj!.avgDuration = (ptsPtMapObj!.wallDuration / ptsPtMapObj!.count).toFixed(2); 209 if (priorityItem.dur > ptsPtMapObj!.maxDuration) { 210 ptsPtMapObj!.maxDuration = priorityItem.dur; 211 } 212 if (priorityItem.dur < ptsPtMapObj!.minDuration) { 213 ptsPtMapObj!.minDuration = priorityItem.dur; 214 } 215 } else { 216 const ptsPtMapObj = new Priority(); 217 ptsPtMapObj.title = priorityItem.state; 218 ptsPtMapObj.minDuration = priorityItem.dur; 219 ptsPtMapObj.maxDuration = priorityItem.dur; 220 ptsPtMapObj.count = 1; 221 ptsPtMapObj.avgDuration = `${priorityItem.dur}`; 222 ptsPtMapObj.wallDuration = priorityItem.dur; 223 stateMap.set(`${priorityItem.priorityType}_${priorityItem.state}`, ptsPtMapObj); 224 } 225 }); 226 } 227 228 private theadClick(data: Array<Priority>): void { 229 let labels = this.priorityTbl?.shadowRoot?.querySelector('.th > .td')!.querySelectorAll('label'); 230 if (labels) { 231 for (let i = 0; i < labels.length; i++) { 232 let label = labels[i].innerHTML; 233 labels[i].addEventListener('click', (): void => { 234 if (label.includes('Priority') && i === 0) { 235 this.priorityTbl!.setStatus(data, false); 236 this.priorityTbl!.recycleDs = this.priorityTbl!.meauseTreeRowElement(data, RedrawTreeForm.Retract); 237 } else if (label.includes('State') && i === 1) { 238 this.priorityTbl!.setStatus(data, true); 239 this.priorityTbl!.recycleDs = this.priorityTbl!.meauseTreeRowElement(data, RedrawTreeForm.Expand); 240 } 241 }); 242 } 243 } 244 } 245 246 public initHtml(): string { 247 return ` 248 <style> 249 :host{ 250 display: flex; 251 flex-direction: column; 252 padding: 10px 10px; 253 } 254 </style> 255 <label id="priority-time-range" style="width: 100%;height: 20px;text-align: end;font-size: 10pt;margin-bottom: 5px">Selected range:0.0 ms</label> 256 <lit-table id="priority-tbl" style="height: auto" tree> 257 <lit-table-column width="27%" data-index="title" key="title" align="flex-start" title="Priority/State" retract> 258 </lit-table-column> 259 <lit-table-column width="1fr" data-index="count" key="count" align="flex-start" title="Count"> 260 </lit-table-column> 261 <lit-table-column width="1fr" data-index="wallDuration" key="wallDuration" align="flex-start" title="Duration(ns)"> 262 </lit-table-column> 263 <lit-table-column width="1fr" data-index="minDuration" key="minDuration" align="flex-start" title="Min Duration(ns)"> 264 </lit-table-column> 265 <lit-table-column width="1fr" data-index="avgDuration" key="avgDuration" align="flex-start" title="Avg Duration(ns)"> 266 </lit-table-column> 267 <lit-table-column width="1fr" data-index="maxDuration" key="maxDuration" align="flex-start" title="Max Duration(ns)"> 268 </lit-table-column> 269 </lit-table> 270 `; 271 } 272} 273