Skip to content

Commit e78df90

Browse files
LessUpCopilot
andcommitted
docs: fix benchmark ratio bars
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7a84bd6 commit e78df90

5 files changed

Lines changed: 155 additions & 13 deletions

File tree

.github/workflows/ci-docs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ jobs:
3030
working-directory: docs
3131
run: npm ci
3232

33+
- name: Run docs tests
34+
working-directory: docs
35+
run: npm test
36+
3337
- name: Build docs
3438
working-directory: docs
3539
run: npm run build

docs/.vitepress/theme/components/BenchmarkChart.vue

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import { ref, computed, watchEffect } from 'vue'
33
import benchmarkData from '../../data/benchmarks.json'
4+
import { getBarHeight as getMetricBarHeight, isBestCompressionRatio } from './benchmarkChartMetrics.js'
45
56
interface BenchmarkResult {
67
algorithm: string
@@ -84,20 +85,23 @@ const maxValue = computed(() => {
8485
return Math.max(...filteredResults.value.map(r => r[selectedMetric.value]))
8586
})
8687
88+
const compressionRatios = computed(() => filteredResults.value.map(r => r.compressionRatio))
89+
8790
const formatMetricName = (metric: string): string => {
8891
const names: Record<string, string> = {
8992
encodeSpeed: 'Encode Speed (MiB/s)',
9093
decodeSpeed: 'Decode Speed (MiB/s)',
91-
compressionRatio: 'Compression Ratio (lower = better)'
94+
compressionRatio: 'Size Saved Relative to Input'
9295
}
9396
return names[metric] || metric
9497
}
9598
9699
const getBarHeight = (value: number): number => {
97-
const max = selectedMetric.value === 'compressionRatio'
98-
? Math.max(maxValue.value, 0.001)
99-
: Math.max(maxValue.value, 300)
100-
return Math.max((value / max) * 100, 5)
100+
return getMetricBarHeight(selectedMetric.value, value, maxValue.value)
101+
}
102+
103+
const isCompressionRatioLeader = (value: number): boolean => {
104+
return isBestCompressionRatio(selectedMetric.value, value, compressionRatios.value)
101105
}
102106
103107
const formatMetricValue = (value: number): string => {
@@ -147,14 +151,15 @@ const formatMetricValue = (value: number): string => {
147151
v-for="result in groupedByAlgorithm[algo]"
148152
:key="result.language"
149153
class="bar-wrapper"
150-
:title="`${languageNames[result.language]}: ${formatMetricValue(result[selectedMetric])}`"
151-
>
152-
<div
153-
class="bar"
154-
:style="{
155-
height: `${getBarHeight(result[selectedMetric])}%`,
156-
backgroundColor: languageColors[result.language]
157-
}"
154+
:title="`${languageNames[result.language]}: ${formatMetricValue(result[selectedMetric])}`"
155+
>
156+
<div
157+
class="bar"
158+
:class="{ 'bar-best': isCompressionRatioLeader(result.compressionRatio) }"
159+
:style="{
160+
height: `${getBarHeight(result[selectedMetric])}%`,
161+
backgroundColor: languageColors[result.language]
162+
}"
158163
>
159164
<span class="bar-value">{{ formatMetricValue(result[selectedMetric]) }}</span>
160165
</div>
@@ -163,6 +168,9 @@ const formatMetricValue = (value: number): string => {
163168
</div>
164169
</div>
165170

171+
<div v-if="selectedMetric === 'compressionRatio'" class="metric-note">
172+
Bars show size saved relative to input; labels show the actual output/input ratio, and the best ratio is highlighted.
173+
</div>
166174
<div class="metric-label">{{ formatMetricName(selectedMetric) }}</div>
167175
</div>
168176
</template>
@@ -302,6 +310,11 @@ const formatMetricValue = (value: number): string => {
302310
opacity: 1;
303311
}
304312
313+
.bar-best {
314+
box-shadow: 0 0 0 2px var(--vp-c-brand-1);
315+
opacity: 1;
316+
}
317+
305318
.bar-value {
306319
position: absolute;
307320
top: -20px;
@@ -313,6 +326,13 @@ const formatMetricValue = (value: number): string => {
313326
white-space: nowrap;
314327
}
315328
329+
.metric-note {
330+
text-align: center;
331+
font-size: 0.8125rem;
332+
color: var(--vp-c-text-2);
333+
margin-top: 1.25rem;
334+
}
335+
316336
.metric-label {
317337
text-align: center;
318338
font-size: 0.875rem;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
const MIN_BAR_HEIGHT = 5
2+
const MIN_COMPRESSION_BAR_HEIGHT = 2
3+
const MIN_SPEED_SCALE = 300
4+
const COMPRESSION_RATIO_TOLERANCE = 1e-9
5+
6+
export function getBarHeight(metric, value, maxValue) {
7+
if (metric === 'compressionRatio') {
8+
const safeRatio = Math.max(value, 0)
9+
const sizeSaved = 1 - Math.min(safeRatio, 1)
10+
if (sizeSaved <= 0) {
11+
return MIN_COMPRESSION_BAR_HEIGHT
12+
}
13+
14+
return MIN_COMPRESSION_BAR_HEIGHT + (sizeSaved * (100 - MIN_COMPRESSION_BAR_HEIGHT))
15+
}
16+
17+
const max = Math.max(maxValue, MIN_SPEED_SCALE)
18+
return Math.max((value / max) * 100, MIN_BAR_HEIGHT)
19+
}
20+
21+
export function isBestCompressionRatio(metric, value, values) {
22+
if (metric !== 'compressionRatio' || values.length === 0) {
23+
return false
24+
}
25+
26+
const bestRatio = Math.min(...values)
27+
return Math.abs(value - bestRatio) <= COMPRESSION_RATIO_TOLERANCE
28+
}

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"scripts": {
66
"sync": "node scripts/sync-changelog.mjs",
77
"dev": "npm run sync && vitepress dev",
8+
"test": "node --test tests/*.test.mjs",
89
"build": "npm run sync && vitepress build",
910
"preview": "vitepress preview"
1011
},
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import test from 'node:test'
2+
import assert from 'node:assert/strict'
3+
import { readFile } from 'node:fs/promises'
4+
import { getBarHeight, isBestCompressionRatio } from '../.vitepress/theme/components/benchmarkChartMetrics.js'
5+
6+
const loadCompressionRatios = async dataset => {
7+
const source = await readFile(new URL('../.vitepress/data/benchmarks.json', import.meta.url), 'utf8')
8+
const { results } = JSON.parse(source)
9+
return results
10+
.filter(result => result.dataset === dataset)
11+
.map(result => result.compressionRatio)
12+
}
13+
14+
test('compression ratio bars reward smaller output/input ratios', async () => {
15+
const values = await loadCompressionRatios('textlike_10MiB')
16+
const bestRatio = Math.min(...values)
17+
const worstRatio = Math.max(...values)
18+
19+
assert.ok(
20+
getBarHeight('compressionRatio', bestRatio, worstRatio) >
21+
getBarHeight('compressionRatio', worstRatio, worstRatio),
22+
'smaller compression ratios should render taller bars'
23+
)
24+
})
25+
26+
test('compression ratio bars keep near-identical ratios visually close', () => {
27+
const better = getBarHeight('compressionRatio', 0.743, 0.746)
28+
const worse = getBarHeight('compressionRatio', 0.746, 0.746)
29+
30+
assert.ok(better > worse, 'smaller compression ratios should still render taller bars')
31+
assert.ok(
32+
better - worse < 1,
33+
'near-identical compression ratios should not be stretched across the full chart'
34+
)
35+
})
36+
37+
test('compression ratio bars bottom out once compression stops helping', () => {
38+
assert.ok(
39+
getBarHeight('compressionRatio', 0.95, 1) > getBarHeight('compressionRatio', 1, 1),
40+
'small-but-positive savings should still render above the no-compression baseline'
41+
)
42+
assert.equal(
43+
getBarHeight('compressionRatio', 1.01, 2),
44+
2,
45+
'expanding results should stay at the floor because they save no space'
46+
)
47+
assert.equal(
48+
getBarHeight('compressionRatio', 2, 2),
49+
2,
50+
'worse expansion should also stay at the floor'
51+
)
52+
})
53+
54+
test('best compression ratio stays highlighted even when bars are close', async () => {
55+
const values = await loadCompressionRatios('textlike_10MiB')
56+
const bestRatio = Math.min(...values)
57+
const worstRatio = Math.max(...values)
58+
59+
assert.equal(
60+
isBestCompressionRatio('compressionRatio', bestRatio, values),
61+
true,
62+
'the lowest compression ratio should be highlighted'
63+
)
64+
assert.equal(
65+
isBestCompressionRatio('compressionRatio', worstRatio, values),
66+
false,
67+
'higher compression ratios should not be highlighted'
68+
)
69+
})
70+
71+
test('best compression ratio still gets highlighted among expanding results', () => {
72+
assert.equal(
73+
isBestCompressionRatio('compressionRatio', 1.01, [1.01, 2]),
74+
true,
75+
'the smaller expansion ratio should still be highlighted as the better result'
76+
)
77+
assert.equal(
78+
isBestCompressionRatio('compressionRatio', 2, [1.01, 2]),
79+
false,
80+
'the larger expansion ratio should not be highlighted'
81+
)
82+
})
83+
84+
test('encode speed bars still reward faster results', () => {
85+
assert.ok(
86+
getBarHeight('encodeSpeed', 277, 277) > getBarHeight('encodeSpeed', 58.8, 277),
87+
'higher encode speeds should still render taller bars'
88+
)
89+
})

0 commit comments

Comments
 (0)