diff --git a/README.md b/README.md index f0fb26f..d8cb9b0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,17 @@ -# PerfSpect · [![Build](https://github.com/intel/PerfSpect/actions/workflows/build.yml/badge.svg)](https://github.com/intel/PerfSpect/actions/workflows/build.yml)[![CodeQL](https://github.com/intel/PerfSpect/actions/workflows/codeql.yml/badge.svg)](https://github.com/intel/PerfSpect/actions/workflows/codeql.yml)[![License](https://img.shields.io/badge/License-BSD--3-blue)](https://github.com/intel/PerfSpect/blob/master/LICENSE) +
-[Quick Start](#quick-start-requires-perf-installed) | [Output](#output) | [Requirements](#requirements) | [Build from source](#build-from-source) +
+ +
+ +[![Build](https://github.com/intel/PerfSpect/actions/workflows/build.yml/badge.svg)](https://github.com/intel/PerfSpect/actions/workflows/build.yml)[![CodeQL](https://github.com/intel/PerfSpect/actions/workflows/codeql.yml/badge.svg)](https://github.com/intel/PerfSpect/actions/workflows/codeql.yml)[![License](https://img.shields.io/badge/License-BSD--3-blue)](https://github.com/intel/PerfSpect/blob/master/LICENSE) + +[![Static Badge](https://img.shields.io/badge/Live_Demo-red?style=for-the-badge)](https://intel.github.io/PerfSpect/) + +[Quick Start](#quick-start-requires-perf-installed) | [Output](#output) | [Deploy in Kubernetes](#deploy-in-kubernetes) | [Requirements](#requirements) | [Build from source](#build-from-source) +
PerfSpect is a system performance characterization tool built on top of linux perf. Most metrics and events come from [perfmon](https://github.com/intel/perfmon) and [TMA v4.5](https://www.intel.com/content/www/us/en/docs/vtune-profiler/cookbook/2023-1/top-down-microarchitecture-analysis-method.html). It contains two parts: @@ -40,8 +51,6 @@ perf-postprocess outputs: 2. `metric_out.sys.csv`: metric values at every 5 second interval 3. `metric_out.html`: html view of a few select metrics -[live example report](https://intel.github.io/PerfSpect/) - ![basic_stats](https://raw.githubusercontent.com/wiki/intel/PerfSpect/newhtml.gif) ## Deploy in Kubernetes diff --git a/_version.txt b/_version.txt index 1892b92..31e5c84 100644 --- a/_version.txt +++ b/_version.txt @@ -1 +1 @@ -1.3.2 +1.3.3 diff --git a/perf-postprocess.py b/perf-postprocess.py index 904f8fa..49360bf 100644 --- a/perf-postprocess.py +++ b/perf-postprocess.py @@ -612,7 +612,9 @@ def generate_metrics_averages( def row(df, name): if name in df.index: - return json.dumps(df.loc[name, :].values.flatten().tolist()) + timeseries = df.loc[[name]].to_dict("split") + timeseries["columns"] = map(lambda x: round(float(x), 1), timeseries["columns"]) + return json.dumps(list(zip(timeseries["columns"], timeseries["data"][0]))) else: return "[]" diff --git a/src/base.html b/src/base.html index 7c58ac1..6aef720 100644 --- a/src/base.html +++ b/src/base.html @@ -34,6 +34,7 @@ createTheme, Typography, Button, + IconButton, ButtonGroup, Slider, Grid, @@ -77,15 +78,7 @@ ].join(","), }, palette: { - primary: { - main: "#556cd6", - }, - secondary: { - main: "#19857b", - }, - error: { - main: colors.red.A400, - }, + mode: 'light', }, }); @@ -159,6 +152,8 @@ function App() { const [systemTabs, setSystemTabs] = React.useState(0); const [openlink, setOpenlink] = React.useState(true); + const [maxdiff, set_maxdiff] = React.useState(0) + const [mindiff, set_mindiff] = React.useState(0) const handleChange = (event, newSystemTabs) => { setSystemTabs(newSystemTabs); @@ -267,11 +262,14 @@ const base_line = { xAxis: { - name: "time (s)" + name: "time (s)", + min: "dataMin", + max: "dataMax", }, yAxis: {}, tooltip: { - trigger: 'axis' + trigger: 'axis', + valueFormatter: (value) => value.toFixed(2), }, legend: {}, } @@ -281,7 +279,7 @@ series: [ { type: 'line', - data: CPUUTIL.map((e, i) => [i * 5, e]), + data: CPUUTIL, } ] } @@ -291,7 +289,7 @@ series: [ { type: 'line', - data: CPIDATA.map((e, i) => [i * 5, e]), + data: CPIDATA, } ] } @@ -301,7 +299,7 @@ series: [ { type: 'line', - data: CPUFREQ.map((e, i) => [i * 5, e]), + data: CPUFREQ, } ] } @@ -311,7 +309,7 @@ series: [ { type: 'line', - data: REMOTENUMA.map((e, i) => [i * 5, e]), + data: REMOTENUMA, } ] } @@ -322,17 +320,17 @@ { name: "L1D", type: 'line', - data: L1DATA.map((e, i) => [i * 5, e]), + data: L1DATA, }, { name: "L2", type: 'line', - data: L2DATA.map((e, i) => [i * 5, e]), + data: L2DATA, }, { name: "LLC Data", type: 'line', - data: LLCDATA.map((e, i) => [i * 5, e]), + data: LLCDATA, }, ] } @@ -343,17 +341,17 @@ { name: "Read", type: 'line', - data: READDATA.map((e, i) => [i * 5, e]), + data: READDATA, }, { name: "Write", type: 'line', - data: WRITEDATA.map((e, i) => [i * 5, e]), + data: WRITEDATA, }, { name: "Total", type: 'line', - data: TOTALDATA.map((e, i) => [i * 5, e]), + data: TOTALDATA, }, ] } @@ -363,7 +361,7 @@ series: [ { type: 'line', - data: PKGPOWER.map((e, i) => [i * 5, e]), + data: PKGPOWER, } ] } @@ -373,27 +371,38 @@ series: [ { type: 'line', - data: DRAMPOWER.map((e, i) => [i * 5, e]), + data: DRAMPOWER, } ] } const diffreport = (e) => { - console.log(e) - var reader = new FileReader(); - + let reader = new FileReader(); reader.onload = (e) => { let new_metrics = JSON.parse(e.target.result.split("\n").filter(e => e.includes("const all_metrics ="))[0].split("const all_metrics =")[1]) let copy = JSON.parse(JSON.stringify(current_metrics)) + let temp_mindiff = 0 + let temp_maxdiff = 0 for (const metric of copy) { for (const other_metric of new_metrics) { if (metric.metrics === other_metric.metrics) { - console.log(metric) - console.log(current_metrics) metric.other = other_metric["0"] + if (other_metric["0"] < metric["0"]) { + metric.diff = ((other_metric["0"] / metric["0"]) - 1) * 100 + } else { + metric.diff = ((metric["0"] / other_metric["0"]) - 1) * -100 + } + if (temp_maxdiff == 0 || temp_maxdiff < metric.diff) { + temp_maxdiff = metric.diff + } + if (temp_mindiff == 0 || temp_mindiff > metric.diff) { + temp_mindiff = metric.diff + } } } } + set_maxdiff(temp_maxdiff) + set_mindiff(temp_mindiff) setCurrent_metrics(copy) }; @@ -413,8 +422,7 @@ onChange={handleChange} variant="scrollable" > - - + @@ -427,7 +435,7 @@ value={systemTabs} index={0} > - + Top-down Microarchitecture Analysis Method (TMAM) @@ -484,27 +492,27 @@ data: [ { name: "Bad Speculation", - value: BADSPECULATION, + value: Math.round(BADSPECULATION * 10) / 10, }, { name: "Retiring", - value: RETIRING, + value: Math.round(RETIRING * 10) / 10, }, { name: "Frontend", - value: FRONTEND, + value: Math.round(FRONTEND * 10) / 10, }, { name: "Backend", - value: BACKEND, + value: Math.round(BACKEND * 10) / 10, children: [ { name: "Core", - value: COREDATA, + value: Math.round(COREDATA * 10) / 10, }, { name: "Memory", - value: MEMORY, + value: Math.round(MEMORY * 10) / 10, }, ], }, @@ -517,18 +525,13 @@ }} /> - - Pressure Stall Information (PSI) - Your workload spent an average of {(PSI_MEM + PSI_CPU + PSI_IO).toFixed(2)}% of time stalled waiting on a hardware resource. + Your workload spent an average of {(PSI_MEM + PSI_CPU + PSI_IO).toFixed(1)}% of time stalled waiting on a hardware resource.
  • @@ -572,28 +575,28 @@ data: [ { name: "CPU stall", - value: PSI_CPU, + value: Math.round(PSI_CPU * 10) / 10, itemStyle: { color: "#ee6666" } }, { name: "Memory stall", - value: PSI_MEM, + value: Math.round(PSI_MEM * 10) / 10, itemStyle: { color: "#fac858" } }, { name: "IO stall", - value: PSI_IO, + value: Math.round(PSI_IO * 10) / 10, itemStyle: { color: "#73c0de" } }, { name: "Not stalled", - value: 100 - (PSI_MEM + PSI_CPU + PSI_IO), + value: Math.round((100 - (PSI_MEM + PSI_CPU + PSI_IO)) * 10) / 10, itemStyle: { color: "#91cc75" } @@ -610,7 +613,7 @@ @@ -632,7 +635,6 @@ {transactions ? "Cycles per transaction retired; indicating how much time each executed transaction took; in units of cycles. Often this metric shows how efficiently applications are using the underlying hardware. A lower \"Cycles per TXN\" could indicate that transactions are not hitting bottlenecks and retiring quickly." : "Cycles per instruction retired; indicating how much time each executed instruction took; in units of cycles. Often this metric shows how efficiently applications are using the underlying hardware. A lower CPI could indicate that instructions are not hitting bottlenecks and retiring quickly."} - @@ -655,7 +657,7 @@ @@ -699,7 +701,7 @@ @@ -730,10 +732,10 @@ - - + +
    Metadata @@ -749,7 +751,9 @@ {row[0]} - {row[1]} + + {row[1]} + ))} @@ -758,16 +762,20 @@ - - -
    + + + TMA metrics are a hierarchy where each sub-metric contains more periods "..." to designate its depth in the tree + + +
    - Value - Metric - {current_metrics[0].hasOwnProperty("other") && Other} + Value + Metric + {current_metrics[0].hasOwnProperty("other") && Other} + {current_metrics[0].hasOwnProperty("other") && Diff} @@ -778,21 +786,24 @@ sx={{ '&:last-child td, &:last-child th': { border: 0 } }} > - - - {row.metrics} - + + {description.hasOwnProperty(row.metrics) && + help + } + {!description.hasOwnProperty(row.metrics) && + help + } + {row.metrics} - - {Number(row["0"]).toFixed(2)} - + {Number(row["0"]).toFixed(1)} - {row.hasOwnProperty("other") && - - {Number(row["other"]).toFixed(2)} - + {row.hasOwnProperty("other") && + {Number(row["other"]).toFixed(1)} + } + {row.hasOwnProperty("other") && 0 ? "rgba(255,0,0," + (row.diff / maxdiff * .5) + ")" : "rgba(0,0,255," + (row.diff / mindiff * .5) + ")") }}> + {Math.round(Number(row["diff"]))}% } ))}