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 sp 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 { JankStruct } from '../database/ui-worker/ProcedureWorkerJank'; 17import { SpSystemTrace } from './SpSystemTrace'; 18import { TraceRow } from './trace/base/TraceRow'; 19import { LineType, ns2xByTimeShaft } from '../database/ui-worker/ProcedureWorkerCommon'; 20import { TabPaneTaskFrames } from './trace/sheet/task/TabPaneTaskFrames'; 21import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc'; 22import { queryBySelectExecute } from '../database/sql/ProcessThread.sql'; 23import { queryTaskPoolOtherRelationData, queryTaskPoolRelationData } from '../database/sql/Func.sql'; 24import { queryBySelectAllocationOrReturn } from '../database/sql/SqlLite.sql'; 25import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread'; 26 27function collectionHasJank(jankRow: any, collectList: TraceRow<any>[]): boolean { 28 for (let item of collectList!) { 29 if (item.rowId === jankRow.rowId && item.rowType === jankRow.rowType) { 30 return false; 31 } 32 } 33 return true; 34} 35 36function setPoint( 37 x: number, 38 y: number, 39 offsetY: number, 40 ns: number, 41 rowEL: any, 42 isRight: boolean, 43 business: string 44): any { 45 return { 46 x: x, 47 y: y, 48 offsetY: offsetY, 49 ns: ns, 50 rowEL: rowEL!, 51 isRight: isRight, 52 business: business, 53 }; 54} 55 56function selectJankApp( 57 endParentRow: any, 58 sp: SpSystemTrace, 59 data: any, 60 startRow: any, 61 selectJankStruct: JankStruct, 62 endRowStruct: any 63): void { 64 let collectList = sp.favoriteChartListEL!.getAllCollectRows(); 65 let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid); 66 let tts = 67 findJankEntry.frame_type == 'frameTime' ? selectJankStruct.ts! : selectJankStruct.ts! + selectJankStruct.dur!; 68 let startParentRow: any; 69 // startRow为子泳道,子泳道不存在,使用父泳道 70 if (startRow) { 71 startParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 72 `trace-row[row-id='${startRow.rowParentId}'][folder]` 73 ); 74 } else { 75 startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 76 `trace-row[row-id='${selectJankStruct?.pid}'][folder]` 77 ); 78 } 79 let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); 80 let endRowEl = endRowStruct; 81 let endOffSetY = 20 * (findJankEntry!.depth! + 0.5); 82 let expansionFlag = collectionHasJank(endRowStruct, collectList); 83 if (!endParentRow.expansion && expansionFlag) { 84 endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5); 85 endRowEl = endParentRow; 86 endOffSetY = 10 * (findJankEntry!.depth! + 0.5); 87 } 88 let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5); 89 let startRowEl = startRow; 90 let startOffSetY = 20 * (selectJankStruct!.depth! + 0.5); 91 expansionFlag = collectionHasJank(startRow, collectList); 92 if (startParentRow && !startParentRow.expansion && expansionFlag) { 93 startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5); 94 startRowEl = startParentRow; 95 startOffSetY = 10 * (selectJankStruct!.depth! + 0.5); 96 } 97 let startX = ns2xByTimeShaft(tts, sp.timerShaftEL!); 98 let endX = ns2xByTimeShaft(findJankEntry.ts!, sp.timerShaftEL!); 99 const startPoint = setPoint(startX, startY, startOffSetY, tts, startRowEl, selectJankStruct.ts == tts, 'janks'); 100 const endPoint = setPoint(endX, endY, endOffSetY, findJankEntry.ts!, endRowEl, true, 'janks'); 101 sp.addPointPair(startPoint, endPoint); 102} 103 104function findJankApp( 105 endParentRow: any, 106 sp: SpSystemTrace, 107 data: any, 108 startRow: any, 109 selectJankStruct: JankStruct, 110 endRowStruct: any 111): void { 112 let collectList = sp.favoriteChartListEL!.getAllCollectRows(); 113 let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid); 114 let tts = selectJankStruct.frame_type == 'frameTime' ? findJankEntry.ts : findJankEntry.ts! + findJankEntry.dur!; 115 let endY = endRowStruct!.translateY! + 20 * (findJankEntry!.depth! + 0.5); 116 let endRowEl = endRowStruct; 117 let endOffSetY = 20 * (findJankEntry!.depth! + 0.5); 118 let expansionFlag = collectionHasJank(endRowStruct, collectList); 119 if (!endParentRow.expansion && expansionFlag) { 120 endY = endParentRow!.translateY! + 10 * (findJankEntry!.depth! + 0.5); 121 endRowEl = endParentRow; 122 endOffSetY = 10 * (findJankEntry!.depth! + 0.5); 123 } 124 let startY = startRow!.translateY! + 20 * (selectJankStruct!.depth! + 0.5); 125 let startRowEl = startRow; 126 expansionFlag = collectionHasJank(startRow, collectList); 127 let startOffsetY = 20 * (selectJankStruct!.depth! + 0.5); 128 let startParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 129 `trace-row[row-id='${startRow.rowParentId}'][folder]` 130 ); 131 if (startParentRow && !startParentRow.expansion && expansionFlag) { 132 startY = startParentRow!.translateY! + 10 * (selectJankStruct!.depth! + 0.5); 133 startRowEl = startParentRow; 134 startOffsetY = 10 * (selectJankStruct!.depth! + 0.5); 135 } 136 let startX = ns2xByTimeShaft(selectJankStruct.ts!, sp.timerShaftEL!); 137 let endX = ns2xByTimeShaft(tts, sp.timerShaftEL!); 138 const startPoint = setPoint(startX, startY, startOffsetY, selectJankStruct.ts!, startRowEl, true, 'janks'); 139 const endPoint = setPoint(endX, endY, endOffSetY, tts, endRowEl, selectJankStruct.ts == tts, 'janks'); 140 sp.addPointPair(startPoint, endPoint); 141} 142 143function addPointLink( 144 endParentRow: any, 145 sp: SpSystemTrace, 146 data: any, 147 startRow: any, 148 selectJankStruct: JankStruct, 149 endRowStruct: any 150): void { 151 let findJankEntry = endRowStruct!.dataListCache!.find((dat: any) => dat.name == data.name && dat.pid == data.pid); 152 //连线规则:frametimeline的头----app的头,app的尾----renderservice的头 153 let tts: number = 0; 154 if (findJankEntry) { 155 if (selectJankStruct.frame_type == 'app') { 156 selectJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); 157 } 158 if (findJankEntry.frame_type == 'app') { 159 findJankApp(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); 160 } 161 if (data.children.length >= 1) { 162 let endP; 163 if (data.children[0].frame_type == 'frameTime') { 164 endP = sp.shadowRoot?.querySelector<TraceRow<any>>("trace-row[row-id='frameTime']"); 165 } else { 166 endP = sp.shadowRoot?.querySelector<TraceRow<any>>(`trace-row[row-id='${data.children[0].pid}'][folder]`); 167 } 168 sp.drawJankLine(endP, findJankEntry, data.children[0]); 169 } 170 } 171} 172 173function getEndStruct(data: any, sp: SpSystemTrace): any { 174 let endRowStruct: any; 175 if (data.frame_type == 'frameTime') { 176 endRowStruct = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 177 "trace-row[row-id='actual frameTime'][row-type='janks']" 178 ); 179 } else { 180 endRowStruct = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 181 `trace-row[row-id='${data.type}-${data.pid}'][row-type='janks']` 182 ); 183 } 184 return endRowStruct; 185} 186 187function drawJankLineEndParent( 188 endParentRow: any, 189 sp: SpSystemTrace, 190 data: any, 191 startRow: any, 192 selectJankStruct: JankStruct 193): void { 194 endParentRow.expansion = true; 195 //终点的父泳道过滤出选中的Struct 196 let endRowStruct = getEndStruct(data, sp); 197 //泳道未展开的情况,查找endRowStruct 198 if (!endRowStruct) { 199 if (data.frame_type == 'frameTime') { 200 endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => { 201 if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { 202 endRowStruct = item; 203 } 204 }); 205 //frameTime未展开 206 if (!endRowStruct) { 207 endParentRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>("trace-row[row-id='frameTime'][folder]"); 208 endParentRow?.childrenList?.forEach((item: TraceRow<JankStruct>) => { 209 if (item.rowId === 'actual frameTime' && item.rowType === 'janks') { 210 endRowStruct = item; 211 } 212 }); 213 } 214 } else { 215 endParentRow.childrenList.forEach((item: TraceRow<JankStruct>) => { 216 if (item.name.startsWith('Actual Timeline') && item.rowType === 'janks') { 217 endRowStruct = item; 218 } 219 }); 220 } 221 } 222 if (endRowStruct) { 223 if (endRowStruct.isComplete) { 224 addPointLink(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); 225 } else { 226 endRowStruct.supplierFrame!().then((res: any) => { 227 endRowStruct.dataListCache = res; 228 endRowStruct.loadingFrame = false; 229 addPointLink(endParentRow, sp, data, startRow, selectJankStruct, endRowStruct); 230 }); 231 } 232 } 233} 234 235export function spSystemTraceDrawJankLine( 236 sp: SpSystemTrace, 237 endParentRow: any, 238 selectJankStruct: JankStruct, 239 data: any 240): void { 241 let collectList = sp.favoriteChartListEL!.getAllCollectRows(); 242 let startRow: any; 243 if (selectJankStruct == undefined || selectJankStruct == null) { 244 return; 245 } 246 let selectRowId = 'actual frameTime'; 247 if (selectJankStruct.frame_type == 'frameTime') { 248 startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 249 `trace-row[row-id='${selectRowId}'][row-type='janks']` 250 ); 251 } else { 252 selectRowId = selectJankStruct?.type + '-' + selectJankStruct?.pid; 253 startRow = sp.shadowRoot?.querySelector<TraceRow<JankStruct>>( 254 `trace-row[row-id='${selectRowId}'][row-type='janks']` 255 ); 256 } 257 if (!startRow) { 258 for (let collectChart of collectList) { 259 if (collectChart.rowId === selectRowId && collectChart.rowType === 'janks') { 260 startRow = collectChart; 261 break; 262 } 263 } 264 } 265 if (endParentRow) { 266 drawJankLineEndParent(endParentRow, sp, data, startRow, selectJankStruct); 267 } 268} 269 270function taskPoolOtherRelationData( 271 selectRow: any, 272 sp: SpSystemTrace, 273 row: TraceRow<any>, 274 relationDataList: FuncStruct[], 275 res: any 276): void { 277 selectRow!.fixedList = relationDataList; 278 relationDataList.forEach((value) => { 279 TabPaneTaskFrames.TaskArray.push(value); 280 // allocation to execute 281 const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20; 282 const offSetY = (value.depth! + 0.5) * 20; 283 const selectRowY = selectRow?.translateY!; 284 const selectStartTs = FuncStruct.selectFuncStruct!.startTs!; 285 const selectDur = FuncStruct.selectFuncStruct!.dur!; 286 287 if (value.id === res[0].allocation_task_row) { 288 sp.addPointPair( 289 sp.makePoint(value.startTs!, 0, selectRowY, selectRow, offSetY, 'task', LineType.bezierCurve, true), 290 sp.makePoint(selectStartTs, 0, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, true) 291 ); 292 } else { 293 sp.addPointPair( 294 sp.makePoint(selectStartTs, selectDur, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, false), 295 sp.makePoint(value.startTs!, value.dur!, selectRowY, selectRow, offSetY, 'task', LineType.bezierCurve, false) 296 ); 297 } 298 }); 299 sp.refreshCanvas(true); 300} 301 302function taskPoolRelationDataAllocation( 303 executeRow: TraceRow<FuncStruct> | null | undefined, 304 sp: SpSystemTrace, 305 row: TraceRow<any>, 306 relationDataList: FuncStruct[], 307 res: any 308): void { 309 let executeStruct = relationDataList.filter((item) => item.id === res[0].execute_task_row)[0]; 310 relationDataList.forEach((value) => { 311 const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20; 312 const offSetY = (value.depth! + 0.5) * 20; 313 const executeRowY = executeRow?.translateY!; 314 const selectStartTs = FuncStruct.selectFuncStruct!.startTs!; 315 const executeY = (executeStruct.depth! + 0.5) * 20; 316 TabPaneTaskFrames.TaskArray.push(value); 317 if (value.id === res[0].execute_task_row) { 318 sp.addPointPair( 319 sp.makePoint(selectStartTs, 0, row?.translateY!, row, selectY, 'task', LineType.bezierCurve, true), 320 sp.makePoint(value.startTs!, 0, executeRowY, executeRow, offSetY, 'task', LineType.bezierCurve, true) 321 ); 322 } else { 323 sp.addPointPair( 324 sp.makePoint( 325 executeStruct.startTs!, 326 executeStruct.dur!, 327 executeRowY, 328 executeRow, 329 executeY, 330 'task', 331 LineType.bezierCurve, 332 false 333 ), 334 sp.makePoint(value.startTs!, value.dur!, row?.translateY!, row, offSetY, 'task', LineType.bezierCurve, false) 335 ); 336 } 337 }); 338} 339 340function taskPoolRelationDataPerformTask( 341 executeRow: TraceRow<FuncStruct> | null | undefined, 342 sp: SpSystemTrace, 343 row: TraceRow<any>, 344 relationDataList: FuncStruct[], 345 res: any 346): void { 347 let executeStruct = relationDataList.filter((item) => item.id === res[0].execute_task_row)[0]; 348 relationDataList.forEach((value) => { 349 const executeRowY = executeRow?.translateY!; 350 const selectStartTs = FuncStruct.selectFuncStruct!.startTs!; 351 const executeY = (executeStruct.depth! + 0.5) * 20; 352 const selectY = (FuncStruct.selectFuncStruct!.depth! + 0.5) * 20; 353 const offSetY = (value.depth! + 0.5) * 20; 354 TabPaneTaskFrames.TaskArray.push(value); 355 if (value.id === res[0].execute_task_row) { 356 sp.addPointPair( 357 sp.makePoint( 358 selectStartTs, 359 FuncStruct.selectFuncStruct!.dur!, 360 row?.translateY!, 361 row, 362 selectY, 363 'task', 364 LineType.bezierCurve, 365 false 366 ), 367 sp.makePoint(value.startTs!, value.dur!, executeRowY, executeRow, offSetY, 'task', LineType.bezierCurve, false) 368 ); 369 } else { 370 sp.addPointPair( 371 sp.makePoint(executeStruct.startTs!, 0, executeRowY, executeRow, executeY, 'task', LineType.bezierCurve, true), 372 sp.makePoint(value.startTs!, 0, row?.translateY!, row, offSetY, 'task', LineType.bezierCurve, true) 373 ); 374 } 375 }); 376 sp.refreshCanvas(true); 377} 378 379function taskAllocationOrPerformTask(sp: SpSystemTrace, row: TraceRow<any>, executeID: string): void { 380 TabPaneTaskFrames.IsShowConcurrency = false; 381 queryBySelectAllocationOrReturn(executeID, FuncStruct.selectFuncStruct!.itid!).then((res) => { 382 if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Allocation:') >= 0 && res.length > 0) { 383 let executeRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 384 `trace-row[row-id='${res[0].tid}'][row-type='func']` 385 ); 386 if (!executeRow) { 387 return; 388 } 389 let idList: number[] = []; 390 let tidList: number[] = []; 391 if (res[0].execute_task_row) { 392 idList.push(res[0].execute_task_row); 393 tidList.push(Number(res[0].tid)); 394 } 395 if (res[0].return_task_row) { 396 idList.push(res[0].return_task_row); 397 tidList.push(Number(row.rowId)); 398 } 399 queryTaskPoolRelationData(idList, tidList).then((relationDataList) => { 400 taskPoolRelationDataAllocation(executeRow, sp, row, relationDataList, res); 401 }); 402 } else if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task PerformTask End:') >= 0) { 403 let executeRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 404 `trace-row[row-id='${res[0].tid}'][row-type='func']` 405 ); 406 TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); 407 let idList: number[] = []; 408 let tidList: number[] = []; 409 if (res[0].execute_task_row) { 410 idList.push(res[0].execute_task_row); 411 tidList.push(Number(res[0].tid)); 412 } 413 if (res[0].allocation_task_row) { 414 idList.push(res[0].allocation_task_row); 415 tidList.push(Number(row.rowId)); 416 } 417 queryTaskPoolRelationData(idList, tidList).then((relationDataList) => { 418 taskPoolRelationDataPerformTask(executeRow, sp, row, relationDataList, res); 419 }); 420 } 421 }); 422} 423 424export function spSystemTraceDrawTaskPollLine(sp: SpSystemTrace, row?: TraceRow<any>): void { 425 let executeID = TabPaneTaskFrames.getExecuteId(FuncStruct.selectFuncStruct!.funName!); 426 TabPaneTaskFrames.TaskArray.push(FuncStruct.selectFuncStruct!); 427 if (!row) { 428 return; 429 } 430 if (FuncStruct.selectFuncStruct!.funName!.indexOf('H:Task Perform:') >= 0) { 431 TabPaneTaskFrames.IsShowConcurrency = true; 432 queryBySelectExecute(executeID, FuncStruct.selectFuncStruct!.itid!).then((res) => { 433 if (res.length === 1) { 434 let allocationRowId = res[0].tid; 435 let selectRow = sp.shadowRoot?.querySelector<TraceRow<FuncStruct>>( 436 `trace-row[row-id='${allocationRowId}'][row-type='func']` 437 ); 438 if (!selectRow) { 439 let collectList = sp.favoriteChartListEL!.getAllCollectRows(); 440 for (let selectCollectRow of collectList) { 441 if (selectCollectRow.rowId === allocationRowId.toString() && selectCollectRow.rowType === 'func') { 442 selectRow = selectCollectRow; 443 break; 444 } 445 } 446 } 447 let idList: number[] = []; 448 if (res[0].allocation_task_row) { 449 idList.push(res[0].allocation_task_row); 450 } 451 if (res[0].return_task_row) { 452 idList.push(res[0].return_task_row); 453 } 454 queryTaskPoolOtherRelationData(idList, allocationRowId).then((relationDataList) => { 455 taskPoolOtherRelationData(selectRow, sp, row, relationDataList, res); 456 }); 457 } 458 }); 459 } else { 460 taskAllocationOrPerformTask(sp, row, executeID); 461 } 462} 463 464function jankPoint( 465 endRowStruct: any, 466 data: any, 467 sp: SpSystemTrace, 468 selectThreadStruct: ThreadStruct, 469 startRow: any, 470 endParentRow: any 471): void { 472 if (endRowStruct) { 473 let findJankEntry = endRowStruct!.dataListCache!.find( 474 (dat: any) => dat.startTime == data.startTime && dat.dur! > 0 475 ); 476 let ts: number = 0; 477 if (findJankEntry) { 478 ts = selectThreadStruct.startTime! + selectThreadStruct.dur! / 2; 479 const [startY, startRowEl, startOffSetY] = sp.calculateStartY(startRow, selectThreadStruct); 480 const [endY, endRowEl, endOffSetY] = sp.calculateEndY(endParentRow, endRowStruct); 481 sp.addPointPair( 482 sp.makePoint( 483 ns2xByTimeShaft(ts, sp.timerShaftEL!), 484 ts, 485 startY, 486 startRowEl!, 487 startOffSetY, 488 'thread', 489 LineType.straightLine, 490 selectThreadStruct.startTime == ts 491 ), 492 sp.makePoint( 493 ns2xByTimeShaft(findJankEntry.startTime!, sp.timerShaftEL!), 494 findJankEntry.startTime!, 495 endY, 496 endRowEl, 497 endOffSetY, 498 'thread', 499 LineType.straightLine, 500 true 501 ) 502 ); 503 sp.refreshCanvas(true); 504 } 505 } 506} 507 508export function spSystemTraceDrawThreadLine( 509 sp: SpSystemTrace, 510 endParentRow: any, 511 selectThreadStruct: ThreadStruct | undefined, 512 data: any 513): void { 514 const collectList = sp.favoriteChartListEL!.getCollectRows(); 515 if (!selectThreadStruct) { 516 return; 517 } 518 const selectRowId = selectThreadStruct?.tid; 519 let startRow = sp.getStartRow(selectRowId, collectList); 520 if (!endParentRow) { 521 return; 522 } 523 let endRowStruct: any = sp.shadowRoot?.querySelector<TraceRow<ThreadStruct>>( 524 `trace-row[row-id='${data.tid}'][row-type='thread']` 525 ); 526 if (!endRowStruct) { 527 endRowStruct = endParentRow.childrenList.find((item: TraceRow<ThreadStruct>) => { 528 return item.rowId === `${data.tid}` && item.rowType === 'thread'; 529 }); 530 } 531 jankPoint(endParentRow, data, sp, selectThreadStruct, startRow, endParentRow); 532} 533