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