Skip to content

Commit b48577f

Browse files
authored
Merge pull request #102 from pylon-code/fix/session-logic-perf-test
test(web): compare work log update cost against a from-scratch derive
2 parents 486065e + a2b1d18 commit b48577f

1 file changed

Lines changed: 57 additions & 36 deletions

File tree

apps/web/src/session-logic.test.ts

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2353,43 +2353,64 @@ describe("session activity performance", () => {
23532353
expect(appendedEntries[1]).toBe(initialEntries[1]);
23542354
});
23552355

2356-
it("updates 20,000 ordered tool activities within 100 ms", () => {
2357-
const activities = Array.from({ length: 20_000 }, (_, index) =>
2358-
makeActivity({
2359-
id: `benchmark-tool-${index}`,
2360-
createdAt: new Date(1_700_000_000_000 + index).toISOString(),
2361-
kind: "tool.completed",
2362-
summary: "Ran command",
2363-
sequence: index,
2364-
payload: {
2365-
itemType: "command_execution",
2366-
title: "Ran command",
2367-
data: {
2368-
toolCallId: `benchmark-tool-${index}`,
2369-
item: { command: ["git", "status"] },
2356+
it("updates 20,000 ordered tool activities far faster than deriving them from scratch", () => {
2357+
const makeActivities = (count: number, prefix: string) =>
2358+
Array.from({ length: count }, (_, index) =>
2359+
makeActivity({
2360+
id: `${prefix}-${index}`,
2361+
createdAt: new Date(1_700_000_000_000 + index).toISOString(),
2362+
kind: "tool.completed",
2363+
summary: "Ran command",
2364+
sequence: index,
2365+
payload: {
2366+
itemType: "command_execution",
2367+
title: "Ran command",
2368+
data: { toolCallId: `${prefix}-${index}`, item: { command: ["git", "status"] } },
23702369
},
2371-
},
2372-
}),
2373-
);
2374-
deriveWorkLogEntries(activities);
2375-
const updatedActivities = [
2376-
...activities,
2377-
makeActivity({
2378-
id: "benchmark-tool-appended",
2379-
createdAt: new Date(1_700_000_000_000 + activities.length).toISOString(),
2380-
kind: "tool.completed",
2381-
summary: "Ran command",
2382-
sequence: activities.length,
2383-
payload: {
2384-
itemType: "command_execution",
2385-
title: "Ran command",
2386-
data: { toolCallId: "benchmark-tool-appended", item: { command: ["git", "diff"] } },
2387-
},
2388-
}),
2389-
];
2370+
}),
2371+
);
2372+
2373+
// Wall-clock on a shared CI runner swings several-fold between runs (the
2374+
// old 100 ms bound measured 100-108 ms on a 4-vCPU hosted runner for work
2375+
// that takes 4 ms on a quiet laptop), so compare the update against a
2376+
// from-scratch derivation measured in the same process instead. Best of
2377+
// three rounds shrugs off a GC pause or scheduling stall in any one
2378+
// sample. With the per-activity cache an update is roughly 6-8x cheaper;
2379+
// without it both calls walk the same code path and the ratio is ~1.
2380+
let fromScratchMs = Number.POSITIVE_INFINITY;
2381+
let updateMs = Number.POSITIVE_INFINITY;
2382+
for (let round = 0; round < 3; round++) {
2383+
const activities = makeActivities(20_000, `benchmark-tool-${round}`);
2384+
deriveWorkLogEntries(activities);
2385+
const updatedActivities = [
2386+
...activities,
2387+
makeActivity({
2388+
id: `benchmark-tool-appended-${round}`,
2389+
createdAt: new Date(1_700_000_000_000 + activities.length).toISOString(),
2390+
kind: "tool.completed",
2391+
summary: "Ran command",
2392+
sequence: activities.length,
2393+
payload: {
2394+
itemType: "command_execution",
2395+
title: "Ran command",
2396+
data: {
2397+
toolCallId: `benchmark-tool-appended-${round}`,
2398+
item: { command: ["git", "diff"] },
2399+
},
2400+
},
2401+
}),
2402+
];
2403+
2404+
const updateStartedAt = performance.now();
2405+
expect(deriveWorkLogEntries(updatedActivities)).toHaveLength(20_001);
2406+
updateMs = Math.min(updateMs, performance.now() - updateStartedAt);
2407+
2408+
const fresh = makeActivities(20_001, `benchmark-fresh-${round}`);
2409+
const fromScratchStartedAt = performance.now();
2410+
expect(deriveWorkLogEntries(fresh)).toHaveLength(20_001);
2411+
fromScratchMs = Math.min(fromScratchMs, performance.now() - fromScratchStartedAt);
2412+
}
23902413

2391-
const startedAt = performance.now();
2392-
expect(deriveWorkLogEntries(updatedActivities)).toHaveLength(20_001);
2393-
expect(performance.now() - startedAt).toBeLessThan(100);
2414+
expect(updateMs).toBeLessThan(fromScratchMs / 2);
23942415
});
23952416
});

0 commit comments

Comments
 (0)