/ concept-collection / qhull-wasm-demo
Sign in
concept-collection / qhull-wasm-demo
qhull-wasm-demo / src / components / Benchmarks.tsx
106 lines · 4.0 KBBlameHistoryRaw
1import { useState } from 'react'
2import {
3 Box, Button, Paper, Stack, Table, TableBody, TableCell, TableContainer,
4 TableHead, TableRow, Typography, LinearProgress, Link,
5} from '@mui/material'
6import { getQhull } from '../qhull'
7import { points2D, points3D } from '../points'
8import benchScript from '../../scripts/qhull_benchmark.m?raw'
10const SIZES = [1000, 5000, 20000, 50000]
12interface Row { n: number; ms2: number; ms3: number; simp2: number; simp3: number }
14const yield_ = () => new Promise((r) => setTimeout(r, 0))
16export function Benchmarks() {
17 const [rows, setRows] = useState<Row[]>([])
18 const [running, setRunning] = useState(false)
19 const [progress, setProgress] = useState(0)
21 const run = async () => {
22 setRunning(true); setRows([]); setProgress(0)
23 const q = await getQhull()
24 const out: Row[] = []
25 for (let i = 0; i < SIZES.length; i++) {
26 const n = SIZES[i]
27 await yield_()
28 const p2 = points2D(n, 'uniform', 12345 + i)
29 let t = performance.now()
30 const r2 = q.delaunay(p2, 2)
31 const ms2 = performance.now() - t
33 const p3 = points3D(n, 'uniform', 54321 + i)
34 t = performance.now()
35 const r3 = q.delaunay(p3, 3)
36 const ms3 = performance.now() - t
38 out.push({ n, ms2, ms3, simp2: r2.facets.length, simp3: r3.facets.length })
39 setRows([...out]); setProgress(((i + 1) / SIZES.length) * 100)
40 }
41 setRunning(false)
42 }
44 const download = () => {
45 const blob = new Blob([benchScript], { type: 'text/plain' })
46 const a = document.createElement('a')
47 a.href = URL.createObjectURL(blob)
48 a.download = 'qhull_benchmark.m'
49 a.click()
50 URL.revokeObjectURL(a.href)
51 }
53 return (
54 <Stack spacing={2}>
55 <Typography variant="body2" color="text.secondary">
56 Delaunay triangulation of uniform random points, timed in your browser via qhull-wasm.
57 Run the matching <code>.m</code> script below in MATLAB, Octave, or{' '}
58 <Link href="https://numbl.org" target="_blank" rel="noreferrer">numbl</Link> for an
59 apples-to-apples comparison (all three triangulate via Qhull).
60 </Typography>
62 <Box>
63 <Button variant="contained" onClick={run} disabled={running}>
64 {running ? 'Running…' : 'Run benchmark'}
65 </Button>
66 </Box>
67 {running && <LinearProgress variant="determinate" value={progress} />}
69 {rows.length > 0 && (
70 <TableContainer component={Paper} variant="outlined" sx={{ maxWidth: 640 }}>
71 <Table size="small">
72 <TableHead>
73 <TableRow>
74 <TableCell>N</TableCell>
75 <TableCell align="right">2D (ms)</TableCell>
76 <TableCell align="right">2D simplices</TableCell>
77 <TableCell align="right">3D (ms)</TableCell>
78 <TableCell align="right">3D simplices</TableCell>
79 </TableRow>
80 </TableHead>
81 <TableBody>
82 {rows.map((r) => (
83 <TableRow key={r.n}>
84 <TableCell>{r.n.toLocaleString()}</TableCell>
85 <TableCell align="right">{r.ms2.toFixed(1)}</TableCell>
86 <TableCell align="right">{r.simp2.toLocaleString()}</TableCell>
87 <TableCell align="right">{r.ms3.toFixed(1)}</TableCell>
88 <TableCell align="right">{r.simp3.toLocaleString()}</TableCell>
89 </TableRow>
90 ))}
91 </TableBody>
92 </Table>
93 </TableContainer>
94 )}
96 <Stack direction="row" spacing={1} alignItems="center">
97 <Typography variant="subtitle2">Comparison script (MATLAB / Octave / numbl)</Typography>
98 <Button size="small" onClick={() => navigator.clipboard?.writeText(benchScript)}>Copy</Button>
99 <Button size="small" onClick={download}>Download .m</Button>
100 </Stack>
101 <Paper variant="outlined" sx={{ p: 2, bgcolor: '#0f1722', overflow: 'auto' }}>
102 <pre style={{ margin: 0, color: '#e0e0e0', fontSize: 13, lineHeight: 1.45 }}>{benchScript}</pre>
103 </Paper>
104 </Stack>
105 )
moveopenescclose