Plotly figures for the web#

Install for this page: export data with pip install scope-profiler; render it in a web project with npm 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.

Gantt — a lane per region and rank
Durations — compare regions between runs
Flame — nested calls
Speedup — region scaling
Duration time series — performance drift
Histogram — call-duration distribution
Rank heatmap — duration by region and rank
Imbalance — per-rank duration
Density — timeline occupancy per region
Call graph — who calls whom
Region summary — the slowest regions in a run

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

buildGanttFigure(payload, { laneBy })

gantt_data.json

Timeline of every call, a lane per region and rank (laneBy: "rank" for one row per rank)

buildFlameFigure(payload)

flame_data.json

Nested call hierarchy

buildDurationsFigure(payload, { metric })

durations_data.json

Per-region duration bars

buildSpeedupFigure(payload)

speedup_data.json

Speedup curve

buildDurationTimeseriesFigure(payload)

duration_timeseries_data.json

Duration drift over time

buildHistogramFigure(payload)

histogram_data.json

Call-duration distribution

buildRankHeatmapFigure(payload)

rank_heatmap_data.json

Rank × region duration matrix

buildImbalanceFigure(payload)

imbalance_data.json

Per-rank duration imbalance

buildDensityFigure(payload)

timeline_density_data.json

Binned timeline occupancy, for traces too large to draw call by call

buildCallgraphFigure(payload)

callgraph_data.json

Sankey call graph, from either callgraph shape

buildRegionSummaryFigure(payload, { metric, topN })

region_statistics.json

The slowest regions of a run, ranked

buildLikwidFigure(payload)

likwid_data.json

One LIKWID hardware-counter metric

buildWeakScalingFigure(payload)

weak_scaling_data.json

Weak-scaling curve

buildScalingEfficiencyFigure(payload)

scaling_efficiency_data.json

Parallel-efficiency curve

buildFigure(payload)

any of the above

Dispatch on the document’s own plot kind

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.