diff --git a/packages/ui-utils/src/formatters.ts b/packages/ui-utils/src/formatters.ts index 76869c9..f55309a 100644 --- a/packages/ui-utils/src/formatters.ts +++ b/packages/ui-utils/src/formatters.ts @@ -1,23 +1,23 @@ -export function formatBytes(bytes: number): string { +export function formatBytes(bytes: number, precision = 2): string { if (bytes === 0) return '0 B'; const units = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log2(bytes) / 10); - return `${(bytes / (1 << (i * 10))).toFixed(2)} ${units[i]}`; + return `${(bytes / (1 << (i * 10))).toFixed(precision)} ${units[i]}`; } -export function formatNumber(num: number): string { - if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B'; - if (num >= 1e6) return (num / 1e6).toFixed(2) + 'M'; - if (num >= 1e3) return (num / 1e3).toFixed(2) + 'K'; +export function formatNumber(num: number, precision = 2): string { + if (num >= 1e9) return (num / 1e9).toFixed(precision) + 'B'; + if (num >= 1e6) return (num / 1e6).toFixed(precision) + 'M'; + if (num >= 1e3) return (num / 1e3).toFixed(precision) + 'K'; return num.toString(); } -export function formatTime(seconds: number): string { - if (seconds < 0.001) return (seconds * 1e6).toFixed(2) + 'μs'; - if (seconds < 1) return (seconds * 1000).toFixed(2) + 'ms'; +export function formatTime(seconds: number, precision = 2): string { + if (seconds < 0.001) return (seconds * 1e6).toFixed(precision) + 'μs'; + if (seconds < 1) return (seconds * 1000).toFixed(precision) + 'ms'; return seconds.toFixed(3) + 's'; } -export function formatPercent(value: number): string { - return (value * 100).toFixed(2) + '%'; +export function formatPercent(value: number, precision = 2): string { + return (value * 100).toFixed(precision) + '%'; } diff --git a/packages/web/src/components/Analysis.tsx b/packages/web/src/components/Analysis.tsx index 2fc65ca..14c29ac 100644 --- a/packages/web/src/components/Analysis.tsx +++ b/packages/web/src/components/Analysis.tsx @@ -46,7 +46,8 @@ const TOOLTIPS = { attrSelect: 'Number of attribute selections performed (accessing .attr from an attribute set)', }; -const Analysis: Component<{ stats: StatsData }> = props => { +const Analysis: Component<{ stats: StatsData; precision?: number }> = props => { + const prec = () => props.precision ?? 2; const totalMemory = createMemo( () => props.stats.envs.bytes + @@ -105,18 +106,22 @@ const Analysis: Component<{ stats: StatsData }> = props => {
- + = props.stats.nrThunks} /> @@ -131,11 +136,11 @@ const Analysis: Component<{ stats: StatsData }> = props => {
GC Statistics
Heap: - {formatBytes(props.stats.gc?.heapSize || 0)} + {formatBytes(props.stats.gc?.heapSize || 0, prec())} Allocated: - {formatBytes(props.stats.gc?.totalBytes || 0)} + {formatBytes(props.stats.gc?.totalBytes || 0, prec())} Cycles: - {formatNumber(props.stats.gc?.cycles || 0)} + {formatNumber(props.stats.gc?.cycles || 0, prec())}
@@ -143,15 +148,15 @@ const Analysis: Component<{ stats: StatsData }> = props => {
- +
- +
- +
@@ -160,17 +165,17 @@ const Analysis: Component<{ stats: StatsData }> = props => {
@@ -180,22 +185,22 @@ const Analysis: Component<{ stats: StatsData }> = props => {
@@ -205,22 +210,22 @@ const Analysis: Component<{ stats: StatsData }> = props => {
@@ -235,7 +240,7 @@ const Analysis: Component<{ stats: StatsData }> = props => {
{i() + 1} {item.name} - {formatNumber(item.count)} + {formatNumber(item.count, prec())}
)} @@ -251,7 +256,7 @@ const Analysis: Component<{ stats: StatsData }> = props => {
{i() + 1} {item.name || ''} - {formatNumber(item.count)} + {formatNumber(item.count, prec())} {item.file}:{item.line} @@ -267,22 +272,22 @@ const Analysis: Component<{ stats: StatsData }> = props => {
@@ -299,7 +304,7 @@ const Analysis: Component<{ stats: StatsData }> = props => { {item.file}:{item.line} - {formatNumber(item.count)} + {formatNumber(item.count, prec())}
)} diff --git a/packages/web/src/components/ComparisonView.tsx b/packages/web/src/components/ComparisonView.tsx index c989099..1c7941e 100644 --- a/packages/web/src/components/ComparisonView.tsx +++ b/packages/web/src/components/ComparisonView.tsx @@ -10,9 +10,11 @@ interface ComparisonViewProps { entries: ComparisonEntry[]; onSelect: (entry: ComparisonEntry) => void; onDelete: (id: number) => void; + precision?: number; } const ComparisonView: Component = props => { + const prec = () => props.precision ?? 2; const [leftEntry, setLeftEntry] = createSignal(null); const [rightEntry, setRightEntry] = createSignal(null); @@ -203,7 +205,7 @@ const ComparisonView: Component = props => { - {Math.abs(row.change).toFixed(2)}% + {Math.abs(row.change).toFixed(prec())}% } diff --git a/packages/web/src/components/OperationsChart.tsx b/packages/web/src/components/OperationsChart.tsx index 13c28e2..d49fa35 100644 --- a/packages/web/src/components/OperationsChart.tsx +++ b/packages/web/src/components/OperationsChart.tsx @@ -4,9 +4,11 @@ import { formatNumber } from '@ns/ui-utils'; interface OperationsChartProps { stats: StatsData; + precision?: number; } const OperationsChart: Component = props => { + const prec = () => props.precision ?? 2; const operations = createMemo(() => [ { label: 'Lookups', value: props.stats.nrLookups, colorClass: 'chart-1' }, @@ -34,7 +36,7 @@ const OperationsChart: Component = props => { }} /> -
{formatNumber(item.value)}
+
{formatNumber(item.value, prec())}
)} diff --git a/packages/web/src/components/ThunkChart.tsx b/packages/web/src/components/ThunkChart.tsx index e403ad8..7a78938 100644 --- a/packages/web/src/components/ThunkChart.tsx +++ b/packages/web/src/components/ThunkChart.tsx @@ -4,9 +4,11 @@ import { formatNumber } from '@ns/ui-utils'; interface ThunkChartProps { stats: StatsData; + precision?: number; } const ThunkChart: Component = props => { + const prec = () => props.precision ?? 2; const maxValue = createMemo(() => Math.max(props.stats.nrThunks, props.stats.nrAvoided)); const avoidedRatio = createMemo(() => { @@ -47,7 +49,7 @@ const ThunkChart: Component = props => {
- Avoidance rate: {(avoidedRatio() * 100).toFixed(1)}% + Avoidance rate: {(avoidedRatio() * 100).toFixed(prec())}%
); diff --git a/packages/web/src/components/TimeChart.tsx b/packages/web/src/components/TimeChart.tsx index 50b07bc..2f5737b 100644 --- a/packages/web/src/components/TimeChart.tsx +++ b/packages/web/src/components/TimeChart.tsx @@ -4,9 +4,11 @@ import { formatBytes, formatTime, formatPercent } from '@ns/ui-utils'; interface TimeChartProps { stats: StatsData; + precision?: number; } const TimeChart: Component = props => { + const prec = () => props.precision ?? 2; const timeData = createMemo(() => { const cpu = props.stats.time.cpu; const gc = props.stats.time.gc || 0; @@ -45,7 +47,7 @@ const TimeChart: Component = props => { }} /> -
{formatTime(item.value)}
+
{formatTime(item.value, prec())}
)} @@ -59,11 +61,13 @@ const TimeChart: Component = props => {
Heap Size - {formatBytes(props.stats.gc?.heapSize || 0)} + {formatBytes(props.stats.gc?.heapSize || 0, prec())}
GC Fraction - {formatPercent(props.stats.time.gcFraction || 0)} + + {formatPercent(props.stats.time.gcFraction || 0, prec())} +
diff --git a/packages/web/src/index.tsx b/packages/web/src/index.tsx index a173b19..578bb8a 100644 --- a/packages/web/src/index.tsx +++ b/packages/web/src/index.tsx @@ -31,6 +31,7 @@ function App() { const [showSaveDialog, setShowSaveDialog] = createSignal(false); const [showHelp, setShowHelp] = createSignal(false); const [showManageSnapshots, setShowManageSnapshots] = createSignal(false); + const [precision, setPrecision] = createSignal(2); const [isLoading, setIsLoading] = createSignal(true); const STORAGE_KEY = 'ns-data'; @@ -58,6 +59,9 @@ function App() { if (parsed.view) { setView(parsed.view); } + if (typeof parsed.precision === 'number' && parsed.precision >= 0) { + setPrecision(parsed.precision); + } } } catch (e) { console.warn('Failed to load saved data:', e); @@ -84,6 +88,7 @@ function App() { raw: Record | null, snaps: ComparisonEntry[], v: 'analysis' | 'compare', + prec: number, ) => { try { localStorage.setItem( @@ -93,6 +98,7 @@ function App() { currentStats: stats, currentRaw: raw, view: v, + precision: prec, }), ); } catch (e) { @@ -108,10 +114,11 @@ function App() { const raw = currentRaw(); const snaps = snapshots(); const v = view(); + const prec = precision(); if (isLoading()) return; - saveToStorage(stats, raw, snaps, v); + saveToStorage(stats, raw, snaps, v, prec); }); const saveSnapshot = () => { @@ -190,6 +197,16 @@ function App() { + @@ -213,7 +230,7 @@ function App() { /> - +