From 251c4d2d8a73149282f4466084c2aa8ef770b5c4 Mon Sep 17 00:00:00 2001 From: Daniil Zhuravlev Date: Thu, 7 Mar 2024 01:24:14 +0400 Subject: [PATCH 1/5] refactor(web): replace plotly with chart.js --- push_results.sh | 4 +- webdriver-ts-results/package-lock.json | 40 +++++++-- webdriver-ts-results/package.json | 3 +- .../BoxPlotTable/BoxPlotTableChart.tsx | 83 +++++++++++++------ .../components/ResultTable/ResultTable.tsx | 2 +- webdriver-ts-results/vite.config.ts | 2 +- 6 files changed, 99 insertions(+), 35 deletions(-) diff --git a/push_results.sh b/push_results.sh index 75873a1f1..b27dc1a7d 100755 --- a/push_results.sh +++ b/push_results.sh @@ -1,12 +1,12 @@ cp webdriver-ts-results/dist/index.html ../krausest.github.io/js-framework-benchmark/current.html cp webdriver-ts-results/dist/BoxPlotTable*.js ../krausest.github.io/js-framework-benchmark/ -cp webdriver-ts-results/dist/plotly*.js ../krausest.github.io/js-framework-benchmark/ +cp webdriver-ts-results/dist/chartjs*.js ../krausest.github.io/js-framework-benchmark/ cp webdriver-ts-results/dist/index*.css ../krausest.github.io/js-framework-benchmark/ cp webdriver-ts-results/dist/index*.js ../krausest.github.io/js-framework-benchmark/ cd ../krausest.github.io git add js-framework-benchmark/current.html git add js-framework-benchmark/BoxPlotTable*.js -git add js-framework-benchmark/plotly*.js +git add js-framework-benchmark/chartjs*.js git add js-framework-benchmark/index*.css git add js-framework-benchmark/index*.js git commit -m "update results" diff --git a/webdriver-ts-results/package-lock.json b/webdriver-ts-results/package-lock.json index 082536692..d0b84d682 100644 --- a/webdriver-ts-results/package-lock.json +++ b/webdriver-ts-results/package-lock.json @@ -8,10 +8,11 @@ "name": "webdriver-ts-results", "version": "0.1.0", "dependencies": { + "@sgratzl/chartjs-chart-boxplot": "^4.2.8", "antd": "^5.14.2", + "chart.js": "^4.4.2", "jstat": "^1.9.6", "lucide-react": "^0.344.0", - "plotly.js-cartesian-dist": "2.18.2", "react": "^18.2.0", "react-dom": "^18.2.0", "zustand": "^4.4.1" @@ -860,6 +861,11 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@rc-component/color-picker": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.2.tgz", @@ -1128,6 +1134,22 @@ "win32" ] }, + "node_modules/@sgratzl/boxplots": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sgratzl/boxplots/-/boxplots-1.3.0.tgz", + "integrity": "sha512-2BRWv+WOH58pwzSgP50buoXgxQic+4auz3BF0wiIUXS8D3QGkdBNgsNdQO1754Tm/0uEwly0R3WaCiGnoYWcmA==" + }, + "node_modules/@sgratzl/chartjs-chart-boxplot": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/@sgratzl/chartjs-chart-boxplot/-/chartjs-chart-boxplot-4.2.8.tgz", + "integrity": "sha512-D4GNB4H1WVqJuvVgATj6GZzDbAKLNIaRGzUNa16+a0QjhiATBm05OfaQM1m9kRUuXs2Hmufi2v8IbHKhAQFALg==", + "dependencies": { + "@sgratzl/boxplots": "^1.3.0" + }, + "peerDependencies": { + "chart.js": "^4.1.1" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1376,6 +1398,17 @@ "node": ">=4" } }, + "node_modules/chart.js": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.2.tgz", + "integrity": "sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, "node_modules/classnames": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", @@ -1656,11 +1689,6 @@ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", "dev": true }, - "node_modules/plotly.js-cartesian-dist": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/plotly.js-cartesian-dist/-/plotly.js-cartesian-dist-2.18.2.tgz", - "integrity": "sha512-cKdcEoDbqgAAFI0k7MdbaS2Gmp+301RhOqO6yxptYgwrhcqDRxB0x81TLPUmmUewo5d0UTF+JNg+BL+JZVs6pQ==" - }, "node_modules/postcss": { "version": "8.4.31", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", diff --git a/webdriver-ts-results/package.json b/webdriver-ts-results/package.json index 6417ccf9b..660608ff8 100644 --- a/webdriver-ts-results/package.json +++ b/webdriver-ts-results/package.json @@ -4,10 +4,11 @@ "private": true, "type": "module", "dependencies": { + "@sgratzl/chartjs-chart-boxplot": "^4.2.8", "antd": "^5.14.2", + "chart.js": "^4.4.2", "jstat": "^1.9.6", "lucide-react": "^0.344.0", - "plotly.js-cartesian-dist": "2.18.2", "react": "^18.2.0", "react-dom": "^18.2.0", "zustand": "^4.4.1" diff --git a/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTableChart.tsx b/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTableChart.tsx index 318ec1159..148442fe5 100644 --- a/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTableChart.tsx +++ b/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTableChart.tsx @@ -1,5 +1,20 @@ import { useRef, useEffect } from "react"; -import Plotly from "plotly.js-cartesian-dist"; +import { BoxPlotChart } from "@sgratzl/chartjs-chart-boxplot"; +import { Chart, ChartConfiguration } from "chart.js"; + +Chart.register(BoxPlotChart); + +const backgroundColor = [ + "hsl(0 80% 50%)", // Red + "hsl(40 80% 50%)", // Orange + "hsl(80 80% 50%)", // Yellow + "hsl(120 80% 50%)", // Green + "hsl(160 80% 50%)", // Cyan + "hsl(200 80% 50%)", // Blue + "hsl(240 80% 50%)", // Purple + "hsl(280 80% 50%)", // Magenta + "hsl(320 80% 50%)", // Pink +]; interface BoxPlotData { framework: string; @@ -11,34 +26,54 @@ interface Props { } const BoxPlotTableChart = ({ traces }: Props) => { - const elemRef = useRef(null); + const chartRef = useRef(null); useEffect(() => { - const plotlTtraces = traces.map((t) => ({ - type: "box", - y: t.values, - boxpoints: false, - jitter: 0.5, - name: t.framework, - boxmean: "sd", - })); - - const layout = { - showlegend: false, - margin: { - l: 40, - r: 0, - b: 120, - t: 0, - pad: 0, + const labels: string[] = []; + const data: number[][] = []; + + for (const trace of traces) { + labels.push(trace.framework); + data.push(trace.values); + } + + const config: ChartConfiguration<"boxplot"> = { + type: "boxplot", + data: { + labels, + datasets: [ + { + backgroundColor, + data, + }, + ], + }, + options: { + scales: { + x: { + grid: { + display: false, + }, + }, + y: { + beginAtZero: false, + }, + }, }, }; - Plotly.newPlot(elemRef.current, plotlTtraces, layout, { - staticPlot: true, - editable: false, - }); + + const chart = new BoxPlotChart(chartRef.current!, config); + + return () => { + chart.destroy(); + }; }, [traces]); - return
; + + return ( +
+ +
+ ); }; export default BoxPlotTableChart; diff --git a/webdriver-ts-results/src/components/ResultTable/ResultTable.tsx b/webdriver-ts-results/src/components/ResultTable/ResultTable.tsx index 15c2514c8..d6b068959 100644 --- a/webdriver-ts-results/src/components/ResultTable/ResultTable.tsx +++ b/webdriver-ts-results/src/components/ResultTable/ResultTable.tsx @@ -7,7 +7,7 @@ import { benchmarks } from "@/results"; import { useRootStore } from "@/reducer"; import SizeResultsTable from "@/components/tables/SizeResultsTable"; -const BoxPlotTable = React.lazy(() => import("@/components/BoxPlotTable")); +const BoxPlotTable = React.lazy(() => import("@/components/BoxPlotTable/BoxPlotTable")); interface Props { type: FrameworkType; diff --git a/webdriver-ts-results/vite.config.ts b/webdriver-ts-results/vite.config.ts index 7c63c564c..1e65bad8f 100644 --- a/webdriver-ts-results/vite.config.ts +++ b/webdriver-ts-results/vite.config.ts @@ -10,7 +10,7 @@ export default defineConfig({ rollupOptions: { output: { manualChunks: { - plotly: ["plotly.js-cartesian-dist"], + chartjs: ["chart.js", "@sgratzl/chartjs-chart-boxplot"], }, }, }, From 1e2680fc8b042b5539470deb878546c0cc115786 Mon Sep 17 00:00:00 2001 From: Daniil Zhuravlev Date: Thu, 7 Mar 2024 01:29:31 +0400 Subject: [PATCH 2/5] style: format code --- .../components/BoxPlotTable/BoxPlotTable.tsx | 21 +-- .../BoxPlotTable/BoxPlotTableRow.tsx | 16 +- .../BoxPlotTable/BoxPlotTableRows.tsx | 9 +- .../src/components/tables/CompareRow.tsx | 13 +- .../src/components/tables/CpuResultsTable.tsx | 175 ++++++++---------- .../src/components/tables/GeomMeanRow.tsx | 21 +-- .../src/components/tables/MemResultsTable.tsx | 13 +- .../components/tables/SizeResultsTable.tsx | 13 +- .../src/components/tables/ValueResultRow.tsx | 18 +- 9 files changed, 119 insertions(+), 180 deletions(-) diff --git a/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTable.tsx b/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTable.tsx index 39152b880..c51bf8185 100644 --- a/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTable.tsx +++ b/webdriver-ts-results/src/components/BoxPlotTable/BoxPlotTable.tsx @@ -1,11 +1,5 @@ import React from "react"; -import { - SORT_BY_NAME, - Benchmark, - Framework, - ResultLookup, - CpuDurationMode, -} from "@/Common"; +import { SORT_BY_NAME, Benchmark, Framework, ResultLookup, CpuDurationMode } from "@/Common"; import BoxPlotTableRows from "./BoxPlotTableRows"; interface Props { @@ -17,14 +11,7 @@ interface Props { cpuDurationMode: CpuDurationMode; } -const BoxPlotTable = ({ - frameworks, - benchmarks, - results, - currentSortKey, - sortBy, - cpuDurationMode, -}: Props) => { +const BoxPlotTable = ({ frameworks, benchmarks, results, currentSortKey, sortBy, cpuDurationMode }: Props) => { const handleSortByName = (event: React.MouseEvent) => { event.preventDefault(); sortBy(SORT_BY_NAME); @@ -39,9 +26,7 @@ const BoxPlotTable = ({ @@ -49,9 +44,7 @@ const CompareRow = ({ comparison, compareWith }: Props) => { return ( - - compare: Green means significantly faster, red significantly slower - + compare: Green means significantly faster, red significantly slower {comparison.map((result, idx) => renderComparisonCell(result, idx))} ); diff --git a/webdriver-ts-results/src/components/tables/CpuResultsTable.tsx b/webdriver-ts-results/src/components/tables/CpuResultsTable.tsx index 529a9648b..260e6d3c8 100644 --- a/webdriver-ts-results/src/components/tables/CpuResultsTable.tsx +++ b/webdriver-ts-results/src/components/tables/CpuResultsTable.tsx @@ -1,10 +1,5 @@ import React from "react"; -import { - ResultTableData, - SORT_BY_NAME, - SORT_BY_GEOMMEAN_CPU, - BenchmarkType, -} from "@/Common"; +import { ResultTableData, SORT_BY_NAME, SORT_BY_GEOMMEAN_CPU, BenchmarkType } from "@/Common"; import GeomMeanRow from "./GeomMeanRow"; import CompareRow from "./CompareRow"; import ValueResultRow from "./ValueResultRow"; @@ -25,7 +20,7 @@ const CpuResultsTable = ({ data, currentSortKey, sortBy }: Props) => { return resultsCPU.results.length === 0 ? null : ( <> - {/* Dummy row for fixed td width */} + {/* Dummy row for fixed td width */} @@ -41,95 +36,83 @@ const CpuResultsTable = ({ data, currentSortKey, sortBy }: Props) => { - - - - -
- Duration for... - - {data.frameworks.map((f, idx) => ( - - {f.frameworkHomeURL ? ( - - {f.displayname} - - ) : ( - f.displayname - )} - - ))} - - - - - Implementation notes - {data.frameworks.map((f) => ( - - {f.issues && - f.issues.map((i) => ( - - {i.toFixed()} - - - ))} - - ))} - - - - - Implementation link - {data.frameworks.map((f) => ( - - - code - - - ))} - - - - {resultsCPU.results.map((resultsForBenchmark, benchIdx) => ( - - ))} - - - + + + + +
+ Duration for... + + {data.frameworks.map((f, idx) => ( + + {f.frameworkHomeURL ? ( + + {f.displayname} + + ) : ( + f.displayname + )} + + ))} + + + + + Implementation notes + {data.frameworks.map((f) => ( + + {f.issues && + f.issues.map((i) => ( + + {i.toFixed()} + + + ))} + + ))} + + + + + Implementation link + {data.frameworks.map((f) => ( + + + code + + + ))} + + + + {resultsCPU.results.map((resultsForBenchmark, benchIdx) => ( + + ))} + + + ); }; diff --git a/webdriver-ts-results/src/components/tables/GeomMeanRow.tsx b/webdriver-ts-results/src/components/tables/GeomMeanRow.tsx index f9508733f..b7e0e685b 100644 --- a/webdriver-ts-results/src/components/tables/GeomMeanRow.tsx +++ b/webdriver-ts-results/src/components/tables/GeomMeanRow.tsx @@ -9,13 +9,7 @@ interface Props { sortbyGeommeanEnum: T_SORT_BY_GEOMMEAN; } -const GeomMeanRow = ({ - weighted, - geomMean, - currentSortKey, - sortBy, - sortbyGeommeanEnum, -}: Props) => { +const GeomMeanRow = ({ weighted, geomMean, currentSortKey, sortBy, sortbyGeommeanEnum }: Props) => { const handleSort = (sortValue: string) => (event: React.SyntheticEvent) => { event.preventDefault(); sortBy(sortValue); @@ -25,12 +19,10 @@ const GeomMeanRow = ({ of all factors in the table @@ -38,13 +30,10 @@ const GeomMeanRow = ({ result == null ? ( ) : ( - + {result.mean.toFixed(2)} - ), + ) )} ); diff --git a/webdriver-ts-results/src/components/tables/MemResultsTable.tsx b/webdriver-ts-results/src/components/tables/MemResultsTable.tsx index ea2f4c001..34d6441bb 100644 --- a/webdriver-ts-results/src/components/tables/MemResultsTable.tsx +++ b/webdriver-ts-results/src/components/tables/MemResultsTable.tsx @@ -29,7 +29,10 @@ const MemResultsTable = ({ data, currentSortKey, sortBy }: Props) => { - @@ -49,7 +52,13 @@ const MemResultsTable = ({ data, currentSortKey, sortBy }: Props) => { sortBy={sortBy} /> ))} - + ); diff --git a/webdriver-ts-results/src/components/tables/SizeResultsTable.tsx b/webdriver-ts-results/src/components/tables/SizeResultsTable.tsx index cfafb42b0..1cb853eeb 100644 --- a/webdriver-ts-results/src/components/tables/SizeResultsTable.tsx +++ b/webdriver-ts-results/src/components/tables/SizeResultsTable.tsx @@ -29,7 +29,10 @@ const SizeResultsTable = ({ data, currentSortKey, sortBy }: Props) => { - @@ -49,7 +52,13 @@ const SizeResultsTable = ({ data, currentSortKey, sortBy }: Props) => { sortBy={sortBy} /> ))} - + ); diff --git a/webdriver-ts-results/src/components/tables/ValueResultRow.tsx b/webdriver-ts-results/src/components/tables/ValueResultRow.tsx index 8d7db3151..6523dd994 100644 --- a/webdriver-ts-results/src/components/tables/ValueResultRow.tsx +++ b/webdriver-ts-results/src/components/tables/ValueResultRow.tsx @@ -10,13 +10,7 @@ interface Props { sortBy: (name: string) => void; } -const ValueResultRow = ({ - benchIdx, - resultsForBenchmark, - benchmarks, - currentSortKey, - sortBy, -}: Props) => { +const ValueResultRow = ({ benchIdx, resultsForBenchmark, benchmarks, currentSortKey, sortBy }: Props) => { const handleSort = (sortValue: string) => (event: React.SyntheticEvent) => { event.preventDefault(); sortBy(sortValue); @@ -26,9 +20,7 @@ const ValueResultRow = ({