From 8bc59c04fd112cd76c4a2398fc09a5b823b5ef20 Mon Sep 17 00:00:00 2001 From: Mark Saroufim Date: Wed, 11 Nov 2026 20:48:59 -0800 Subject: [PATCH] Sort GPU displays by newest supported type --- frontend/src/api/api.ts | 20 +++++++++++++++++-- frontend/src/lib/utils/gpu.ts | 11 ++++++++++ .../leaderboard/components/UserTrendChart.tsx | 7 ++++--- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 frontend/src/lib/utils/gpu.ts diff --git a/frontend/src/api/api.ts b/frontend/src/api/api.ts index c7ef9b6f..9b98e25f 100644 --- a/frontend/src/api/api.ts +++ b/frontend/src/api/api.ts @@ -1,4 +1,5 @@ import type { User } from "../lib/types/user"; +import { compareGpuTypes } from "../lib/utils/gpu"; export class APIError extends Error { status: number; @@ -117,7 +118,15 @@ export async function fetchLeaderBoard(id: string): Promise { `[Perf] fetchLeaderBoard id=${id} | fetch=${fetchTime.toFixed(2)}ms | parse=${parseTime.toFixed(2)}ms | total=${totalTime.toFixed(2)}ms`, ); - return r.data; + const data: LeaderboardDetail = r.data; + return { + ...data, + gpu_types: [...data.gpu_types].sort(compareGpuTypes), + // JSON object key order is not a GPU display order; normalize it for every page. + rankings: Object.fromEntries( + Object.entries(data.rankings).sort(([a], [b]) => compareGpuTypes(a, b)), + ), + }; } export async function fetchCodes( @@ -192,7 +201,14 @@ export async function fetchLeaderboardSummaries( `[Perf] fetchLeaderboardSummaries (${version}| ${forceRefreshCache})( | fetch=${fetchTime.toFixed(2)}ms | parse=${parseTime.toFixed(2)}ms | total=${totalTime.toFixed(2)}ms`, ); - return r.data; + const data: LeaderboardSummariesResponse = r.data; + return { + ...data, + leaderboards: data.leaderboards.map((leaderboard) => ({ + ...leaderboard, + gpu_types: [...leaderboard.gpu_types].sort(compareGpuTypes), + })), + }; } export async function getMe(): Promise { diff --git a/frontend/src/lib/utils/gpu.ts b/frontend/src/lib/utils/gpu.ts new file mode 100644 index 00000000..c4bb4df4 --- /dev/null +++ b/frontend/src/lib/utils/gpu.ts @@ -0,0 +1,11 @@ +// Keep GPU displays consistent with the leaderboard summary priority. +const GPU_ORDER = ["B200", "H100", "MI300", "A100", "L4", "T4"]; + +export function compareGpuTypes(a: string, b: string): number { + const aIndex = GPU_ORDER.indexOf(a.trim().toUpperCase()); + const bIndex = GPU_ORDER.indexOf(b.trim().toUpperCase()); + const aPriority = aIndex === -1 ? GPU_ORDER.length : aIndex; + const bPriority = bIndex === -1 ? GPU_ORDER.length : bIndex; + + return aPriority - bPriority || a.localeCompare(b); +} diff --git a/frontend/src/pages/leaderboard/components/UserTrendChart.tsx b/frontend/src/pages/leaderboard/components/UserTrendChart.tsx index 9c5522f6..91c9cb99 100644 --- a/frontend/src/pages/leaderboard/components/UserTrendChart.tsx +++ b/frontend/src/pages/leaderboard/components/UserTrendChart.tsx @@ -36,6 +36,7 @@ import { type UserSearchResult, } from "../../../api/api"; import { isExpired } from "../../../lib/date/utils"; +import { compareGpuTypes } from "../../../lib/utils/gpu"; import { formatMicrosecondsNum, formatMicroseconds } from "../../../lib/utils/ranking"; import { useThemeStore } from "../../../lib/store/themeStore"; import type { @@ -266,7 +267,7 @@ export default function UserTrendChart({ leaderboardId, defaultUsers, defaultGpu const fastestTrendGpuTypes = fastestTrendData?.time_series ? Object.keys(fastestTrendData.time_series) : []; const gpuTypesFromUsers = data?.time_series ? Object.keys(data.time_series) : []; const gpuTypesFromCustom = customData?.time_series ? Object.keys(customData.time_series) : []; - const allGpuTypes = [...new Set([...gpuTypesFromUsers, ...gpuTypesFromCustom, ...fastestTrendGpuTypes])]; + const allGpuTypes = [...new Set([...gpuTypesFromUsers, ...gpuTypesFromCustom, ...fastestTrendGpuTypes])].sort(compareGpuTypes); return selectedGpuType || allGpuTypes[0] || ""; }, [selectedGpuType, data, customData, fastestTrendData]); @@ -423,7 +424,7 @@ export default function UserTrendChart({ leaderboardId, defaultUsers, defaultGpu const result = await fetchUserTrend(leaderboardId, userIds); setData(result); // Set default GPU type to the one with the most unique users - const gpuTypes = Object.keys(result.time_series || {}); + const gpuTypes = Object.keys(result.time_series || {}).sort(compareGpuTypes); if (gpuTypes.length > 0 && !gpuTypes.includes(selectedGpuType)) { // Count unique users per GPU type let maxUsers = 0; @@ -566,7 +567,7 @@ export default function UserTrendChart({ leaderboardId, defaultUsers, defaultGpu // GPU types from user data or custom data const gpuTypesFromUsers = data?.time_series ? Object.keys(data.time_series) : []; const gpuTypesFromCustom = customData?.time_series ? Object.keys(customData.time_series) : []; - const gpuTypes = [...new Set([...gpuTypesFromUsers, ...gpuTypesFromCustom])]; + const gpuTypes = [...new Set([...gpuTypesFromUsers, ...gpuTypesFromCustom])].sort(compareGpuTypes); // Apply axis range from input fields const handleApplyAxisRange = () => {