From dc186589cb86ae140b76d43c01d78044e74f9bc5 Mon Sep 17 00:00:00 2001 From: Jonathan Ho <48591478+H01001000@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:13:11 +0800 Subject: [PATCH] feat: add benchmark to site (#2567) * feat: add benchmark to site * test * remove test file --- .github/workflows/commentBenchResult.yml | 3 +- site/docs/benchmark.mdx | 9 ++ site/docusaurus.config.js | 4 +- site/package-lock.json | 90 +++++++++++ site/package.json | 2 + site/src/components/BenchmarkResultCharts.jsx | 147 ++++++++++++++++++ 6 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 site/docs/benchmark.mdx create mode 100644 site/src/components/BenchmarkResultCharts.jsx diff --git a/.github/workflows/commentBenchResult.yml b/.github/workflows/commentBenchResult.yml index 9d374c14e..b50bad0e2 100644 --- a/.github/workflows/commentBenchResult.yml +++ b/.github/workflows/commentBenchResult.yml @@ -80,6 +80,7 @@ jobs: const fs = require('fs'); const commit_sha = fs.readFileSync('./sha', 'utf-8'); const repo = fs.readFileSync('./repo', 'utf-8'); + if (repo.split('/')[1] === undefined) process.exit(0) const pr = await github.rest.repos.listPullRequestsAssociatedWithCommit({ commit_sha: commit_sha.slice(0,-1), owner: repo.split('/')[0], @@ -88,7 +89,7 @@ jobs: if (pr.data[0]) { github.rest.issues.createComment({ issue_number: pr.data[0].number, - owner: repo.split('/')[0], + owner: "discordeno", repo: "discordeno", body: `${{ env.MESSAGE }}` }) diff --git a/site/docs/benchmark.mdx b/site/docs/benchmark.mdx new file mode 100644 index 000000000..0b4d9c774 --- /dev/null +++ b/site/docs/benchmark.mdx @@ -0,0 +1,9 @@ +--- +sidebar_position: 5 +--- + +# Benchmark + +import BenchmarkResultCharts from '@site/src/components/BenchmarkResultCharts' + + \ No newline at end of file diff --git a/site/docusaurus.config.js b/site/docusaurus.config.js index f310ec6e0..1ee49127b 100644 --- a/site/docusaurus.config.js +++ b/site/docusaurus.config.js @@ -52,7 +52,7 @@ const config = { type: "doc", docId: "intro", position: "left", - label: "Tutorial", + label: "Docs", }, { to: "/blog", label: "Blog", position: "left" }, { @@ -69,7 +69,7 @@ const config = { title: "Docs", items: [ { - label: "Tutorial", + label: "Docs", to: "/docs/intro", }, ], diff --git a/site/package-lock.json b/site/package-lock.json index 1785fdf1e..9199d82f7 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -13,9 +13,11 @@ "@docusaurus/preset-classic": "2.0.0-beta.15", "@easyops-cn/docusaurus-search-local": "^0.21.4", "@mdx-js/react": "^1.6.21", + "chart.js": "^2.9.4", "clsx": "^1.1.1", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", + "react-chartjs-2": "^2.11.2", "react-dom": "^17.0.1" }, "devDependencies": { @@ -4359,6 +4361,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chart.js": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", + "dependencies": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "node_modules/chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "dependencies": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "node_modules/chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "dependencies": { + "color-name": "^1.0.0" + } + }, "node_modules/cheerio": { "version": "1.0.0-rc.10", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", @@ -8197,6 +8225,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, "node_modules/mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -9625,6 +9661,20 @@ "pure-color": "^1.2.0" } }, + "node_modules/react-chartjs-2": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.11.2.tgz", + "integrity": "sha512-hcPS9vmRJeAALPPf0uo02BiD8BDm0HNmneJYTZVR74UKprXOpql+Jy1rVuj93rKw0Jfx77mkcRfXPxTe5K83uw==", + "dependencies": { + "lodash": "^4.17.19", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "chart.js": "^2.3", + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0", + "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/react-dev-utils": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz", @@ -16089,6 +16139,32 @@ "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==" }, + "chart.js": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz", + "integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==", + "requires": { + "chartjs-color": "^2.1.0", + "moment": "^2.10.2" + } + }, + "chartjs-color": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz", + "integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==", + "requires": { + "chartjs-color-string": "^0.6.0", + "color-convert": "^1.9.3" + } + }, + "chartjs-color-string": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz", + "integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==", + "requires": { + "color-name": "^1.0.0" + } + }, "cheerio": { "version": "1.0.0-rc.10", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", @@ -18878,6 +18954,11 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, "mrmime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.0.tgz", @@ -19851,6 +19932,15 @@ "pure-color": "^1.2.0" } }, + "react-chartjs-2": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-2.11.2.tgz", + "integrity": "sha512-hcPS9vmRJeAALPPf0uo02BiD8BDm0HNmneJYTZVR74UKprXOpql+Jy1rVuj93rKw0Jfx77mkcRfXPxTe5K83uw==", + "requires": { + "lodash": "^4.17.19", + "prop-types": "^15.7.2" + } + }, "react-dev-utils": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz", diff --git a/site/package.json b/site/package.json index 1855464de..32aee7880 100644 --- a/site/package.json +++ b/site/package.json @@ -20,9 +20,11 @@ "@docusaurus/preset-classic": "2.0.0-beta.15", "@easyops-cn/docusaurus-search-local": "^0.21.4", "@mdx-js/react": "^1.6.21", + "chart.js": "^2.9.4", "clsx": "^1.1.1", "prism-react-renderer": "^1.2.1", "react": "^17.0.1", + "react-chartjs-2": "^2.11.2", "react-dom": "^17.0.1" }, "devDependencies": { diff --git a/site/src/components/BenchmarkResultCharts.jsx b/site/src/components/BenchmarkResultCharts.jsx new file mode 100644 index 000000000..ef040f82a --- /dev/null +++ b/site/src/components/BenchmarkResultCharts.jsx @@ -0,0 +1,147 @@ +import { useColorMode } from "@docusaurus/theme-common"; +import React, { useEffect, useState } from "react"; +import { Line } from "react-chartjs-2"; +// Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml +const toolColors = { + cargo: "#dea584", + go: "#00add8", + benchmarkjs: "#f1e05a", + benchmarkluau: "#000080", + pytest: "#3572a5", + googlecpp: "#f34b7d", + catch2: "#f34b7d", + julia: "#a270ba", + benchmarkdotnet: "#178600", + customBiggerIsBetter: "#38ff38", + customSmallerIsBetter: "#ff3838", + _: "#333333", +}; + +const BenchmarkResultChart = ({ name, dataset, theme }) => { + const color = toolColors[dataset.length > 0 ? dataset[0].tool : "_"]; + const data = { + labels: dataset.map((d) => d.commit.id.slice(0, 7)), + datasets: [ + { + label: name, + data: dataset.map((d) => d.bench.value), + borderColor: color, + backgroundColor: color + "60", // Add alpha for #rrggbbaa + }, + ], + }; + const options = { + scales: { + xAxes: [ + { + scaleLabel: { + display: true, + labelString: "commit", + }, + }, + ], + yAxes: [ + { + scaleLabel: { + display: true, + labelString: dataset.length > 0 ? dataset[0].bench.unit : "", + }, + ticks: { + beginAtZero: true, + }, + }, + ], + legend: { + labels: { + // This more specific font property overrides the global property + defaultFontColor: theme === "light" ? "#000000" : "#FFFFFF", + }, + }, + }, + tooltips: { + callbacks: { + afterTitle: (items) => { + const { index } = items[0]; + const data = dataset[index]; + return "\n" + data.commit.message + "\n\n" + data.commit.timestamp + " committed by @" + + data.commit.committer.username + "\n"; + }, + label: (item) => { + let label = item.value; + const { range, unit } = dataset[item.index].bench; + label += " " + unit; + if (range) { + label += " (" + range + ")"; + } + return label; + }, + afterLabel: (item) => { + const { extra } = dataset[item.index].bench; + return extra ? "\n" + extra : ""; + }, + }, + }, + onClick: (_mouseEvent, activeElems) => { + if (activeElems.length === 0) { + return; + } + // XXX: Undocumented. How can we know the index? + const index = activeElems[0]._index; + const url = dataset[index].commit.url; + window.open(url, "_blank"); + }, + }; + // console.log(theme); + return ; +}; + +export default function BenchmarkResultCharts() { + const { colorMode } = useColorMode(); + const [data, setData] = useState(); + + useEffect(async () => { + if (!data) { + setData( + JSON.parse( + (await (await fetch( + "https://raw.githubusercontent.com/discordeno/discordeno/benchies/benchmarksResult/data.js", + )).text()).slice(24), + ), + ); + } + }, []); + + function collectBenchesPerTestCase(entries) { + const dataMap = new Map(); + for (const entry of entries) { + const { commit, date, tool, benches } = entry; + for (const bench of benches) { + const result = { commit, date, tool, bench }; + const arr = dataMap.get(bench.name); + if (arr === undefined) { + dataMap.set(bench.name, [result]); + } else { + arr.push(result); + } + } + } + return dataMap; + } + + return (data + ? Array.from( + collectBenchesPerTestCase(data.entries.Benchmark), + ([key, value]) => ({ benchName: key, benches: value }), + ).map(( + bench, + index, + ) => ( + + )) + : <>); +}