Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions src/api/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,25 @@ export const startupProgressSchema = z.object({
waiting_for_supermajority_stake_percent: z.number().nullable(),
});

export const computeUnitsSchema = z.object({
max_compute_units: z.number(),
export const slotTransactionsSchema = z.object({
start_timestamp_nanos: z.coerce.bigint(),
target_end_timestamp_nanos: z.coerce.bigint(),
compute_unit_timestamps_nanos: z.coerce.bigint().array(),
compute_units_deltas: z.number().array(),
active_bank_count: z.number().array(),
txn_mb_start_timestamps_nanos: z.coerce.bigint().array(),
txn_mb_end_timestamps_nanos: z.coerce.bigint().array(),
txn_compute_units_requested: z.number().array(),
txn_max_compute_units: z.number().array(),
txn_compute_units_consumed: z.number().array(),
txn_priority_fee: z.coerce.bigint().array(),
txn_tips: z.coerce.bigint().array(),
txn_error_code: z.number().array(),
txn_from_bundle: z.boolean().array(),
txn_is_simple_vote: z.boolean().array(),
txn_bank_idx: z.number().array(),
txn_start_timestamps_nanos: z.coerce.bigint().array(),
txn_load_end_timestamps_nanos: z.coerce.bigint().array(),
txn_end_timestamps_nanos: z.coerce.bigint().array(),
txn_microblock_id: z.number().array(),
txn_landed: z.boolean().array(),
});

export const slotLevelSchema = z.enum([
Expand All @@ -237,6 +249,7 @@ export const slotPublishSchema = z.object({
priority_fee: z.coerce.bigint().nullable(),
transaction_fee: z.coerce.bigint().nullable(),
tips: z.coerce.bigint().nullable(),
max_compute_units: z.number().nullable(),
compute_units: z.number().nullable(),
duration_nanos: z.number().nullable(),
completed_time_nanos: z.coerce.bigint().nullable(),
Expand Down Expand Up @@ -436,7 +449,7 @@ export const slotResponseSchema = z.object({
waterfall: txnWaterfallSchema.nullable().optional(),
tile_primary_metric: tilePrimaryMetricSchema.nullable().optional(),
tile_timers: tsTileTimersSchema.array().nullable().optional(),
compute_units: computeUnitsSchema.nullable().optional(),
transactions: slotTransactionsSchema.nullable().optional(),
});

export const slotSkippedHistorySchema = z.number().array();
Expand Down
4 changes: 2 additions & 2 deletions src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
versionSchema,
voteDistanceSchema,
voteStateSchema,
computeUnitsSchema,
slotTransactionsSchema,
voteBalanceSchema,
} from "./entities";

Expand Down Expand Up @@ -114,7 +114,7 @@ export interface Peer extends z.infer<typeof peerUpdateSchema> {

export type PeerRemove = z.infer<typeof peerRemoveSchema>;

export type ComputeUnits = z.infer<typeof computeUnitsSchema>;
export type ComputeUnits = z.infer<typeof slotTransactionsSchema>;

export type SlotPublish = z.infer<typeof slotPublishSchema>;

Expand Down
2 changes: 1 addition & 1 deletion src/atoms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export const setSlotResponseAtom = atom(
(_, set, response: SlotResponse) => {
const slot = response.publish.slot;
set(slotResponseAtom, (draft) => {
response.compute_units ??= draft[slot]?.compute_units;
response.transactions ??= draft[slot]?.transactions;
response.tile_primary_metric ??= draft[slot]?.tile_primary_metric;
response.tile_timers ??= draft[slot]?.tile_timers;
response.waterfall ??= draft[slot]?.waterfall;
Expand Down
123 changes: 74 additions & 49 deletions src/features/Overview/SlotPerformance/ComputeUnitsCard/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { AxisDomain, Coordinate } from "recharts/types/util/types";

interface ChartProps {
computeUnits: ComputeUnits;
maxComputeUnits: number;
bankTileCount: number;
}

Expand Down Expand Up @@ -79,33 +80,52 @@ const tickLabelWidth = 110;
const minTickCount = 3;

function getChartData(computeUnits: ComputeUnits): ChartData[] {
const data: ChartData[] = [
{ timestampNanos: 0, computeUnits: 0, activeBankCount: 0 },
];

for (let i = 0; i < computeUnits.compute_unit_timestamps_nanos.length; i++) {
const prev = data[data.length - 1];

if (
prev &&
computeUnits.compute_unit_timestamps_nanos[i - 1] ===
computeUnits.compute_unit_timestamps_nanos[i]
) {
prev.computeUnits += computeUnits.compute_units_deltas[i];
prev.activeBankCount = computeUnits.active_bank_count[i];
} else {
data.push({
timestampNanos: Number(
computeUnits.compute_unit_timestamps_nanos[i] -
computeUnits.start_timestamp_nanos,
),
computeUnits: prev.computeUnits + computeUnits.compute_units_deltas[i],
activeBankCount: computeUnits.active_bank_count[i],
});
}
}

return data;
const events = [
...computeUnits.txn_start_timestamps_nanos.map((timestamp, i) => ({
timestampNanos: timestamp,
txn_idx: i,
start: true,
})),
...computeUnits.txn_end_timestamps_nanos.map((timestamp, i) => ({
timestampNanos: timestamp,
txn_idx: i,
start: false,
})),
].sort((a, b) => Number(a.timestampNanos - b.timestampNanos));

const activeBanks = Array(64).fill(false);
return events.reduce<ChartData[]>(
(chartData, event, i) => {
const txn_idx = event.txn_idx;
const cus_delta = computeUnits.txn_landed[txn_idx]
? event.start
? computeUnits.txn_max_compute_units[txn_idx]
: -computeUnits.txn_max_compute_units[txn_idx] +
computeUnits.txn_compute_units_consumed[txn_idx]
: 0;

const prev = chartData[chartData.length - 1];
activeBanks[computeUnits.txn_bank_idx[txn_idx]] = event.start;
const activeBankCount = activeBanks.filter(
(is_active) => is_active,
).length;

if (i > 0 && events[i - 1].timestampNanos === event.timestampNanos) {
prev.computeUnits += cus_delta;
prev.activeBankCount = activeBankCount;
} else {
chartData.push({
timestampNanos: Number(
event.timestampNanos - computeUnits.start_timestamp_nanos,
),
computeUnits: prev.computeUnits + cus_delta,
activeBankCount,
});
}
return chartData;
},
[{ timestampNanos: 0, computeUnits: 0, activeBankCount: 0 }],
);
}

const getXTicks = memoize(function getXTicks(
Expand Down Expand Up @@ -202,6 +222,7 @@ function getBankCount({

function getSegments(
computeUnits: ComputeUnits,
maxComputeUnits: number,
bankTileCount: number,
xDomain: Domain,
yDomain: Domain,
Expand All @@ -219,24 +240,24 @@ function getSegments(
ts,
bankCount,
tEnd,
maxComputeUnits: computeUnits.max_compute_units,
maxComputeUnits: maxComputeUnits,
});
};

for (let bankCount = 1; bankCount <= bankTileCount; bankCount++) {
const y0Ts = getTsByCu({
computeUnits: yDomain[0],
tEnd,
maxComputeUnits: computeUnits.max_compute_units,
maxComputeUnits: maxComputeUnits,
bankCount,
});
const t0X = withinDomain(xDomain, y0Ts) ? y0Ts : xDomain[0];
const t0Y = getCusAtTs(t0X, bankCount);

const y1Ts = getTsByCu({
computeUnits: Math.min(yDomain[1], computeUnits.max_compute_units),
computeUnits: Math.min(yDomain[1], maxComputeUnits),
tEnd,
maxComputeUnits: computeUnits.max_compute_units,
maxComputeUnits: maxComputeUnits,
bankCount,
});

Expand Down Expand Up @@ -287,7 +308,11 @@ function getPolygonPoints(
return resPoints;
}

export default function Chart({ computeUnits, bankTileCount }: ChartProps) {
export default function Chart({
computeUnits,
maxComputeUnits,
bankTileCount,
}: ChartProps) {
const isMouseDownRef = useRef(false);
const [isModKeyDown, setIsModKeyDown] = useState(false);
const [isPanning, setIsPanning] = useState(false);
Expand Down Expand Up @@ -352,20 +377,25 @@ export default function Chart({ computeUnits, bankTileCount }: ChartProps) {

const cuDomain = useMemo(
() =>
fitYToData
? getDataDomain(data, computeUnits.max_compute_units, zoomRange)
: undefined,
[computeUnits.max_compute_units, data, fitYToData, zoomRange],
fitYToData ? getDataDomain(data, maxComputeUnits, zoomRange) : undefined,
[maxComputeUnits, data, fitYToData, zoomRange],
);

const yDomain = useMemo<Domain>(
() => cuDomain ?? [0, computeUnits.max_compute_units + 1_000_000],
[computeUnits.max_compute_units, cuDomain],
() => cuDomain ?? [0, maxComputeUnits + 1_000_000],
[maxComputeUnits, cuDomain],
);

const segments = useMemo(
() => getSegments(computeUnits, bankTileCount, xDomain, yDomain),
[bankTileCount, computeUnits, xDomain, yDomain],
() =>
getSegments(
computeUnits,
maxComputeUnits,
bankTileCount,
xDomain,
yDomain,
),
[bankTileCount, computeUnits, maxComputeUnits, xDomain, yDomain],
);

const activeBankCountTicks = new Array(bankTileCount)
Expand Down Expand Up @@ -694,12 +724,7 @@ export default function Chart({ computeUnits, bankTileCount }: ChartProps) {
const useActiveBanksMdStroke =
!useActiveBanksLargeStroke && xDomain[1] - xDomain[0] < mdNanosThreshold;

const tEnd =
0.95 *
Number(
computeUnits.target_end_timestamp_nanos -
computeUnits.start_timestamp_nanos,
);
const tEnd = 0.95 * slotDurationNanos;

const prevPolyPoints = useRef<[Coordinate, Coordinate][]>([]);
prevPolyPoints.current = [];
Expand Down Expand Up @@ -770,7 +795,7 @@ export default function Chart({ computeUnits, bankTileCount }: ChartProps) {
x1={xDomain[0]}
x2={xDomain[1]}
y1={yDomain[0]}
y2={Math.min(yDomain[1], computeUnits.max_compute_units)}
y2={Math.min(yDomain[1], maxComputeUnits)}
shape={(props) => {
graphRectProps.current = props as RectangleProps;
return <></>;
Expand Down Expand Up @@ -835,7 +860,7 @@ export default function Chart({ computeUnits, bankTileCount }: ChartProps) {
computeUnits: yDomain[1] - yDomain[0] + yDomain[0],
ts: xDomain[1] - xDomain[0] + xDomain[0],
tEnd,
maxComputeUnits: computeUnits.max_compute_units,
maxComputeUnits: maxComputeUnits,
}),
),
);
Expand Down Expand Up @@ -884,7 +909,7 @@ export default function Chart({ computeUnits, bankTileCount }: ChartProps) {
}}
/>
<ReferenceLine
y={computeUnits.max_compute_units}
y={maxComputeUnits}
stroke="#2a7edf"
strokeDasharray="3 3"
yAxisId={cuAxisId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function ComputeUnitsCard() {
const tileCount = useAtomValue(tileCountAtom);
const bankTileCount = tileCount["bank"];

if (!slot || !query.response?.compute_units) return null;
if (!slot || !query.response?.transactions) return null;

return (
<Card style={{ marginTop: "8px" }}>
Expand All @@ -27,7 +27,10 @@ export default function ComputeUnitsCard() {
</Flex>
<div className={styles.chart}>
<Chart
computeUnits={query.response.compute_units}
computeUnits={query.response.transactions}
maxComputeUnits={
query.response.publish.max_compute_units ?? 48_000_000
}
bankTileCount={bankTileCount}
/>
<Legend bankTileCount={bankTileCount} />
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSlotQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function useSlotQueryResponse(slot?: number) {
const response = useAtomValue(
useMemo(() => getSlotResponseAtom(slot), [slot]),
);
const skipQuery = !!response?.compute_units;
const skipQuery = !!response?.transactions;

const { hasWaitedForData } = useSlotQuery(slot, true, skipQuery);

Expand Down