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