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 { LitSelectV } from '../../../base-ui/select/LitSelectV'; 18import { LitSelect } from '../../../base-ui/select/LitSelect'; 19import { LitSlider } from '../../../base-ui/slider/LitSlider'; 20import LitSwitch, { LitSwitchChangeEvent } from '../../../base-ui/switch/lit-switch'; 21import '../../../base-ui/select/LitSelectV'; 22import '../../../base-ui/select/LitSelect'; 23 24import '../../../base-ui/switch/lit-switch'; 25import { info } from '../../../log/Log'; 26import { HdcDeviceManager } from '../../../hdc/HdcDeviceManager'; 27import { SpRecordTrace } from '../SpRecordTrace'; 28import { SpApplication } from '../../SpApplication'; 29import { LitSearch } from '../trace/search/Search'; 30import { Cmd } from '../../../command/Cmd'; 31import { CmdConstant } from '../../../command/CmdConstant'; 32import { SpRecordPerfHtml } from './SpRecordPerf.html'; 33 34@element('sp-record-perf') 35export class SpRecordPerf extends BaseElement { 36 private addOptionButton: HTMLButtonElement | undefined | null; 37 private processSelect: LitSelectV | undefined | null; 38 private processInput: HTMLInputElement | undefined | null; 39 private cpuSelect: LitSelectV | undefined | null; 40 private eventSelect: LitSelectV | undefined | null; 41 42 private frequencySetInput: HTMLInputElement | undefined | null; 43 private recordProcessInput: HTMLInputElement | undefined | null; 44 private offCPUSwitch: LitSwitch | undefined | null; 45 private kernelChainSwitch: LitSwitch | undefined | null; 46 private callSelect: LitSelect | undefined | null; 47 private sp: SpApplication | undefined; 48 private recordPerfSearch: LitSearch | undefined; 49 private inputCpu: HTMLInputElement | undefined; 50 private inputEvent: HTMLInputElement | undefined; 51 private cpuData: Array<string> = []; 52 private eventData: Array<string> = []; 53 54 get show(): boolean { 55 return this.hasAttribute('show'); 56 } 57 58 set show(perfShow: boolean) { 59 if (perfShow) { 60 this.setAttribute('show', ''); 61 } else { 62 this.removeAttribute('show'); 63 } 64 } 65 66 set startSamp(perfStart: boolean) { 67 if (perfStart) { 68 this.setAttribute('startSamp', ''); 69 this.recordProcessInput!.removeAttribute('readonly'); 70 } else { 71 this.removeAttribute('startSamp'); 72 this.recordProcessInput!.setAttribute('readonly', 'readonly'); 73 } 74 } 75 76 get startSamp(): boolean { 77 return this.hasAttribute('startSamp'); 78 } 79 80 getPerfConfig(): PerfConfig | undefined { 81 let recordPerfConfigVal = this.shadowRoot?.querySelectorAll<HTMLElement>('.config'); 82 let perfConfig: PerfConfig = { 83 process: 'ALL', 84 cpu: 'select ALL', 85 eventList: 'NONE', 86 cpuPercent: 100, 87 frequency: 1000, 88 period: 1, 89 isOffCpu: true, 90 noInherit: false, 91 isKernelChain: true, 92 callStack: 'dwarf', 93 branch: 'none', 94 mmap: 256, 95 clockType: 'monotonic', 96 }; 97 recordPerfConfigVal!.forEach((value) => { 98 perfConfig = this.getPerfConfigData(value, perfConfig); 99 }); 100 info('perfConfig is : ', perfConfig); 101 return perfConfig; 102 } 103 104 private getPerfConfigData(value: HTMLElement, perfConfig: PerfConfig): PerfConfig { 105 switch (value.title) { 106 case 'Process': 107 let processSelect = value as LitSelectV; 108 if (processSelect.all) { 109 perfConfig.process = 'ALL'; 110 break; 111 } 112 perfConfig = this.perfConfigByProcess(processSelect, perfConfig); 113 break; 114 case 'CPU': 115 perfConfig = this.perfConfigByCPU(perfConfig, value as LitSelectV); 116 break; 117 case 'Event List': 118 perfConfig = this.perfConfigByEventList(perfConfig, value as LitSelectV); 119 break; 120 case 'CPU Percent': 121 perfConfig = this.perfConfigCpuPercent(perfConfig, value.parentElement!); 122 break; 123 case 'Frequency': 124 perfConfig = this.perfConfigByFrequency(perfConfig, value as HTMLInputElement); 125 break; 126 case 'Period': 127 perfConfig = this.perfConfigByPeriod(perfConfig, value as HTMLInputElement); 128 break; 129 case 'Off CPU': 130 perfConfig.isOffCpu = (value as LitSwitch).checked; 131 break; 132 case 'Kernel Chain': 133 perfConfig.isKernelChain = (value as LitSwitch).checked; 134 break; 135 case 'No Inherit': 136 perfConfig.noInherit = (value as LitSwitch).checked; 137 break; 138 case 'Call Stack': 139 perfConfig = this.perfConfigByCallStack(perfConfig, value as LitSelect); 140 break; 141 case 'Branch': 142 perfConfig = this.perfConfigByBranch(perfConfig, value as LitSelect); 143 break; 144 case 'Mmap Pages': 145 perfConfig = this.perfConfigByMmapPages(perfConfig, value.parentElement!); 146 break; 147 case 'Clock Type': 148 perfConfig = this.perfConfigByClockType(perfConfig, value as LitSelect); 149 break; 150 } 151 return perfConfig; 152 } 153 154 private perfConfigByProcess(processSelect: LitSelectV, perfConfig: PerfConfig): PerfConfig { 155 if (processSelect.value.length > 0) { 156 let result = processSelect.value.match(/\((.+?)\)/g); 157 if (result) { 158 perfConfig.process = result.toString().replace(/[()]/g, ''); 159 } else { 160 perfConfig.process = processSelect.value; 161 } 162 } 163 return perfConfig; 164 } 165 166 private perfConfigByCPU(perfConfig: PerfConfig, selectValue: LitSelectV): PerfConfig { 167 if (selectValue.value.length > 0) { 168 perfConfig.cpu = selectValue.value; 169 } 170 return perfConfig; 171 } 172 173 private perfConfigByEventList(perfConfig: PerfConfig, selectValue: LitSelectV): PerfConfig { 174 if (selectValue.value.length > 0) { 175 perfConfig.eventList = selectValue.value.replace(/\s/g, ','); 176 } 177 return perfConfig; 178 } 179 180 private perfConfigCpuPercent(perfConfig: PerfConfig, parEle: HTMLElement): PerfConfig { 181 if (parEle!.hasAttribute('percent')) { 182 let percent = parEle!.getAttribute('percent'); 183 perfConfig.cpuPercent = Number(percent); 184 } 185 return perfConfig; 186 } 187 188 private perfConfigByFrequency(perfConfig: PerfConfig, elValue: HTMLInputElement): PerfConfig { 189 if (elValue.value !== '') { 190 perfConfig.frequency = Number(elValue.value); 191 } 192 return perfConfig; 193 } 194 195 private perfConfigByPeriod(perfConfig: PerfConfig, elValue: HTMLInputElement): PerfConfig { 196 if (elValue.value !== '') { 197 perfConfig.period = Number(elValue.value); 198 } 199 return perfConfig; 200 } 201 202 private perfConfigByCallStack(perfConfig: PerfConfig, callStack: LitSelect): PerfConfig { 203 if (callStack.value !== '') { 204 perfConfig.callStack = callStack.value; 205 } 206 return perfConfig; 207 } 208 209 private perfConfigByBranch(perfConfig: PerfConfig, branch: LitSelect): PerfConfig { 210 if (branch.value !== '') { 211 perfConfig.branch = branch.value; 212 } 213 return perfConfig; 214 } 215 216 private perfConfigByMmapPages(perfConfig: PerfConfig, parent: HTMLElement): PerfConfig { 217 if (parent!.hasAttribute('percent')) { 218 let pagesPercent = parent!.getAttribute('percent'); 219 perfConfig.mmap = Math.pow(2, Number(pagesPercent)); 220 } 221 return perfConfig; 222 } 223 224 private perfConfigByClockType(perfConfig: PerfConfig, clock: LitSelect): PerfConfig { 225 if (clock.value !== '') { 226 perfConfig.clockType = clock.value; 227 } 228 return perfConfig; 229 } 230 231 private initRecordPerfConfig(): void { 232 let recordPerfConfigList = this.shadowRoot?.querySelector<HTMLDivElement>('.configList'); 233 this.addOptionButton = this.shadowRoot?.querySelector<HTMLButtonElement>('#addOptions'); 234 perfConfigList.forEach((config) => { 235 let recordPerfDiv = document.createElement('div'); 236 if (config.hidden) { 237 recordPerfDiv.className = 'record-perf-config-div hidden'; 238 } else { 239 recordPerfDiv.className = 'record-perf-config-div'; 240 } 241 let recordPerfHeadDiv = document.createElement('div'); 242 recordPerfDiv.appendChild(recordPerfHeadDiv); 243 let recordPerfTitle = document.createElement('span'); 244 recordPerfTitle.className = 'record-perf-title'; 245 recordPerfTitle.textContent = config.title; 246 recordPerfHeadDiv.appendChild(recordPerfTitle); 247 let recordPerfDes = document.createElement('span'); 248 recordPerfDes.textContent = config.des; 249 recordPerfDes.className = 'record-perf-des'; 250 recordPerfHeadDiv.appendChild(recordPerfDes); 251 switch (config.type) { 252 case 'select-multiple': 253 this.configTypeBySelectMultiple(config, recordPerfDiv); 254 break; 255 case 'lit-slider': 256 this.configTypeByLitSlider(config, recordPerfDiv); 257 break; 258 case 'Mmap-lit-slider': 259 this.configTypeByMmapLitSlider(config, recordPerfDiv); 260 break; 261 case 'input': 262 this.configTypeByInput(config, recordPerfDiv); 263 break; 264 case 'select': 265 this.configTypeBySelect(config, recordPerfDiv); 266 break; 267 case 'switch': 268 this.configTypeBySwitch(config, recordPerfHeadDiv); 269 break; 270 default: 271 break; 272 } 273 recordPerfConfigList!.appendChild(recordPerfDiv); 274 }); 275 } 276 277 processSelectMousedownHandler = (): void => { 278 if (SpRecordTrace.serialNumber === '') { 279 this.processSelect!.dataSource([], 'ALL-Process'); 280 } else { 281 if (this.sp!.search) { 282 this.sp!.search = false; 283 this.recordPerfSearch!.clear(); 284 } 285 Cmd.getProcess().then( 286 (processList) => { 287 this.processSelect?.dataSource(processList, 'ALL-Process'); 288 }, 289 () => { 290 this.sp!.search = true; 291 this.recordPerfSearch!.clear(); 292 this.recordPerfSearch!.setPercent('please kill other hdc-server !', -2); 293 } 294 ); 295 } 296 }; 297 298 cpuSelectMouseDownHandler = (): void => { 299 if (SpRecordTrace.serialNumber === '') { 300 this.cpuSelect!.dataSource([], 'ALL-CPU'); 301 } 302 }; 303 304 cpuSelectMouseUpHandler = (): void => { 305 if (SpRecordTrace.serialNumber === '') { 306 this.cpuSelect?.dataSource([], ''); 307 } else { 308 if (this.sp!.search) { 309 this.sp!.search = false; 310 this.recordPerfSearch!.clear(); 311 } 312 if (SpRecordTrace.isVscode) { 313 let cmd = Cmd.formatString(CmdConstant.CMD_GET_CPU_COUNT_DEVICES, [SpRecordTrace.serialNumber]); 314 Cmd.execHdcCmd(cmd, (res: string) => { 315 this.cpuData = []; 316 let cpuCount = res!.trim(); 317 let cpus = Number(cpuCount); 318 for (let index = 0; index < cpus; index++) { 319 this.cpuData.push(String(index)); 320 } 321 this.cpuSelect?.dataSource(this.cpuData, 'ALL-CPU'); 322 }); 323 } else { 324 HdcDeviceManager.connect(SpRecordTrace.serialNumber).then((conn) => { 325 this.cpuData = []; 326 if (conn) { 327 HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_CPU_COUNT, false).then((res) => { 328 let cpuCount = res!.trim(); 329 let cpus = Number(cpuCount); 330 for (let index = 0; index < cpus; index++) { 331 this.cpuData.push(String(index)); 332 } 333 this.cpuSelect?.dataSource(this.cpuData, 'ALL-CPU'); 334 }); 335 } else { 336 this.recordPerfSearch!.clear(); 337 this.sp!.search = true; 338 this.recordPerfSearch!.setPercent('please kill other hdc-server !', -2); 339 } 340 }); 341 } 342 } 343 }; 344 345 eventSelectMousedownHandler = (): void => { 346 if (SpRecordTrace.serialNumber === '') { 347 this.eventSelect!.dataSource([], ''); 348 } 349 }; 350 351 eventSelectClickHandler = (): void => { 352 if (SpRecordTrace.serialNumber === '') { 353 this.eventSelect?.dataSource(eventSelect, ''); 354 } else { 355 if (this.sp!.search) { 356 this.sp!.search = false; 357 this.recordPerfSearch!.clear(); 358 } 359 if (SpRecordTrace.isVscode) { 360 let cmd = Cmd.formatString(CmdConstant.CMD_GET_HIPERF_EVENTS_DEVICES, [SpRecordTrace.serialNumber]); 361 Cmd.execHdcCmd(cmd, (res: string) => { 362 let eventMap = this.parseEvent(res); 363 let eventList = this.getSoftHardWareEvents(eventMap); 364 if (eventList) { 365 for (let eventListElement of eventList) { 366 this.eventData.push(eventListElement.trim()); 367 } 368 } 369 this.eventSelect!.dataSource(this.eventData, ''); 370 }); 371 } else { 372 HdcDeviceManager.connect(SpRecordTrace.serialNumber).then((conn) => { 373 this.eventData = []; 374 if (conn) { 375 HdcDeviceManager.shellResultAsString(CmdConstant.CMD_GET_HIPERF_EVENTS, false).then((res) => { 376 if (res) { 377 let eventMap = this.parseEvent(res); 378 let eventList = this.getSoftHardWareEvents(eventMap); 379 if (eventList) { 380 for (let eventListElement of eventList) { 381 this.eventData.push(eventListElement.trim()); 382 } 383 } 384 this.eventSelect!.dataSource(this.eventData, ''); 385 } 386 }); 387 } else { 388 this.sp!.search = true; 389 this.recordPerfSearch!.clear(); 390 this.recordPerfSearch!.setPercent('please kill other hdc-server !', -2); 391 } 392 }); 393 } 394 } 395 }; 396 397 initElements(): void { 398 this.cpuData = []; 399 this.eventData = []; 400 this.initRecordPerfConfig(); 401 this.sp = document.querySelector('sp-application') as SpApplication; 402 this.recordPerfSearch = this.sp?.shadowRoot?.querySelector('#lit-record-search') as LitSearch; 403 this.processSelect = this.shadowRoot?.querySelector<LitSelectV>("lit-select-v[title='Process']"); 404 this.recordProcessInput = this.processSelect?.shadowRoot?.querySelector<HTMLInputElement>('input'); 405 this.processInput = this.processSelect!.shadowRoot?.querySelector('input') as HTMLInputElement; 406 this.cpuSelect = this.shadowRoot?.querySelector<LitSelectV>("lit-select-v[title='CPU']"); 407 this.inputCpu = this.cpuSelect!.shadowRoot?.querySelector('input') as HTMLInputElement; 408 this.eventSelect = this.shadowRoot?.querySelector<LitSelectV>("lit-select-v[title='Event List']"); 409 this.inputEvent = this.eventSelect!.shadowRoot?.querySelector('input') as HTMLInputElement; 410 this.frequencySetInput = this.shadowRoot?.querySelector<HTMLInputElement>("input[title='Frequency']"); 411 this.frequencySetInput!.onkeydown = (ev): void => { 412 // @ts-ignore 413 if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { 414 ev.preventDefault(); 415 } 416 }; 417 this.offCPUSwitch = this.shadowRoot?.querySelector<LitSwitch>("lit-switch[title='Off CPU']"); 418 this.kernelChainSwitch = this.shadowRoot?.querySelector<LitSwitch>("lit-switch[title='Kernel Chain']"); 419 this.callSelect = this.shadowRoot?.querySelector<LitSelect>("lit-select[title='Call Stack']"); 420 this.addOptionButton!.addEventListener('click', () => { 421 if (!this.startSamp) { 422 return; 423 } 424 this.addOptionButton!.style.display = 'none'; 425 this.show = true; 426 }); 427 this.disable(); 428 } 429 430 private configTypeBySwitch(config: unknown, recordPerfHeadDiv: HTMLDivElement): void { 431 let recordPerfSwitch = document.createElement('lit-switch') as LitSwitch; 432 recordPerfSwitch.className = 'config'; 433 //@ts-ignore 434 recordPerfSwitch.title = config.title; 435 //@ts-ignore 436 recordPerfSwitch.checked = !!config.value; 437 //@ts-ignore 438 if (config.title === 'Start Hiperf Sampling') { 439 recordPerfSwitch.addEventListener('change', (event: CustomEventInit<LitSwitchChangeEvent>) => { 440 let detail = event.detail; 441 if (detail!.checked) { 442 this.startSamp = true; 443 this.unDisable(); 444 this.dispatchEvent(new CustomEvent('addProbe', {})); 445 } else { 446 this.startSamp = false; 447 this.addOptionButton!.style.display = 'unset'; 448 this.disable(); 449 this.show = false; 450 } 451 }); 452 } 453 recordPerfHeadDiv.appendChild(recordPerfSwitch); 454 } 455 456 private configTypeBySelect(config: unknown, recordPerfDiv: HTMLDivElement): void { 457 let recordPerfSelect = ''; 458 recordPerfSelect += `<lit-select rounded="" default-value="" class="record-perf-select config" 459placement="bottom" title="${ 460 //@ts-ignore 461 config.title 462 }" placeholder="${ 463 //@ts-ignore 464 config.selectArray[0] 465 }">`; 466 //@ts-ignore 467 config.selectArray.forEach((value: string) => { 468 recordPerfSelect += `<lit-select-option value="${value}">${value}</lit-select-option>`; 469 }); 470 recordPerfSelect += '</lit-select>'; 471 recordPerfDiv.innerHTML = recordPerfDiv.innerHTML + recordPerfSelect; 472 } 473 474 private configTypeByInput(config: unknown, recordPerfDiv: HTMLDivElement): void { 475 let recordPerfInput = document.createElement('input'); 476 recordPerfInput.className = 'record-perf-input config'; 477 //@ts-ignore 478 recordPerfInput.textContent = config.value; 479 //@ts-ignore 480 recordPerfInput.value = config.value; 481 //@ts-ignore 482 recordPerfInput.title = config.title; 483 recordPerfInput.oninput = (): void => { 484 recordPerfInput.value = recordPerfInput.value.replace(/\D/g, ''); 485 }; 486 recordPerfDiv.appendChild(recordPerfInput); 487 } 488 489 private configTypeByMmapLitSlider(config: unknown, recordPerfDiv: HTMLDivElement): void { 490 //@ts-ignore 491 let defaultValue = Math.pow(2, config.litSliderStyle.defaultValue); 492 let mapsilder = ` 493<div class="sliderBody"><lit-slider defaultColor="var(--dark-color3,#46B1E3)" open dir="right" 494class="silderclass config" title="${ 495 //@ts-ignore 496 config.title 497 }"></lit-slider><input readonly class="sliderInput" 498type="text" value = ' ${defaultValue} ${ 499 //@ts-ignore 500 config.litSliderStyle.resultUnit 501 }' ></div>`; 502 recordPerfDiv.innerHTML = recordPerfDiv.innerHTML + mapsilder; 503 let maplitSlider = recordPerfDiv.querySelector<LitSlider>('.silderclass'); 504 //@ts-ignore 505 maplitSlider!.percent = config.litSliderStyle.defaultValue; 506 let mapsliderBody = recordPerfDiv.querySelector<HTMLDivElement>('.sliderBody'); 507 let mapbufferInput = recordPerfDiv?.querySelector('.sliderInput') as HTMLInputElement; 508 maplitSlider!.addEventListener('input', () => { 509 let percnet = mapsliderBody!.getAttribute('percent'); 510 if (percnet !== null) { 511 //@ts-ignore 512 mapbufferInput.value = Math.pow(2, Number(percnet)) + config.litSliderStyle.resultUnit; 513 } 514 }); 515 //@ts-ignore 516 maplitSlider!.sliderStyle = config.litSliderStyle; 517 } 518 519 private configTypeByLitSlider(config: unknown, recordPerfDiv: HTMLDivElement): void { 520 let sliderEl = ` 521<div class="sliderBody"><lit-slider defaultColor="var(--dark-color3,#46B1E3)" open dir="right" 522class="silderclass config" title="${ 523 //@ts-ignore 524 config.title 525 }"></lit-slider><input readonly class="sliderInput" 526type="text" value = ' ${ 527 //@ts-ignore 528 config.litSliderStyle.defaultValue 529 } ${ 530 //@ts-ignore 531 config.litSliderStyle.resultUnit 532 }' > 533</div>`; 534 recordPerfDiv.innerHTML = recordPerfDiv.innerHTML + sliderEl; 535 let litSlider = recordPerfDiv.querySelector<LitSlider>('.silderclass'); 536 //@ts-ignore 537 litSlider!.percent = config.litSliderStyle.defaultValue; 538 let sliderBody = recordPerfDiv.querySelector<HTMLDivElement>('.sliderBody'); 539 let bufferInput = recordPerfDiv?.querySelector('.sliderInput') as HTMLInputElement; 540 litSlider!.addEventListener('input', () => { 541 //@ts-ignore 542 bufferInput.value = sliderBody!.getAttribute('percent') + config.litSliderStyle.resultUnit; 543 }); 544 //@ts-ignore 545 litSlider!.sliderStyle = config.litSliderStyle; 546 } 547 548 private configTypeBySelectMultiple(config: unknown, recordPerfDiv: HTMLDivElement): void { 549 let html = ''; 550 //@ts-ignore 551 let placeholder = config.selectArray[0]; 552 //@ts-ignore 553 if (config.title === 'Event List') { 554 placeholder = 'NONE'; 555 } 556 html += `<lit-select-v default-value="" rounded="" class="record-perf-select config" 557mode="multiple" canInsert="" title="${ 558 //@ts-ignore 559 config.title 560 }" rounded placement = "bottom" placeholder="${placeholder}">`; 561 //@ts-ignore 562 config.selectArray.forEach((value: string) => { 563 html += `<lit-select-option value="${value}">${value}</lit-select-option>`; 564 }); 565 html += '</lit-select-v>'; 566 recordPerfDiv.innerHTML = recordPerfDiv.innerHTML + html; 567 } 568 569 getSoftHardWareEvents(eventListResult: Map<string, string[]>): string[] { 570 let shEvents = []; 571 let hardwareEvents = eventListResult.get('hardware'); 572 if (hardwareEvents) { 573 for (let hardwareEvent of hardwareEvents) { 574 shEvents.push(hardwareEvent); 575 } 576 } 577 let softwareEvents = eventListResult.get('software'); 578 if (softwareEvents) { 579 for (let softwareEvent of softwareEvents) { 580 shEvents.push(softwareEvent); 581 } 582 } 583 return shEvents; 584 } 585 586 parseEvent(eventListResult: string): Map<string, Array<string>> { 587 let eventMap: Map<string, Array<string>> = new Map<string, Array<string>>(); 588 let events: Array<string> = []; 589 let type: string = ''; 590 let lineValues: string[] = eventListResult.replace(/\r\n/g, '\r').replace(/\n/g, '\r').split(/\r/); 591 for (let line of lineValues) { 592 if (line.startsWith('Supported')) { 593 let startSign: string = 'for'; 594 type = line.substring(line.indexOf(startSign) + startSign.length, line.lastIndexOf(':')).trim(); 595 events = []; 596 eventMap.set(type, events); 597 } else if ( 598 line.indexOf('not support') !== -1 || 599 line.trim().length === 0 || 600 line.indexOf('Text file busy') !== -1 601 ) { 602 // do not need deal with it 603 } else { 604 let event: string = line.split(' ')[0]; 605 let ventMap = eventMap.get(type); 606 if (ventMap !== null) { 607 ventMap!.push(event); 608 } 609 } 610 } 611 return eventMap; 612 } 613 614 private unDisable(): void { 615 if (this.processSelect) { 616 this.processSelect.removeAttribute('disabled'); 617 } 618 if (this.frequencySetInput) { 619 this.frequencySetInput!.disabled = false; 620 } 621 if (this.offCPUSwitch) { 622 this.offCPUSwitch!.disabled = false; 623 } 624 if (this.kernelChainSwitch) { 625 this.kernelChainSwitch!.disabled = false; 626 } 627 if (this.callSelect) { 628 this.callSelect!.removeAttribute('disabled'); 629 } 630 if (this.addOptionButton) { 631 this.addOptionButton.disabled = false; 632 } 633 } 634 635 private disable(): void { 636 if (this.processSelect) { 637 this.processSelect.setAttribute('disabled', ''); 638 } 639 if (this.frequencySetInput) { 640 this.frequencySetInput!.disabled = true; 641 } 642 if (this.offCPUSwitch) { 643 this.offCPUSwitch!.disabled = true; 644 } 645 if (this.kernelChainSwitch) { 646 this.kernelChainSwitch!.disabled = true; 647 } 648 if (this.callSelect) { 649 this.callSelect!.setAttribute('disabled', ''); 650 } 651 if (this.addOptionButton) { 652 this.addOptionButton.disabled = true; 653 } 654 } 655 656 connectedCallback(): void { 657 let traceMode = this.shadowRoot!.querySelector('#traceMode') as HTMLDivElement; 658 let isLongTrace = SpApplication.isLongTrace; 659 if (isLongTrace) { 660 traceMode!.style.display = 'block'; 661 } else { 662 traceMode!.style.display = 'none'; 663 } 664 this.processInput?.addEventListener('mousedown', this.processSelectMousedownHandler); 665 this.inputCpu?.addEventListener('mousedown', this.cpuSelectMouseDownHandler); 666 this.inputCpu?.addEventListener('mouseup', this.cpuSelectMouseUpHandler); 667 this.inputEvent?.addEventListener('mousedown', this.eventSelectMousedownHandler); 668 this.inputEvent?.addEventListener('click', this.eventSelectClickHandler); 669 } 670 671 disconnectedCallback(): void { 672 super.disconnectedCallback(); 673 this.processInput?.removeEventListener('mousedown', this.processSelectMousedownHandler); 674 this.inputCpu?.removeEventListener('mousedown', this.cpuSelectMouseDownHandler); 675 this.inputCpu?.removeEventListener('mouseup', this.cpuSelectMouseUpHandler); 676 this.inputEvent?.removeEventListener('mousedown', this.eventSelectMousedownHandler); 677 this.inputEvent?.removeEventListener('click', this.eventSelectClickHandler); 678 } 679 680 initHtml(): string { 681 return SpRecordPerfHtml; 682 } 683} 684 685export interface PerfConfig { 686 process: string; 687 cpu: string; 688 eventList: string; 689 cpuPercent: number; 690 frequency: number; 691 period: number; 692 isOffCpu: boolean; 693 noInherit: boolean; 694 callStack: string; 695 branch: string; 696 mmap: number; 697 clockType: string; 698 isKernelChain: boolean; 699} 700 701const eventSelect = [ 702 'hw-cpu-cycles', 703 'hw-instructions', 704 'hw-cache-references', 705 'hw-cache-misses', 706 'hw-branch-instructions', 707 'hw-branch-misses', 708 'hw-bus-cycles', 709 'hw-stalled-cycles-backend', 710 'hw-stalled-cycles-frontend', 711 'sw-cpu-clock', 712 'sw-task-clock', 713 'sw-page-faults', 714 'sw-context-switches', 715 'sw-cpu-migrations', 716 'sw-page-faults-min', 717 'sw-page-faults-maj', 718 'sw-alignment-faults', 719 'sw-emulation-faults', 720 'sw-dummy', 721 'sw-bpf-output', 722]; 723 724const perfConfigList = [ 725 { 726 title: 'Start Hiperf Sampling', 727 des: '', 728 hidden: false, 729 type: 'switch', 730 value: false, 731 }, 732 { 733 type: 'select-multiple', 734 title: 'Process', 735 des: 'Record process', 736 hidden: false, 737 selectArray: [''], 738 }, 739 { 740 title: 'CPU', 741 des: 'Record assign cpu num such as 0,1,2', 742 hidden: true, 743 type: 'select-multiple', 744 selectArray: [''], 745 }, 746 { 747 title: 'Event List', 748 des: 'Event type Default is cpu cycles', 749 hidden: true, 750 type: 'select-multiple', 751 selectArray: [''], 752 }, 753 { 754 title: 'CPU Percent', 755 des: 'Set the max percent of cpu time used for recording', 756 hidden: true, 757 type: 'lit-slider', 758 litSliderStyle: { 759 minRange: 0, 760 maxRange: 100, 761 defaultValue: '100', 762 resultUnit: '%', 763 stepSize: 1, 764 lineColor: 'var(--dark-color3,#a88888)', 765 buttonColor: '#a88888', 766 }, 767 }, 768 { 769 title: 'Frequency', 770 des: 'Set event sampling frequency', 771 hidden: false, 772 type: 'input', 773 value: '1000', 774 }, 775 { 776 title: 'Period', 777 des: 'Set event sampling period for trace point events2', 778 hidden: true, 779 type: 'input', 780 value: '1', 781 }, 782 { 783 title: 'Off CPU', 784 des: 'Trace when threads are scheduled off cpu', 785 hidden: false, 786 type: 'switch', 787 value: false, 788 }, 789 { 790 title: 'Kernel Chain', 791 des: '', 792 hidden: false, 793 type: 'switch', 794 value: false, 795 }, 796 { 797 title: 'No Inherit', 798 des: "Don't trace child processes", 799 hidden: true, 800 type: 'switch', 801 value: false, 802 }, 803 { 804 title: 'Call Stack', 805 des: 'Setup and enable call stack recording', 806 hidden: false, 807 type: 'select', 808 selectArray: ['dwarf', 'fp', 'none'], 809 }, 810 { 811 title: 'Branch', 812 des: 'Taken branch stack sampling', 813 hidden: true, 814 type: 'select', 815 selectArray: ['none', 'any', 'any_call', 'any_ret', 'ind_call', 'call', 'user', 'kernel'], 816 }, 817 { 818 title: 'Mmap Pages', 819 des: 'Used to receiving record data from kernel', 820 hidden: true, 821 type: 'Mmap-lit-slider', 822 litSliderStyle: { 823 minRange: 1, 824 maxRange: 10, 825 defaultValue: '8', 826 resultUnit: 'MB', 827 stepSize: 1, 828 lineColor: 'var(--dark-color3,#46B1E3)', 829 buttonColor: '#999999', 830 }, 831 }, 832 { 833 title: 'Clock Type', 834 des: 'Set the clock id to use for the various time fields in the perf_event_type records', 835 hidden: true, 836 type: 'select', 837 selectArray: ['monotonic', 'realtime', 'monotonic_raw', 'boottime', 'perf'], 838 }, 839]; 840