Plotly figures for the web#
Install for this page: export data with
pip install scope-profiler; render it in a web project withnpm install @scope-profiler/plotly plotly.js-dist-min.
@scope-profiler/plotly is the browser-facing companion to
scope-profiler export plot-data --format json. It builds plain Plotly
figure specifications from the exported JSON, without importing Plotly
itself. That makes it suitable for static sites and any JavaScript
framework.
Install#
Install the figure builders plus the Plotly bundle your application wants to use:
npm install @scope-profiler/plotly plotly.js-dist-min
Then fetch a JSON payload and render it with your own Plotly instance:
import Plotly from "plotly.js-dist-min";
import { buildGanttFigure, renderFigure } from "@scope-profiler/plotly";
const payload = await fetch("/figures/gantt_data.json").then((response) => response.json());
const figure = buildGanttFigure(payload);
await renderFigure(Plotly, document.querySelector("#gantt"), figure);
Live examples#
The figures below are built by the published npm package in this page.
Each uses the same shape of payload that
scope-profiler export plot-data --format json writes.
One call for any payload#
buildFigure reads the plot kind stamped on every plot-data document
and picks the builder itself, so a page that renders whatever the
profiler wrote does not need to know which chart it is getting:
import Plotly from "plotly.js-dist-min";
import { buildFigure, renderFigure } from "@scope-profiler/plotly";
for (const name of ["gantt", "durations", "rank_heatmap"]) {
const payload = await fetch(`/figures/${name}_data.json`).then((response) => response.json());
await renderFigure(Plotly, document.querySelector(`#${name}`), buildFigure(payload));
}
It throws on a document that is not scope-profiler-plot-data, and on
one whose format_version is newer than the installed package
understands. For JSON written by a scope-profiler old enough to predate
the envelope, it falls back to inferPlotKind(payload), which reads the
shape of the payload instead; pass { plot: "gantt" } to settle the
case by hand.
Builders#
Builder |
Input payload |
Use case |
|---|---|---|
|
|
Timeline of every call, a lane per region and rank ( |
|
|
Nested call hierarchy |
|
|
Per-region duration bars |
|
|
Speedup curve |
|
|
Duration drift over time |
|
|
Call-duration distribution |
|
|
Rank × region duration matrix |
|
|
Per-rank duration imbalance |
|
|
Binned timeline occupancy, for traces too large to draw call by call |
|
|
Sankey call graph, from either callgraph shape |
|
|
The slowest regions of a run, ranked |
|
|
One LIKWID hardware-counter metric |
|
|
Weak-scaling curve |
|
|
Parallel-efficiency curve |
|
any of the above |
Dispatch on the document’s own |
Use renderFigure(Plotly, element, figure) as a convenience, or pass
figure.data and figure.layout to Plotly.newPlot directly.
Payloads with more than one run#
export plot-data accepts several profiles at once, and every row of
the resulting payload names the run it came from. The builders keep
those runs apart rather than pooling them: the gantt, density and
rank-heatmap charts give each run its own lanes, while the histogram,
imbalance and duration time series give each run its own trace, named
run / region. A region keeps its colour across runs – what changes
between runs is the marker symbol on a line, or the bar pattern on a
histogram – so the same region stays recognisable while the runs stay
distinguishable. Single-run payloads are unaffected: series are named by
region alone, as before.