Skip to content

Commit 4066062

Browse files
committed
perf: add gas limit bands and RLPx cap
Add reference bands to Gas Used and Gas Fill % charts showing General/Payment/Shared gas limit regions. Move Block Headroom charts into the Blocks section. Add RLPx 16 MiB hard cap band to RLP Block Size chart. Fix oblong hover dots by rendering them as HTML elements instead of SVG circles (preserveAspectRatio=none).
1 parent 875921d commit 4066062

1 file changed

Lines changed: 184 additions & 72 deletions

File tree

apps/perf/src/routes/benchmark.$id.tsx

Lines changed: 184 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,12 @@ function RunDetailPage(): React.JSX.Element {
259259
const residentSeries = findSeries(m, 'reth_jemalloc_resident')
260260
const allocatedSeries = findSeries(m, 'reth_jemalloc_allocated')
261261

262+
// Gas limit breakdown (derived from block gas limit)
263+
const refGasLimit = blocks?.[0]?.gasLimit ?? 0
264+
const sharedGasLimit = Math.floor(refGasLimit / 10)
265+
const generalGasLimit = 30_000_000
266+
const paymentGasLimit = refGasLimit - sharedGasLimit - generalGasLimit
267+
262268
return (
263269
<div>
264270
<div className="mb-4">
@@ -380,6 +386,99 @@ function RunDetailPage(): React.JSX.Element {
380386
]}
381387
formatValue={(v) => formatGas(v, false)}
382388
xFormat="block"
389+
referenceBands={
390+
refGasLimit > 0
391+
? [
392+
{
393+
label: `General (${formatGas(generalGasLimit, false)})`,
394+
from: 0,
395+
to: generalGasLimit,
396+
color: COLORS.blue,
397+
},
398+
{
399+
label: `Payment (${formatGas(paymentGasLimit, false)})`,
400+
from: generalGasLimit,
401+
to: generalGasLimit + paymentGasLimit,
402+
color: COLORS.orange,
403+
},
404+
{
405+
label: `Shared (${formatGas(sharedGasLimit, false)})`,
406+
from: generalGasLimit + paymentGasLimit,
407+
to: refGasLimit,
408+
color: COLORS.purple,
409+
},
410+
]
411+
: undefined
412+
}
413+
/>
414+
<TimeSeriesChart
415+
title="Gas Fill %"
416+
tooltip="Percentage of the block gas limit that was used."
417+
showMean
418+
series={[
419+
{
420+
label: 'Fill %',
421+
color: COLORS.blue,
422+
data: blocks
423+
.filter((b) => b.gasLimit > 0)
424+
.map((b) => ({
425+
x: b.index,
426+
y: (b.gasUsed / b.gasLimit) * 100,
427+
})),
428+
},
429+
]}
430+
formatValue={(v) => `${v.toFixed(1)}%`}
431+
yMax={100}
432+
xFormat="block"
433+
referenceBands={
434+
refGasLimit > 0
435+
? [
436+
{
437+
label: `General (${((generalGasLimit / refGasLimit) * 100).toFixed(0)}%)`,
438+
from: 0,
439+
to: (generalGasLimit / refGasLimit) * 100,
440+
color: COLORS.blue,
441+
},
442+
{
443+
label: `Payment (${((paymentGasLimit / refGasLimit) * 100).toFixed(0)}%)`,
444+
from: (generalGasLimit / refGasLimit) * 100,
445+
to:
446+
((generalGasLimit + paymentGasLimit) / refGasLimit) *
447+
100,
448+
color: COLORS.orange,
449+
},
450+
{
451+
label: `Shared (${((sharedGasLimit / refGasLimit) * 100).toFixed(0)}%)`,
452+
from:
453+
((generalGasLimit + paymentGasLimit) / refGasLimit) *
454+
100,
455+
to: 100,
456+
color: COLORS.purple,
457+
},
458+
]
459+
: undefined
460+
}
461+
/>
462+
<TimeSeriesChart
463+
title="RLP Block Size"
464+
tooltip="RLP-encoded size of each block in kilobytes."
465+
showMean
466+
series={[
467+
{
468+
label: 'Size',
469+
color: COLORS.green,
470+
data: transformSamples(rlpSizeSeries, (v) => v / 1024),
471+
},
472+
]}
473+
formatValue={(v) => `${v.toFixed(0)} KB`}
474+
referenceBands={[
475+
{
476+
label: 'RLPx hard cap (16 MiB)',
477+
from: 16 * 1024,
478+
to: 16 * 1024 * 1.05,
479+
color: COLORS.red,
480+
},
481+
]}
383482
/>
384483
</div>
385484
</section>
@@ -521,48 +620,6 @@ function RunDetailPage(): React.JSX.Element {
521620
</div>
522621
</section>
523622

524-
<section className="mb-10">
525-
<SectionHeader
526-
title="Block Headroom"
527-
tooltip="How close blocks are to their gas limit and size constraints."
528-
/>
529-
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
530-
<TimeSeriesChart
531-
title="Gas Fill %"
532-
tooltip="Percentage of the block gas limit that was used."
533-
showMean
534-
series={[
535-
{
536-
label: 'Fill %',
537-
color: COLORS.blue,
538-
data: (blocks ?? [])
539-
.filter((b) => b.gasLimit > 0)
540-
.map((b) => ({
541-
x: b.index,
542-
y: (b.gasUsed / b.gasLimit) * 100,
543-
})),
544-
},
545-
]}
546-
formatValue={(v) => `${v.toFixed(1)}%`}
547-
yMax={100}
548-
xFormat="block"
549-
/>
550-
<TimeSeriesChart
551-
title="RLP Block Size"
552-
tooltip="RLP-encoded size of each block in kilobytes."
553-
showMean
554-
series={[
555-
{
556-
label: 'Size',
557-
color: COLORS.green,
558-
data: transformSamples(rlpSizeSeries, (v) => v / 1024),
559-
},
560-
]}
561-
formatValue={(v) => `${v.toFixed(0)} KB`}
562-
/>
563-
</div>
564-
</section>
565-
566623
<section className="mb-10">
567624
<SectionHeader
568625
title="Txgen"
@@ -860,6 +917,13 @@ function seriesMean(data: Array<ChartPoint>): number {
860917
return data.reduce((sum, p) => sum + p.y, 0) / data.length
861918
}
862919

920+
type ReferenceBand = {
921+
label: string
922+
from: number
923+
to: number
924+
color: string
925+
}
926+
863927
function TimeSeriesChart(props: {
864928
series: Array<ChartSeries>
865929
title?: string | undefined
@@ -869,6 +933,7 @@ function TimeSeriesChart(props: {
869933
formatValue?: ((v: number) => string) | undefined
870934
xFormat?: 'time' | 'block' | undefined
871935
yMax?: number | undefined
936+
referenceBands?: Array<ReferenceBand> | undefined
872937
}): React.JSX.Element {
873938
const plotRef = React.useRef<HTMLDivElement>(null)
874939
const [hoverX, setHoverX] = React.useState<number | null>(null)
@@ -897,6 +962,10 @@ function TimeSeriesChart(props: {
897962
const xMax = refSeries.data.at(-1)?.x ?? 1
898963
const xRange = xMax - xMin || 1
899964

965+
const refBandMax = props.referenceBands?.length
966+
? Math.max(...props.referenceBands.map((rb) => rb.to))
967+
: 0
968+
900969
let yMax: number
901970
if (props.yMax != null) {
902971
yMax = props.yMax
@@ -907,9 +976,12 @@ function TimeSeriesChart(props: {
907976
for (const s of props.series) sum += s.data[i]?.y ?? 0
908977
sums.push(sum)
909978
}
910-
yMax = (Math.max(...sums) || 1) * 1.1
979+
yMax = Math.max((Math.max(...sums) || 1) * 1.1, refBandMax * 1.05)
911980
} else {
912-
yMax = (Math.max(...allPoints.map((p) => p.y)) || 1) * 1.1
981+
yMax = Math.max(
982+
(Math.max(...allPoints.map((p) => p.y)) || 1) * 1.1,
983+
refBandMax * 1.05,
984+
)
913985
}
914986
const yMin = 0
915987
const yRange = yMax - yMin || 1
@@ -1082,6 +1154,46 @@ function TimeSeriesChart(props: {
10821154
))
10831155
))}
10841156

1157+
{/* Reference bands */}
1158+
{props.referenceBands?.map((rb) => {
1159+
const y1 = sy(rb.to)
1160+
const y2 = sy(rb.from)
1161+
const h = y2 - y1
1162+
const midY = y1 + h / 2
1163+
return (
1164+
<React.Fragment key={rb.label}>
1165+
<rect
1166+
x={0}
1167+
y={y1}
1168+
width={SVG_W}
1169+
height={h}
1170+
fill={rb.color}
1171+
opacity={0.1}
1172+
/>
1173+
<line
1174+
x1={0}
1175+
y1={y1}
1176+
x2={SVG_W}
1177+
y2={y1}
1178+
stroke={rb.color}
1179+
vectorEffect="non-scaling-stroke"
1180+
strokeWidth={0.5}
1181+
opacity={0.3}
1182+
/>
1183+
<text
1184+
x={SVG_W - 4}
1185+
y={h > 12 ? midY + 3 : y1 + 11}
1186+
textAnchor="end"
1187+
fill={rb.color}
1188+
fontSize={8}
1189+
opacity={0.8}
1190+
>
1191+
{rb.label}
1192+
</text>
1193+
</React.Fragment>
1194+
)
1195+
})}
1196+
10851197
{/* Stacked area fills */}
10861198
{props.stacked &&
10871199
stackedAreas.map((a) => (
@@ -1141,36 +1253,36 @@ function TimeSeriesChart(props: {
11411253
strokeDasharray="3 3"
11421254
/>
11431255
)}
1256+
</svg>
11441257

1145-
{/* Hover dots */}
1146-
{hoverX !== null &&
1147-
props.series.map((s) => {
1148-
const pt = closestPoint(s.data, hoverX)
1149-
if (!pt) return null
1150-
let y = pt.y
1151-
if (props.stacked) {
1152-
const si = props.series.indexOf(s)
1153-
y = 0
1154-
for (let j = 0; j <= si; j++) {
1155-
const cp = closestPoint(props.series[j].data, hoverX)
1156-
y += cp?.y ?? 0
1157-
}
1258+
{/* Hover dots (HTML to avoid SVG stretch distortion) */}
1259+
{hoverX !== null &&
1260+
props.series.map((s) => {
1261+
const pt = closestPoint(s.data, hoverX)
1262+
if (!pt) return null
1263+
let y = pt.y
1264+
if (props.stacked) {
1265+
const si = props.series.indexOf(s)
1266+
y = 0
1267+
for (let j = 0; j <= si; j++) {
1268+
const cp = closestPoint(props.series[j].data, hoverX)
1269+
y += cp?.y ?? 0
11581270
}
1159-
return (
1160-
<circle
1161-
key={s.label}
1162-
cx={sx(pt.x)}
1163-
cy={sy(y)}
1164-
r={3}
1165-
fill={s.color}
1166-
stroke="currentColor"
1167-
className="text-surface"
1168-
vectorEffect="non-scaling-stroke"
1169-
strokeWidth={1.5}
1170-
/>
1171-
)
1172-
})}
1173-
</svg>
1271+
}
1272+
const xPct = ((pt.x - xMin) / xRange) * 100
1273+
const yPct = (1 - (y - yMin) / yRange) * 100
1274+
return (
1275+
<div
1276+
key={s.label}
1277+
className="pointer-events-none absolute h-2 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full border-[1.5px] border-surface"
1278+
style={{
1279+
left: `${xPct}%`,
1280+
top: `${yPct}%`,
1281+
backgroundColor: s.color,
1282+
}}
1283+
/>
1284+
)
1285+
})}
11741286

11751287
{/* Hover tooltip */}
11761288
{hoverX !== null && (

0 commit comments

Comments
 (0)