# HG changeset patch # User Raphaël Gomès <rgomes@octobus.net> # Date 1657215875 -7200 # Thu Jul 07 19:44:35 2022 +0200 # Node ID 200951f8524902bd69f4b0f3c3227ffd53fd277d # Parent 2396316c0f7a786b4ff973405dd19bcc162ab4e5 web-ui: start merging graphs diff --git a/web-ui/src/App.svelte b/web-ui/src/App.svelte --- a/web-ui/src/App.svelte +++ b/web-ui/src/App.svelte @@ -7,12 +7,12 @@ <main> <h1>Poulpe!</h1> - {#each Object.entries(results) as [name, branches]} + {#each Object.entries(results) as [name, variants]} <h2>{name}</h2> - {#each Object.entries(branches) as [branchName, variants]} - <h3>Branch: {branchName}</h3> - {#each Object.entries(variants) as [variant, data]} - <h3>Variant: {variant}</h3> + {#each Object.entries(variants) as [variantName, branches]} + <h3>Variant: {variantName}</h3> + {#each Object.entries(branches) as [branchName, data]} + <h3>Branch: {branchName}</h3> <Benchmark {data} /> {/each} {/each} diff --git a/web-ui/src/config.ts b/web-ui/src/config.ts new file mode 100644 --- /dev/null +++ b/web-ui/src/config.ts @@ -0,0 +1,54 @@ +export const COLORS = [ + "#FF6633", + "#FFB399", + "#FF33FF", + "#00B3E6", + "#1AB399", + "#E6B333", + "#3366E6", + "#999966", + "#B34D4D", + "#80B300", + "#809900", + "#6680B3", + "#FF1A66", + "#66991A", + "#FF99E6", + "#CCFF1A", + "#33FFCC", + "#66994D", + "#E6331A", + "#B366CC", + "#99FF99", + "#E6B3B3", + "#4D8000", + "#B33300", + "#CC80CC", + "#66664D", + "#991AFF", + "#E666FF", + "#4DB3FF", + "#E666B3", + "#33991A", + "#CC9999", + "#B3B31A", + "#00E680", + "#4D8066", + "#809980", + "#E6FF80", + "#1AFF33", + "#999933", + "#FF3380", + "#CCCC00", + "#66E64D", + "#4D80CC", + "#9900B3", + "#FFFF99", + "#E64D66", + "#4DB380", + "#FF4D4D", + "#99E6E6", + "#6666FF", + ]; + +export const GRAPH_SIZE = 400; \ No newline at end of file diff --git a/web-ui/src/lib/Benchmark.svelte b/web-ui/src/lib/Benchmark.svelte --- a/web-ui/src/lib/Benchmark.svelte +++ b/web-ui/src/lib/Benchmark.svelte @@ -6,9 +6,7 @@ <div class="benchmark"> <div class="graphs"> - {#each Object.entries(data) as graph_data} - <Graph data={graph_data} /> - {/each} + <Graph {data} /> </div> </div> @@ -16,6 +14,8 @@ .graphs { display: grid; gap: 1.5rem; - grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(500px, max-content)); + justify-content: center; + align-content: center; } </style> diff --git a/web-ui/src/lib/Graph.svelte b/web-ui/src/lib/Graph.svelte --- a/web-ui/src/lib/Graph.svelte +++ b/web-ui/src/lib/Graph.svelte @@ -1,53 +1,52 @@ <script lang="ts"> import Chart from "chart.js/auto"; + import nodemap from "../../../mercurial-mapping.json"; import { onMount } from "svelte"; - export let data = [ - "mozilla-dirstate-v1", - [ - { - "bin-env-vars": { - hg: { - version: "4.8.2+1-7354292899eb", - changeset: { - node: "7354292899ebc84f9b0bb840ad4cad14545bc798", - }, - }, - }, - result: { - time: { - median: 3.69134702416, - }, - }, - }, - ], - ]; + import { COLORS } from "../config.js"; + import { getNodeForResult, sortVersions } from "../utils"; + + export let data; let myChart; onMount(() => { const ctx = myChart.getContext("2d"); const datasets = []; + const labels = new Set(); - const [repoName, results] = data; - let graphData = []; - for (let result of results) { - graphData.push({ - x: result["bin-env-vars"]["hg"]["version"].split("+")[0], - y: result["result"]["time"]["median"], - node: result["bin-env-vars"]["hg"]["changeset"]["node"], + for (const [index, [repoVariant, results]] of Object.entries( + data + ).entries()) { + const graphData = []; + const sorted = [...results].sort((a, b) => { + const nodeA = nodemap[getNodeForResult(a)]; + const nodeB = nodemap[getNodeForResult(b)]; + return nodeA - nodeB; + }); + for (const result of sorted) { + const label = result["bin-env-vars"]["hg"]["version"].split("+")[0]; + graphData.push({ + x: label, + y: result["result"]["time"]["median"], + node: getNodeForResult(result), + }); + labels.add(label); + } + datasets.push({ + label: repoVariant, + data: graphData, + backgroundColor: COLORS[index], + borderColor: COLORS[index], + borderWidth: 1, }); } - datasets.push({ - label: repoName, - data: graphData, - backgroundColor: "rgba(255, 99, 132, 0.2)", - borderColor: "rgba(255, 99, 132, 1)", - borderWidth: 1, - }); + const sortedLabels = Array.from(labels); + sortedLabels.sort(sortVersions); new Chart(ctx, { type: "line", data: { + labels: sortedLabels, datasets: datasets, }, options: { diff --git a/web-ui/src/utils.ts b/web-ui/src/utils.ts new file mode 100644 --- /dev/null +++ b/web-ui/src/utils.ts @@ -0,0 +1,57 @@ +/** + * return a sortable key for a given Mercurial version + */ +export const parseVersion = (version: string): Array<number> => { + let v_parts: string; + let rank_s: string; + if (version.includes("+")) { + let [first, ...rest] = version.split("+"); + v_parts = first; + rank_s = version.slice(first.length + 1); + } else { + v_parts = version; + rank_s = "0"; + } + + let rc = "100"; + const pieces = []; + if (v_parts.includes("rc")) { + let [first, ...rest] = version.split("rc", 1); + v_parts = first; + rc = version.slice(first.length + 2); + } + + const v = v_parts.split("."); + pieces.push(...v.map((part: string) => parseInt(part, 10))); + while (pieces.length < 3) { + pieces.push(0); + } + pieces.push(parseInt(rc, 10)); + + rank_s = rank_s.split(".")[0]; + rank_s = rank_s.split("-")[0]; + + if (rank_s.includes("hg")) { + rank_s = rank_s.slice(rank_s.split("hg", 1)[0].length + 2); + } + pieces.push(parseInt(rank_s, 10)); + return pieces; +}; + +export const sortVersions = (a: string, b: string): number => { + const versionA = parseVersion(a); + const versionB = parseVersion(b); + + for (const [index, num] of Object.entries(versionA)) { + if (num < versionB[index]) { + return -1; + } else if (num > versionB[index]) { + return 1; + } + } + return 0; +}; + +export const getNodeForResult = (result) => { + return result["bin-env-vars"]["hg"]["changeset"]["node"]; +}; \ No newline at end of file