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"]))}%
}
))}