Skip to content

Commit 1fc37b5

Browse files
feat: startup snapshot writing card
1 parent e755f55 commit 1fc37b5

9 files changed

Lines changed: 303 additions & 189 deletions

File tree

src/api/entities.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export const tileTypeSchema = z.enum([
8585
"snapld",
8686
"snapdc",
8787
"snapin",
88+
"snapwr",
8889

8990
// shred tiles
9091
"netlnk",
@@ -338,6 +339,15 @@ export const bootProgressSchema = z.object({
338339
.nullable()
339340
.optional(),
340341
loading_full_snapshot_insert_accounts: z.number().nullable().optional(),
342+
loading_full_snapshot_snapwr_in_bytes_decompressed: z.coerce
343+
.number()
344+
.nullable()
345+
.optional(),
346+
loading_full_snapshot_snapwr_out_bytes_decompressed: z.coerce
347+
.number()
348+
.nullable()
349+
.optional(),
350+
loading_full_snapshot_snapwr_accounts: z.number().nullable().optional(),
341351

342352
loading_incremental_snapshot_elapsed_seconds: z
343353
.number()
@@ -370,6 +380,20 @@ export const bootProgressSchema = z.object({
370380
.number()
371381
.nullable()
372382
.optional(),
383+
loading_incremental_snapshot_snapwr_in_bytes_decompressed: z.coerce
384+
.number()
385+
.nullable()
386+
.optional(),
387+
loading_incremental_snapshot_snapwr_out_bytes_decompressed: z.coerce
388+
.number()
389+
.nullable()
390+
.optional(),
391+
loading_incremental_snapshot_snapwr_accounts: z
392+
.number()
393+
.nullable()
394+
.optional(),
395+
396+
accounts_database_path: z.string().nullable().optional(),
373397

374398
wait_for_supermajority_bank_hash: z.string().nullable().optional(),
375399
wait_for_supermajority_shred_version: z.string().nullable().optional(),

src/features/Overview/SlotPerformance/atoms.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export const groupedLiveIdlePerTileAtom = atom((get) => {
133133
export const snapshotTimerIndicesAtom = atom(
134134
(get): [TileType, number[]][] | undefined => {
135135
const tiles = get(tilesAtom);
136-
const tileTypes: TileType[] = ["snapld", "snapdc", "snapin"];
136+
const tileTypes: TileType[] = ["snapld", "snapdc", "snapin", "snapwr"];
137137

138138
if (!tiles) return;
139139

src/features/StartupProgress/Firedancer/Snapshot/SnapshotBarsCard.tsx

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,69 @@ import { Bars } from "../Bars";
55
import { useValuePerSecond } from "../useValuePerSecond";
66
import { bootProgressPhaseAtom } from "../../atoms";
77
import { useAtomValue } from "jotai";
8-
import { useEffect, useMemo } from "react";
8+
import { memo, useEffect, useMemo } from "react";
99
import StorageIcon from "@material-design-icons/svg/filled/storage.svg?react";
1010
import { compactSingleDecimalFormatter } from "../../../../numUtils";
1111
import type { FormattedBytes } from "../../../../utils";
12+
import Progress from "../../../../components/Progress";
13+
14+
const gap = "4px";
1215

1316
interface SnapshotBarsCardProps {
17+
title: string;
1418
headerContent: JSX.Element;
1519
footer?: JSX.Element;
1620
throughput: number | null | undefined;
17-
containerClassName: string;
1821
maxThroughput: number;
22+
progressPct: number | undefined;
1923
}
2024
export function SnapshotBarsCard({
25+
title,
2126
headerContent,
2227
footer,
2328
throughput,
24-
containerClassName,
2529
maxThroughput,
30+
progressPct,
2631
}: SnapshotBarsCardProps) {
2732
return (
28-
<Card className={clsx(styles.card, styles.barsCard, containerClassName)}>
29-
<Flex
30-
justify="between"
31-
align="center"
32-
wrap="wrap"
33-
gapX="4"
34-
className={styles.cardHeader}
35-
>
36-
{headerContent}
33+
<Card className={clsx(styles.card, styles.barsCard)}>
34+
<Flex direction="column" gap="2px">
35+
<ProgressBar pct={progressPct} />
36+
<Flex
37+
justify="between"
38+
wrap="nowrap"
39+
gap={gap}
40+
className={styles.cardHeader}
41+
>
42+
<SnapshotTitle text={title} />
43+
<Flex gap={gap} minWidth="0" className={styles.headerRightSection}>
44+
{headerContent}
45+
</Flex>
46+
</Flex>
3747
</Flex>
38-
3948
<Bars value={throughput ?? 0} max={maxThroughput} />
4049

4150
{footer}
4251
</Card>
4352
);
4453
}
4554

55+
interface ProgressBarProps {
56+
pct: number | undefined;
57+
}
58+
function ProgressBar({ pct }: ProgressBarProps) {
59+
const bootPhase = useAtomValue(bootProgressPhaseAtom);
60+
// jump to inital value on phase change
61+
return (
62+
<Flex key={bootPhase} gap="10px" align="center">
63+
<Progress className={styles.progressBar} value={pct ?? 0} />
64+
<Text className={clsx(styles.secondaryColor, styles.progressPctText)}>
65+
{pct == null ? "-" : pct.toFixed(0)}%
66+
</Text>
67+
</Flex>
68+
);
69+
}
70+
4671
function ValueUnitText({
4772
value,
4873
unit,
@@ -53,21 +78,16 @@ function ValueUnitText({
5378
return (
5479
<>
5580
<Text>{value ?? "--"}</Text>
56-
{unit && (
57-
<>
58-
{" "}
59-
<Text className={styles.secondaryColor}>{unit}</Text>
60-
</>
61-
)}
81+
{unit && <Text className={styles.secondaryColor}> {unit}</Text>}
6282
</>
6383
);
6484
}
6585

6686
interface SnapshotTitleProps {
6787
text: string;
6888
}
69-
export function SnapshotTitle({ text }: SnapshotTitleProps) {
70-
return <Text className={clsx(styles.title, styles.ellipsis)}>{text}</Text>;
89+
function SnapshotTitle({ text }: SnapshotTitleProps) {
90+
return <Text className={clsx(styles.leftColumn, styles.title)}>{text}</Text>;
7191
}
7292

7393
interface AccountsRateProps {
@@ -94,7 +114,7 @@ export function AccountsRate({ cumulativeAccounts }: AccountsRateProps) {
94114
}, [accountsPerSecond, cumulativeAccounts]);
95115

96116
return (
97-
<div className={styles.accountsRate}>
117+
<div className={styles.rightColumn}>
98118
<ValueUnitText value={value} unit="Accounts / sec" />
99119
</div>
100120
);
@@ -109,13 +129,13 @@ export function SnapshotTotalComplete({
109129
total,
110130
}: SnapshotTotalCompleteProps) {
111131
return (
112-
<div className={styles.total}>
132+
<Flex className={styles.centerColumn}>
113133
<ValueUnitText value={completed?.value} unit={completed?.unit} />
114134

115135
<Text> / </Text>
116136

117137
<ValueUnitText value={total?.value} unit={total?.unit} />
118-
</div>
138+
</Flex>
119139
);
120140
}
121141

@@ -128,27 +148,30 @@ export function SnapshotThroughput({
128148
throughput,
129149
}: SnapshotThroughputProps) {
130150
return (
131-
<div className={clsx(styles.throughput, { [styles.withPrefix]: !!prefix })}>
151+
<div className={styles.rightColumn}>
132152
{prefix && <Text className={styles.secondaryColor}>{prefix} </Text>}
133153
<ValueUnitText value={throughput?.value} unit={throughput?.unit} />
134154
<Text className={styles.secondaryColor}>/sec</Text>
135155
</div>
136156
);
137157
}
138158

139-
interface SnapshotReadPathProps {
140-
readPath?: string | null;
159+
interface SnapshotPathProps {
160+
path?: string | null;
141161
}
142-
export function SnapshotReadPath({ readPath }: SnapshotReadPathProps) {
162+
export const MSnapshotPath = memo(function SnapshotPath({
163+
path,
164+
}: SnapshotPathProps) {
165+
if (!path) return;
143166
return (
144167
<Flex
145168
align="center"
146169
gap="10px"
147170
wrap="nowrap"
148-
className={styles.readPathContainer}
171+
className={styles.pathContainer}
149172
>
150173
<StorageIcon />
151-
<Text className={clsx(styles.readPath, styles.ellipsis)}>{readPath}</Text>
174+
<Text className={clsx(styles.path, styles.ellipsis)}>{path}</Text>
152175
</Flex>
153176
);
154-
}
177+
});

src/features/StartupProgress/Firedancer/Snapshot/SnapshotDecompressingCard.tsx

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@ import { useEffect } from "react";
44
import {
55
SnapshotBarsCard,
66
SnapshotThroughput,
7-
SnapshotTitle,
87
SnapshotTotalComplete,
98
} from "./SnapshotBarsCard";
10-
import { Flex } from "@radix-ui/themes";
119
import { formatBytes } from "../../../../utils";
12-
import styles from "./snapshot.module.css";
1310
import { useEma } from "../../../../hooks/useEma";
1411

1512
interface SnapshotDecompressingCardProps {
@@ -36,10 +33,6 @@ export function SnapshotDecompressingCard({
3633
resetDecompressed();
3734
}, [phase, resetCompressed, resetDecompressed]);
3835

39-
const compressedThroughputObj =
40-
compressedThroughput == null
41-
? undefined
42-
: formatBytes(compressedThroughput);
4336
const decompressedThroughputObj =
4437
decompressedThroughput == null
4538
? undefined
@@ -49,36 +42,22 @@ export function SnapshotDecompressingCard({
4942
compressedCompleted == null ? undefined : formatBytes(compressedCompleted);
5043
const totalObj =
5144
compressedTotal == null ? undefined : formatBytes(compressedTotal);
45+
const progressPct =
46+
compressedCompleted == null || !compressedTotal
47+
? undefined
48+
: (compressedCompleted / compressedTotal) * 100;
5249

5350
return (
5451
<SnapshotBarsCard
55-
containerClassName={styles.decompressingCard}
52+
title="Decompressing"
53+
progressPct={progressPct}
5654
headerContent={
5755
<>
58-
<Flex
59-
flexGrow="1"
60-
justify="between"
61-
align="center"
62-
className={styles.decompressingCardLeft}
63-
>
64-
<SnapshotTitle text="Decompressing" />
65-
<SnapshotTotalComplete completed={completedObj} total={totalObj} />
66-
</Flex>
67-
<Flex
68-
gapX="30px"
69-
justify="end"
70-
flexGrow="1"
71-
className={styles.decompressingCardRight}
72-
>
73-
<SnapshotThroughput
74-
prefix="Input"
75-
throughput={compressedThroughputObj}
76-
/>
77-
<SnapshotThroughput
78-
prefix="Output"
79-
throughput={decompressedThroughputObj}
80-
/>
81-
</Flex>
56+
<SnapshotTotalComplete completed={completedObj} total={totalObj} />
57+
<SnapshotThroughput
58+
prefix="Output"
59+
throughput={decompressedThroughputObj}
60+
/>
8261
</>
8362
}
8463
throughput={compressedThroughput}

src/features/StartupProgress/Firedancer/Snapshot/SnapshotInsertingCard.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import {
22
AccountsRate,
33
SnapshotBarsCard,
4-
SnapshotThroughput,
5-
SnapshotTitle,
64
SnapshotTotalComplete,
75
} from "./SnapshotBarsCard";
86
import { formatBytes } from "../../../../utils";
9-
import styles from "./snapshot.module.css";
107

118
interface SnapshotInsertingCardProps {
129
decompressedThroughput?: number;
@@ -20,26 +17,26 @@ export function SnapshotInsertingCard({
2017
decompressedTotal,
2118
cumulativeAccounts,
2219
}: SnapshotInsertingCardProps) {
23-
const throughputObj =
24-
decompressedThroughput == null
25-
? undefined
26-
: formatBytes(decompressedThroughput);
2720
const completedObj =
2821
decompressedCompleted == null
2922
? undefined
3023
: formatBytes(decompressedCompleted);
3124
const totalObj =
3225
decompressedTotal == null ? undefined : formatBytes(decompressedTotal);
3326

27+
const progressPct =
28+
decompressedCompleted == null || !decompressedTotal
29+
? undefined
30+
: (decompressedCompleted / decompressedTotal) * 100;
31+
3432
return (
3533
<SnapshotBarsCard
36-
containerClassName={styles.insertingCard}
34+
title="Inserting"
35+
progressPct={progressPct}
3736
headerContent={
3837
<>
39-
<SnapshotTitle text="Inserting" />
40-
<AccountsRate cumulativeAccounts={cumulativeAccounts} />
4138
<SnapshotTotalComplete completed={completedObj} total={totalObj} />
42-
<SnapshotThroughput throughput={throughputObj} />
39+
<AccountsRate cumulativeAccounts={cumulativeAccounts} />
4340
</>
4441
}
4542
throughput={decompressedThroughput}

0 commit comments

Comments
 (0)