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