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 { SpSystemTrace } from '../SpSystemTrace'; 17import { TraceRow } from '../trace/base/TraceRow'; 18import { type BaseStruct } from '../../bean/BaseStruct'; 19import { renders } from '../../database/ui-worker/ProcedureWorker'; 20import { Utils } from '../trace/base/Utils'; 21import { type EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; 22import { info } from '../../../log/Log'; 23import { type SnapshotRender, SnapshotStruct } from '../../database/ui-worker/ProcedureWorkerSnapshot'; 24import { type TreeItemData } from '../../../base-ui/tree/LitTree'; 25import { MemoryConfig } from '../../bean/MemoryConfig'; 26import { TabPaneSmapsRecord } from '../trace/sheet/smaps/TabPaneSmapsRecord'; 27import { 28 dmaDataSender, 29 gpuGpuDataSender, 30 gpuMemoryDataSender, 31 gpuResourceDataSender, 32 gpuTotalDataSender, 33 gpuWindowDataSender, 34 purgeableDataSender, 35 sMapsDataSender, 36 shmDataSender, 37} from '../../database/data-trafic/VmTrackerDataSender'; 38import { resetVmTracker } from '../../database/data-trafic/VmTrackerDataReceiver'; 39import { querySmapsExits } from '../../database/sql/Smaps.sql'; 40import { 41 queryisExistsGpuMemoryData, 42 queryisExistsPurgeableData, 43 queryisExistsShmData, 44} from '../../database/sql/Memory.sql'; 45import { queryisExistsDmaData } from '../../database/sql/Dma.sql'; 46import { 47 queryGpuTotalType, 48 queryGpuWindowType, 49 queryisExistsGpuData, 50 queryisExistsGpuResourceData, 51} from '../../database/sql/Gpu.sql'; 52import { SpStatisticsHttpUtil } from '../../../statistics/util/SpStatisticsHttpUtil'; 53 54export class VmTrackerChart { 55 private trace: SpSystemTrace; 56 private rowFolder!: TraceRow<BaseStruct>; 57 private sMapsFolder!: TraceRow<BaseStruct>; 58 private gpuFolder!: TraceRow<BaseStruct>; 59 private memoryConfig: MemoryConfig = MemoryConfig.getInstance(); 60 static gpuTotalModule: number | null = null; //ns 61 static gpuWindow: number | null = null; //ns 62 static gpuWindowModule: number | null = null; //ns 63 private smapsRecordTab: TabPaneSmapsRecord | undefined | null; 64 private scratchId = -1; 65 private isExistsPurgeableTotal: Array<unknown> = []; 66 private isExistsPurgeablePin: Array<unknown> = []; 67 private isExistsGpuMemory: Array<unknown> = []; 68 private isExistsGpuResource: Array<unknown> = []; 69 private isExistsGraph: Array<unknown> = []; 70 private isExistsGl: Array<unknown> = []; 71 constructor(trace: SpSystemTrace) { 72 this.trace = trace; 73 } 74 75 async init(): Promise<void> { 76 this.smapsRecordTab = this.trace 77 .shadowRoot!.querySelector('div > trace-sheet')! 78 .shadowRoot!.querySelector<TabPaneSmapsRecord>('#box-smaps-record > tabpane-smaps-record'); 79 if (this.scratchId === -1) { 80 for (let [key, value] of SpSystemTrace.DATA_DICT) { 81 if (value === 'Scratch') { 82 this.scratchId = key; 83 break; 84 } 85 } 86 } 87 const result = await querySmapsExits(); 88 this.isExistsPurgeableTotal = await queryisExistsPurgeableData(this.memoryConfig.iPid, false); 89 this.isExistsPurgeablePin = await queryisExistsPurgeableData(this.memoryConfig.iPid, true); 90 this.isExistsGpuMemory = await queryisExistsGpuMemoryData(this.memoryConfig.iPid); 91 this.isExistsGpuResource = await queryisExistsGpuResourceData(this.scratchId); 92 this.isExistsGraph = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.graph_pss'"); 93 this.isExistsGl = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.gl_pss'"); 94 const isExistsShm = await queryisExistsShmData(this.memoryConfig.iPid); 95 const isExistsDma = await queryisExistsDmaData(this.memoryConfig.iPid); 96 //@ts-ignore 97 if (result.length === 0 && isExistsShm[0].data_exists === 0 && isExistsDma[0].data_exists === 0 && this.isExistsPurgeableTotal[0].data_exists === 0 && 98 //@ts-ignore 99 this.isExistsPurgeablePin[0].data_exists === 0 && this.isExistsGpuMemory[0].data_exists === 0 && this.isExistsGpuResource[0].data_exists === 0 && 100 //@ts-ignore 101 this.isExistsGraph[0].data_exists === 0 && this.isExistsGl[0].data_exists === 0) { 102 return; 103 } 104 await this.initVmTrackerFolder(); 105 if (result.length > 0) { 106 await this.initSMapsFolder(); 107 const rowNameList: Array<string> = ['Dirty', 'Swapped', 'RSS', 'PSS', 'USS']; 108 for (const rowName of rowNameList) { 109 await this.initSmapsRows(rowName); 110 } 111 } 112 //@ts-ignore 113 if (isExistsShm[0].data_exists) { 114 await this.initShmRows(); 115 } 116 await this.initPurgeableVM(); 117 // @ts-ignore 118 if (isExistsDma[0].data_exists) { 119 await this.initDmaRow(); 120 } 121 await this.initGpuData(); 122 } 123 124 private async initGpuData(): Promise<void> { 125 if ( 126 // @ts-ignore 127 this.isExistsGpuMemory[0].data_exists || 128 // @ts-ignore 129 this.isExistsGpuResource[0].data_exists || 130 // @ts-ignore 131 this.isExistsGraph[0].data_exists || 132 // @ts-ignore 133 this.isExistsGl[0].data_exists 134 ) { 135 await this.initGpuFolder(); 136 // @ts-ignore 137 if (this.isExistsGpuMemory[0].data_exists) { 138 await this.initGpuMemoryRow(); 139 } 140 // @ts-ignore 141 if (this.isExistsGpuResource[0].data_exists) { 142 await this.initGpuResourceRow(this.scratchId); 143 } else { 144 this.smapsRecordTab!.GLESHostCache = []; 145 } 146 // @ts-ignore 147 if (this.isExistsGraph[0].data_exists) { 148 await this.addGpuGraphRow(); 149 } 150 // @ts-ignore 151 if (this.isExistsGl[0].data_exists) { 152 await this.addGpuGLRow(); 153 await this.addGpuTotalRow(); 154 await this.addGpuWindowRow(); 155 } 156 } 157 } 158 159 private initVmTrackerFolder = async (): Promise<void> => { 160 let VmTrackerRow = TraceRow.skeleton(); 161 VmTrackerRow.rowId = 'VmTrackerRow'; 162 VmTrackerRow.rowType = TraceRow.ROW_TYPE_VM_TRACKER; 163 VmTrackerRow.addTemplateTypes('ProcessMemory'); 164 VmTrackerRow.addTemplateTypes('Memory'); 165 VmTrackerRow.rowParentId = ''; 166 VmTrackerRow.style.height = '40px'; 167 VmTrackerRow.index = 0; 168 VmTrackerRow.folder = true; 169 VmTrackerRow.name = `VM Tracker (${this.memoryConfig.processName} ${this.memoryConfig.pid})`; 170 VmTrackerRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 171 VmTrackerRow.selectChangeHandler = this.trace.selectChangeHandler; 172 VmTrackerRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => 173 new Promise<Array<SnapshotStruct>>((resolve) => resolve([])); 174 VmTrackerRow.onThreadHandler = (useCache): void => { 175 let context: CanvasRenderingContext2D; 176 if (VmTrackerRow.currentContext) { 177 context = VmTrackerRow.currentContext; 178 } else { 179 context = VmTrackerRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 180 } 181 VmTrackerRow.canvasSave(context); 182 if (VmTrackerRow.expansion) { 183 // @ts-ignore 184 context?.clearRect(0, 0, VmTrackerRow.frame.width, VmTrackerRow.frame.height); 185 } else { 186 (renders.empty as EmptyRender).renderMainThread( 187 { 188 context: context, 189 useCache: useCache, 190 type: '', 191 }, 192 VmTrackerRow 193 ); 194 } 195 VmTrackerRow.canvasRestore(context, this.trace); 196 }; 197 this.rowFolder = VmTrackerRow; 198 this.trace.rowsEL?.appendChild(VmTrackerRow); 199 }; 200 201 private initSMapsFolder = async (): Promise<void> => { 202 let sMapsRow = TraceRow.skeleton<SnapshotStruct>(); 203 sMapsRow.rowId = 'smapsRow'; 204 sMapsRow.rowParentId = 'VmTrackerRow'; 205 sMapsRow.rowHidden = !this.rowFolder.expansion; 206 sMapsRow.rowType = TraceRow.ROW_TYPE_VM_TRACKER_SMAPS; 207 sMapsRow.folder = true; 208 sMapsRow.name = 'Smaps'; 209 sMapsRow.folderPaddingLeft = 20; 210 sMapsRow.style.height = '40px'; 211 sMapsRow.style.width = '100%'; 212 sMapsRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 213 sMapsRow.selectChangeHandler = this.trace.selectChangeHandler; 214 sMapsRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => 215 new Promise<Array<SnapshotStruct>>((resolve) => resolve([])); 216 sMapsRow.onThreadHandler = (useCache): void => { 217 let context: CanvasRenderingContext2D; 218 if (sMapsRow.currentContext) { 219 context = sMapsRow.currentContext; 220 } else { 221 context = sMapsRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 222 } 223 sMapsRow.canvasSave(context); 224 if (sMapsRow.expansion) { 225 // @ts-ignore 226 context?.clearRect(0, 0, sMapsRow.frame.width, sMapsRow.frame.height); 227 } else { 228 (renders.empty as EmptyRender).renderMainThread( 229 { 230 context: context, 231 useCache: useCache, 232 type: '', 233 }, 234 sMapsRow 235 ); 236 } 237 sMapsRow.canvasRestore(context, this.trace); 238 }; 239 this.sMapsFolder = sMapsRow; 240 this.rowFolder?.addChildTraceRow(sMapsRow); 241 }; 242 243 private initGpuFolder = async (): Promise<TraceRow<SnapshotStruct>> => { 244 let gpuTraceRow = TraceRow.skeleton<SnapshotStruct>(); 245 gpuTraceRow.rowId = 'skiaGpuTraceRow'; 246 gpuTraceRow.rowType = TraceRow.ROW_TYPE_SYS_MEMORY_GPU; 247 gpuTraceRow.rowParentId = 'VmTrackerRow'; 248 gpuTraceRow.style.height = '40px'; 249 gpuTraceRow.folder = true; 250 gpuTraceRow.folderPaddingLeft = 20; 251 gpuTraceRow.rowHidden = !this.rowFolder.expansion; 252 gpuTraceRow.name = 'GPU'; 253 gpuTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 254 gpuTraceRow.selectChangeHandler = this.trace.selectChangeHandler; 255 gpuTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => 256 new Promise<Array<SnapshotStruct>>((resolve) => resolve([])); 257 gpuTraceRow.onThreadHandler = (useCache): void => { 258 let context: CanvasRenderingContext2D; 259 if (gpuTraceRow.currentContext) { 260 context = gpuTraceRow.currentContext; 261 } else { 262 context = gpuTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 263 } 264 gpuTraceRow.canvasSave(context); 265 if (gpuTraceRow.expansion) { 266 // @ts-ignore 267 context?.clearRect(0, 0, gpuTraceRow.frame.width, gpuTraceRow.frame.height); 268 } else { 269 (renders.empty as EmptyRender).renderMainThread( 270 { 271 context: context, 272 useCache: useCache, 273 type: '', 274 }, 275 gpuTraceRow 276 ); 277 } 278 gpuTraceRow.canvasRestore(context, this.trace); 279 }; 280 this.gpuFolder = gpuTraceRow; 281 this.rowFolder.addChildTraceRow(gpuTraceRow); 282 return gpuTraceRow; 283 }; 284 285 private getSmapsKeyName(rowName: string): string { 286 let columnName = rowName.toLowerCase(); 287 let keyName = ''; 288 switch (rowName) { 289 case 'USS': 290 keyName = 'private_clean + private_dirty'; 291 break; 292 case 'RSS': 293 keyName = 'resident_size'; 294 break; 295 case 'Swapped': 296 keyName = 'swap + swap_pss'; 297 break; 298 default: 299 keyName = columnName; 300 } 301 return keyName; 302 } 303 304 private initSmapsRows = async (rowName: string): Promise<void> => { 305 let sMapsTraceRow = this.initTraceRow(rowName, TraceRow.ROW_TYPE_VM_TRACKER_SMAPS, 'smapsRow'); 306 sMapsTraceRow.rowHidden = !this.sMapsFolder.expansion; 307 sMapsTraceRow.folderTextLeft = 40; 308 sMapsTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 309 //@ts-ignore 310 return sMapsDataSender(this.getSmapsKeyName(rowName), sMapsTraceRow).then((sMaps: unknown[]) => { 311 this.setName(sMaps); 312 return sMaps; 313 }); 314 }; 315 this.sMapsFolder.addChildTraceRow(sMapsTraceRow); 316 }; 317 318 private initShmRows = async (): Promise<void> => { 319 let shmTraceRow = this.initTraceRow('SHM', TraceRow.ROW_TYPE_VMTRACKER_SHM, 'VmTrackerRow'); 320 shmTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 321 //@ts-ignore 322 return shmDataSender(this.memoryConfig.iPid, shmTraceRow).then((shmData: unknown[]) => { 323 this.setName(shmData); 324 return shmData; 325 }); 326 }; 327 this.rowFolder.addChildTraceRow(shmTraceRow); 328 }; 329 330 private async initPurgeableTotal(): Promise<void> { 331 let totalTraceRow = this.initTraceRow('Purgeable Total', TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM, 'VmTrackerRow'); 332 totalTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 333 //@ts-ignore 334 return purgeableDataSender(this.memoryConfig.iPid, totalTraceRow, false).then((purgeableTotalData: unknown[]) => { 335 this.setName(purgeableTotalData); 336 return purgeableTotalData; 337 }); 338 }; 339 this.rowFolder.addChildTraceRow(totalTraceRow); 340 } 341 342 private async initPurgeablePin(): Promise<void> { 343 let pinTraceRow = this.initTraceRow('Purgeable Pin', TraceRow.ROW_TYPE_PURGEABLE_PIN_VM, 'VmTrackerRow'); 344 pinTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 345 //@ts-ignore 346 return purgeableDataSender(this.memoryConfig.iPid, pinTraceRow, true).then((purgeablePinData: unknown[]) => { 347 this.setName(purgeablePinData); 348 return purgeablePinData; 349 }); 350 }; 351 this.rowFolder.addChildTraceRow(pinTraceRow); 352 } 353 354 private initPurgeableVM = async (): Promise<void> => { 355 let time = new Date().getTime(); 356 //@ts-ignore 357 if (this.isExistsPurgeableTotal[0].data_exists) { 358 await this.initPurgeableTotal(); 359 } //@ts-ignore 360 if (this.isExistsPurgeablePin[0].data_exists) { 361 await this.initPurgeablePin(); 362 } 363 let durTime = new Date().getTime() - time; 364 info('The time to load the VM Purgeable is: ', durTime); 365 }; 366 367 private initDmaRow = async (): Promise<void> => { 368 let dmaTraceRow = this.initTraceRow('DMA', TraceRow.ROW_TYPE_DMA_VMTRACKER, 'VmTrackerRow'); 369 dmaTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 370 //@ts-ignore 371 return dmaDataSender(this.memoryConfig.iPid, dmaTraceRow).then((dmaData: unknown[]) => { 372 this.setName(dmaData); 373 return dmaData; 374 }); 375 }; 376 this.rowFolder.addChildTraceRow(dmaTraceRow); 377 }; 378 379 private initGpuMemoryRow = async (): Promise<void> => { 380 let gpuMemoryTraceRow = this.initTraceRow( 381 'Skia Gpu Memory', 382 TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER, 383 'skiaGpuTraceRow' 384 ); 385 gpuMemoryTraceRow.rowHidden = !this.gpuFolder.expansion; 386 gpuMemoryTraceRow.folderTextLeft = 40; 387 gpuMemoryTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 388 //@ts-ignore 389 return gpuMemoryDataSender(this.memoryConfig.iPid, gpuMemoryTraceRow).then((gpuMemoryData: unknown[]) => { 390 this.setName(gpuMemoryData); 391 return gpuMemoryData; 392 }); 393 }; 394 this.gpuFolder.addChildTraceRow(gpuMemoryTraceRow); 395 }; 396 397 private initGpuResourceRow = async (scratchId: number): Promise<void> => { 398 let gpuMemoryTraceRow = this.initTraceRow( 399 'Gpu Resource', 400 TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER, 401 this.gpuFolder.rowId! 402 ); 403 gpuMemoryTraceRow.rowHidden = !this.gpuFolder.expansion; 404 gpuMemoryTraceRow.folderTextLeft = 40; 405 gpuMemoryTraceRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 406 //@ts-ignore 407 return gpuResourceDataSender(scratchId, gpuMemoryTraceRow).then((gpuResourceData: unknown[]) => { 408 this.setName(gpuResourceData); 409 // 将泳道图数据传递给Native Heap Tab页 410 //@ts-ignore 411 this.smapsRecordTab!.GLESHostCache = gpuResourceData; 412 return gpuResourceData; 413 }); 414 }; 415 this.gpuFolder.addChildTraceRow(gpuMemoryTraceRow); 416 }; 417 418 private async addGpuGraphRow(): Promise<void> { 419 let graphRow = this.initTraceRow('Graph', TraceRow.ROW_TYPE_SYS_MEMORY_GPU_GRAPH, this.gpuFolder.rowId!); 420 graphRow.addTemplateTypes('sys-memory'); 421 graphRow.folderTextLeft = 40; 422 graphRow.supplierFrame = (): Promise<SnapshotStruct[]> => { 423 //@ts-ignore 424 return gpuGpuDataSender(this.memoryConfig.iPid, "'mem.graph_pss'", graphRow).then((graphData: unknown[]) => { 425 this.setName(graphData); 426 return graphData; 427 }); 428 }; 429 this.gpuFolder.addChildTraceRow(graphRow); 430 } 431 432 private async addGpuGLRow(): Promise<void> { 433 let glRow = this.initTraceRow('GL', TraceRow.ROW_TYPE_SYS_MEMORY_GPU_GL, this.gpuFolder.rowId!); 434 glRow.addTemplateTypes('sys-memory'); 435 glRow.folderTextLeft = 40; 436 glRow.supplierFrame = (): Promise<SnapshotStruct[]> => { 437 //@ts-ignore 438 return gpuGpuDataSender(this.memoryConfig.iPid, "'mem.gl_pss'", glRow).then((glData: unknown[]) => { 439 this.setName(glData); 440 return glData; 441 }); 442 }; 443 this.gpuFolder.addChildTraceRow(glRow); 444 } 445 446 private async addGpuTotalRow(): Promise<void> { 447 let types = await queryGpuTotalType(); 448 if (!types || types.length === 0) { 449 return; 450 } 451 let gpuTotalRow = this.initTraceRow( 452 'Skia Gpu Dump Total', 453 TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL, 454 this.gpuFolder.rowId! 455 ); 456 gpuTotalRow.folderTextLeft = 40; 457 gpuTotalRow.addTemplateTypes('sys-memory'); 458 gpuTotalRow.addRowSettingPop(); 459 gpuTotalRow.rowSetting = 'enable'; 460 gpuTotalRow.rowSettingList = [ 461 { 462 key: 'total', 463 title: 'Total', 464 checked: true, 465 }, 466 ...types.map( 467 ( 468 it 469 ): { 470 key: string; 471 title: string; 472 } => { 473 return { 474 key: `${it.id}`, 475 title: it.data, 476 }; 477 } 478 ), 479 ]; 480 this.addHandleEventByGpuTotalRow(gpuTotalRow); 481 this.gpuFolder.addChildTraceRow(gpuTotalRow); 482 } 483 484 private addHandleEventByGpuTotalRow(gpuTotalRow: TraceRow<SnapshotStruct>): void { 485 gpuTotalRow.onRowSettingChangeHandler = (setting): void => { 486 if (setting && setting.length > 0) { 487 gpuTotalRow.dataListCache = []; 488 gpuTotalRow.dataList = []; 489 gpuTotalRow.isComplete = false; 490 VmTrackerChart.gpuTotalModule = setting[0] === 'total' ? null : parseInt(setting[0]); 491 gpuTotalRow.needRefresh = true; 492 gpuTotalRow.drawFrame(); 493 } 494 }; 495 gpuTotalRow.supplierFrame = (): Promise<Array<SnapshotStruct>> => { 496 //@ts-ignore 497 return gpuTotalDataSender(VmTrackerChart.gpuTotalModule, gpuTotalRow).then((gpuTotalData: unknown[]) => { 498 this.setName(gpuTotalData); 499 return gpuTotalData; 500 }); 501 }; 502 } 503 504 private async addGpuWindowRow(): Promise<void> { 505 let types = await queryGpuWindowType(); 506 if (!types || types.length === 0) { 507 return; 508 } 509 let settings: TreeItemData[] = types 510 .filter((it) => it.pid === null) 511 .map((it) => { 512 return { 513 key: `${it.id}`, 514 title: it.data, 515 children: [], 516 }; 517 }); 518 settings.forEach((it) => { 519 it.children = types 520 .filter((child) => `${child.pid}` === it.key) 521 .map((item) => { 522 return { 523 key: `${it.key}-${item.id}`, 524 title: item.data, 525 }; 526 }); 527 }); 528 settings[0].checked = true; 529 VmTrackerChart.gpuWindow = parseInt(settings[0].key); 530 VmTrackerChart.gpuWindowModule = null; 531 let gpuWindowRow = this.initTraceRow( 532 'Skia Gpu Dump Window', 533 TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW, 534 this.gpuFolder.rowId! 535 ); 536 gpuWindowRow.folderTextLeft = 40; 537 gpuWindowRow.addRowSettingPop(); 538 gpuWindowRow.rowSetting = 'enable'; 539 gpuWindowRow.rowSettingList = settings; 540 gpuWindowRow.addTemplateTypes('sys-memory'); 541 this.addHandleEventByGpuWindowRow(gpuWindowRow); 542 this.gpuFolder.addChildTraceRow(gpuWindowRow); 543 } 544 545 private addHandleEventByGpuWindowRow(gpuWindowRow: TraceRow<SnapshotStruct>): void { 546 gpuWindowRow.onRowSettingChangeHandler = (setting): void => { 547 if (setting && setting.length > 0) { 548 let split = setting[0].split('-'); 549 VmTrackerChart.gpuWindow = parseInt(split[0]); 550 VmTrackerChart.gpuWindowModule = split.length > 1 ? parseInt(split[1]) : null; 551 gpuWindowRow.dataListCache = []; 552 gpuWindowRow.dataList = []; 553 gpuWindowRow.isComplete = false; 554 gpuWindowRow.needRefresh = true; 555 gpuWindowRow.drawFrame(); 556 } 557 }; 558 gpuWindowRow.supplierFrame = (): Promise<SnapshotStruct[]> => { 559 //@ts-ignore 560 return gpuWindowDataSender(VmTrackerChart.gpuWindow!, VmTrackerChart.gpuWindowModule, gpuWindowRow).then( 561 (gpuWindowData: unknown[]) => { 562 this.setName(gpuWindowData); 563 return gpuWindowData; 564 } 565 ); 566 }; 567 } 568 569 private initTraceRow(rowName: string, type: string, rowParentId: string): TraceRow<SnapshotStruct> { 570 let vmTrackerTraceRow = TraceRow.skeleton<SnapshotStruct>(); 571 vmTrackerTraceRow.rowParentId = rowParentId; 572 vmTrackerTraceRow.rowId = rowName; 573 vmTrackerTraceRow.rowType = type; 574 vmTrackerTraceRow.folderTextLeft = 20; 575 vmTrackerTraceRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; 576 vmTrackerTraceRow.selectChangeHandler = this.trace.selectChangeHandler; 577 vmTrackerTraceRow.style.height = '40px'; 578 vmTrackerTraceRow.style.width = '100%'; 579 vmTrackerTraceRow.setAttribute('children', ''); 580 vmTrackerTraceRow.name = rowName; 581 vmTrackerTraceRow.focusHandler = (): void => { 582 this.showTip(vmTrackerTraceRow); 583 }; 584 vmTrackerTraceRow.findHoverStruct = (): void => { 585 SnapshotStruct.hoverSnapshotStruct = vmTrackerTraceRow.getHoverStruct(); 586 }; 587 vmTrackerTraceRow.onThreadHandler = (useCache): void => { 588 let context: CanvasRenderingContext2D; 589 if (vmTrackerTraceRow.currentContext) { 590 context = vmTrackerTraceRow.currentContext; 591 } else { 592 context = vmTrackerTraceRow.collect ? this.trace.canvasFavoritePanelCtx! : this.trace.canvasPanelCtx!; 593 } 594 vmTrackerTraceRow.canvasSave(context); 595 (renders.snapshot as SnapshotRender).renderMainThread( 596 { 597 context: context, 598 useCache: useCache, 599 type: 'snapshot', 600 }, 601 vmTrackerTraceRow 602 ); 603 vmTrackerTraceRow.canvasRestore(context, this.trace); 604 }; 605 return vmTrackerTraceRow; 606 } 607 608 private showTip(traceRow: TraceRow<SnapshotStruct>): void { 609 this.trace?.displayTip( 610 traceRow, 611 SnapshotStruct.hoverSnapshotStruct, 612 `<span>Name: ${SnapshotStruct.hoverSnapshotStruct?.name || ''}</span> 613 <span>Size: ${Utils.getBinaryByteWithUnit(SnapshotStruct.hoverSnapshotStruct?.value || 0)}</span>` 614 ); 615 } 616 617 private setName(data: Array<unknown>): void { 618 if (data.length > 0) { 619 data.forEach((item, index) => { 620 //@ts-ignore 621 item.name = `SnapShot ${index}`; 622 }); 623 } 624 } 625} 626