| 1 | import { NodeId, PlanId, ProjectId, RunId } from "@t3tools/contracts"; |
| 2 | import { |
| 3 | getLatestThreadForProject, |
| 4 | sortActiveThreadsByOrderKey, |
| 5 | sortPinnedThreadsByOrderKey, |
| 6 | sortThreads, |
| 7 | } from "@t3tools/client-runtime/state/thread-sort"; |
| 8 | import { formatHourShort, formatRelativeHourShort } from "@t3tools/shared/usageFormat"; |
| 9 | import { describe, test } from "vite-plus/test"; |
| 10 | |
| 11 | import { makeThreadProjectionFixture } from "./test-fixtures"; |
| 12 | import { deriveActivePlanState } from "./session-logic"; |
| 13 | |
| 14 | const projectId = ProjectId.make("benchmark-project"); |
| 15 | const runId = RunId.make("benchmark-run"); |
| 16 | const start = Date.parse("2026-08-11T00:00:00.000Z"); |
| 17 | const threads = Array.from({ length: 1_000 }, (_, index) => { |
| 18 | const timestamp = new Date(start + ((index * 997) % 1_000) * 60_000).toISOString(); |
| 19 | return { |
| 20 | id: `thread-${index}`, |
| 21 | projectId, |
| 22 | archivedAt: null, |
| 23 | createdAt: timestamp, |
| 24 | updatedAt: timestamp, |
| 25 | latestUserMessageAt: timestamp, |
| 26 | unsettledAt: null, |
| 27 | }; |
| 28 | }); |
| 29 | const baseProjection = makeThreadProjectionFixture(); |
| 30 | const projection = { |
| 31 | ...baseProjection, |
| 32 | plans: Array.from({ length: 5 }, (_, index) => ({ |
| 33 | id: PlanId.make(`plan-${index}`), |
| 34 | runId, |
| 35 | threadId: baseProjection.thread.id, |
| 36 | nodeId: NodeId.make("bench-node"), |
| 37 | status: "active" as const, |
| 38 | kind: "todo_list" as const, |
| 39 | steps: [{ id: "check", text: "Run checks", status: "running" as const }], |
| 40 | })), |
| 41 | }; |
| 42 | const hours = Array.from({ length: 24 }, (_, index) => |
| 43 | new Date(start + index * 3_600_000).toISOString(), |
| 44 | ); |
| 45 | const referenceTime = "2026-08-12T00:00:00.000Z"; |
| 46 | |
| 47 | describe("client performance", () => { |
| 48 | test("sort 1000 threads by recent activity", async ({ bench }) => { |
| 49 | await bench("sort", () => { |
| 50 | sortThreads(threads, "updated_at"); |
| 51 | }).run(); |
| 52 | }); |
| 53 | test("sort 1000 active threads", async ({ bench }) => { |
| 54 | await bench("sort", () => { |
| 55 | sortActiveThreadsByOrderKey(threads); |
| 56 | }).run(); |
| 57 | }); |
| 58 | test("sort 1000 keyless pinned threads", async ({ bench }) => { |
| 59 | await bench("sort", () => { |
| 60 | sortPinnedThreadsByOrderKey(threads); |
| 61 | }).run(); |
| 62 | }); |
| 63 | test("select latest project thread from 1000 threads", async ({ bench }) => { |
| 64 | await bench("select", () => { |
| 65 | getLatestThreadForProject(threads, projectId, "updated_at"); |
| 66 | }).run(); |
| 67 | }); |
| 68 | test("derive current plan from 5 normalized plans", async ({ bench }) => { |
| 69 | await bench("derive", () => { |
| 70 | deriveActivePlanState(projection, runId); |
| 71 | }).run(); |
| 72 | }); |
| 73 | test("format 24 hourly usage labels and tooltips", async ({ bench }) => { |
| 74 | await bench("format", () => { |
| 75 | hours.map((hour) => [ |
| 76 | formatHourShort(hour, "America/New_York"), |
| 77 | formatRelativeHourShort(hour, referenceTime, "America/New_York"), |
| 78 | ]); |
| 79 | }).run(); |
| 80 | }); |
| 81 | }); |