• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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