concept-collection / benchcompress
update web-ui
Jeremy Magland <jmagland@flatironinstitute.org> committed commit 7ccd097c2039 parent bb5262d Browse files
5 changed files+3498−68
README.mdmodified+2−0View file
@@ -1,3 +1,5 @@
11 # zia
22
33 Benchmarking compression of integer arrays
4+
5+Benchmark results: https://magland.github.io/zia/
web-ui/package-lock.jsonmodified+3362−61View file
This diff is 4,119 lines long and is not shown.
web-ui/package.jsonmodified+5−1View file
@@ -11,14 +11,18 @@
1111 },
1212 "dependencies": {
1313 "@tanstack/react-table": "^8.20.6",
14+ "@types/plotly.js": "^2.35.2",
1415 "axios": "^1.7.9",
16+ "plotly.js-dist-min": "^2.35.3",
1517 "react": "^18.3.1",
16- "react-dom": "^18.3.1"
18+ "react-dom": "^18.3.1",
19+ "react-plotly.js": "^2.6.0"
1720 },
1821 "devDependencies": {
1922 "@eslint/js": "^9.17.0",
2023 "@types/react": "^18.3.18",
2124 "@types/react-dom": "^18.3.5",
25+ "@types/react-plotly.js": "^2.6.3",
2226 "@vitejs/plugin-react": "^4.3.4",
2327 "autoprefixer": "^10.4.20",
2428 "eslint": "^9.17.0",
web-ui/src/components/BenchmarkTable.tsxmodified+128−3View file
@@ -1,5 +1,6 @@
1-import { useEffect, useState } from 'react';
1+import { useEffect, useState, useMemo } from 'react';
22 import axios from 'axios';
3+import Plot from 'react-plotly.js';
34 import {
45 createColumnHelper,
56 flexRender,
@@ -99,31 +100,155 @@ const columns = [
99100
100101 export function BenchmarkTable() {
101102 const [data, setData] = useState<BenchmarkResult[]>([]);
103+ const [selectedDataset, setSelectedDataset] = useState<string>('');
104+ const [availableDatasets, setAvailableDatasets] = useState<string[]>([]);
105+ const [isLoading, setIsLoading] = useState(true);
106+ const [error, setError] = useState<string | null>(null);
102107
103108 useEffect(() => {
104109 const fetchData = async () => {
105110 try {
111+ setIsLoading(true);
112+ setError(null);
106113 const response = await axios.get(
107114 'https://raw.githubusercontent.com/magland/zia/benchmark-results/benchmark_results/results.json'
108115 );
109- setData(response.data.results);
116+ const results = response.data.results;
117+ setData(results);
118+ // Extract unique dataset names with proper typing
119+ const datasets = Array.from(new Set(results.map((result: BenchmarkResult) => result.dataset))).sort() as string[];
120+ setAvailableDatasets(datasets);
110121 } catch (error) {
122+ const message = error instanceof Error ? error.message : 'Failed to fetch data';
123+ setError(message);
111124 console.error('Error fetching benchmark data:', error);
125+ } finally {
126+ setIsLoading(false);
112127 }
113128 };
114129
115130 fetchData();
116131 }, []);
117132
133+ // Memoize filtered data to prevent unnecessary recalculations
134+ const filteredData = useMemo(() => {
135+ if (!selectedDataset) return data;
136+ return data.filter(row => row.dataset === selectedDataset);
137+ }, [data, selectedDataset]);
138+
118139 const table = useReactTable({
119- data,
140+ data: filteredData || [],
120141 columns,
121142 getCoreRowModel: getCoreRowModel(),
122143 getSortedRowModel: getSortedRowModel(),
123144 });
124145
146+ // Prepare data for bar charts when a dataset is selected
147+ const chartData = useMemo(() => {
148+ if (!selectedDataset) return [];
149+ return data
150+ .filter(row => row.dataset === selectedDataset)
151+ .map(row => ({
152+ algorithm: row.algorithm,
153+ compression_ratio: row.compression_ratio,
154+ encode_speed: row.encode_mb_per_sec,
155+ decode_speed: row.decode_mb_per_sec
156+ }));
157+ }, [data, selectedDataset]);
158+
159+ if (isLoading) {
160+ return <div>Loading benchmark data...</div>;
161+ }
162+
163+ if (error) {
164+ return <div>Error: {error}</div>;
165+ }
166+
125167 return (
126168 <div className="table-container">
169+ <div style={{ marginBottom: '20px', display: 'flex', alignItems: 'center', gap: '10px' }}>
170+ <label htmlFor="dataset-select">Filter by Dataset:</label>
171+ <select
172+ id="dataset-select"
173+ value={selectedDataset}
174+ onChange={(e) => setSelectedDataset(e.target.value)}
175+ style={{
176+ padding: '8px',
177+ borderRadius: '4px',
178+ border: '1px solid #ccc',
179+ minWidth: '200px',
180+ backgroundColor: '#fff'
181+ }}
182+ >
183+ <option value="">All Datasets</option>
184+ {availableDatasets.map(dataset => (
185+ <option key={dataset} value={dataset}>
186+ {dataset}
187+ </option>
188+ ))}
189+ </select>
190+ </div>
191+
192+ {selectedDataset && chartData.length > 0 && (
193+ <div style={{ marginBottom: '30px' }}>
194+ <div style={{ marginBottom: '20px' }}>
195+ <h3 style={{ marginBottom: '10px' }}>Compression Ratio</h3>
196+ <Plot
197+ data={[{
198+ type: 'bar',
199+ x: chartData.map(d => d.algorithm),
200+ y: chartData.map(d => d.compression_ratio),
201+ marker: { color: '#8884d8' }
202+ }]}
203+ layout={{
204+ width: 800,
205+ height: 300,
206+ margin: { t: 5, r: 30, l: 50, b: 30 },
207+ yaxis: { title: 'Ratio' }
208+ }}
209+ config={{ displayModeBar: false }}
210+ />
211+ </div>
212+
213+ <div style={{ marginBottom: '20px' }}>
214+ <h3 style={{ marginBottom: '10px' }}>Encode Speed (MB/s)</h3>
215+ <Plot
216+ data={[{
217+ type: 'bar',
218+ x: chartData.map(d => d.algorithm),
219+ y: chartData.map(d => d.encode_speed),
220+ marker: { color: '#82ca9d' }
221+ }]}
222+ layout={{
223+ width: 800,
224+ height: 300,
225+ margin: { t: 5, r: 30, l: 50, b: 30 },
226+ yaxis: { title: 'MB/s' }
227+ }}
228+ config={{ displayModeBar: false }}
229+ />
230+ </div>
231+
232+ <div style={{ marginBottom: '20px' }}>
233+ <h3 style={{ marginBottom: '10px' }}>Decode Speed (MB/s)</h3>
234+ <Plot
235+ data={[{
236+ type: 'bar',
237+ x: chartData.map(d => d.algorithm),
238+ y: chartData.map(d => d.decode_speed),
239+ marker: { color: '#ff7300' }
240+ }]}
241+ layout={{
242+ width: 800,
243+ height: 300,
244+ margin: { t: 5, r: 30, l: 50, b: 30 },
245+ yaxis: { title: 'MB/s' }
246+ }}
247+ config={{ displayModeBar: false }}
248+ />
249+ </div>
250+ </div>
251+ )}
127252 <table>
128253 <thead>
129254 {table.getHeaderGroups().map(headerGroup => (
web-ui/tsconfig.app.jsonmodified+1−3View file
@@ -1,6 +1,5 @@
11 {
22 "compilerOptions": {
3- "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
43 "target": "ES2020",
54 "useDefineForClassFields": true,
65 "lib": ["ES2020", "DOM", "DOM.Iterable"],
@@ -19,8 +18,7 @@
1918 "strict": true,
2019 "noUnusedLocals": true,
2120 "noUnusedParameters": true,
22- "noFallthroughCasesInSwitch": true,
23- "noUncheckedSideEffectImports": true
21+ "noFallthroughCasesInSwitch": true
2422 },
2523 "include": ["src"]
2624 }