session-timeline-benchmark.spec.ts 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import { benchmark, benchmarkDiagnostics, expect } from "../benchmark"
  2. import {
  3. buildInitialStreamEvent,
  4. buildStreamDeltaEvents,
  5. setupTimelineBenchmark,
  6. textPartID,
  7. } from "./session-timeline-benchmark.fixture"
  8. import { startTimelineProfile } from "./session-timeline-profile"
  9. import {
  10. collectTimelineStreamMetrics,
  11. installTimelineStreamProbe,
  12. startTimelineStreamProbe,
  13. } from "./session-timeline-stream-probe"
  14. benchmark.describe("performance: session timeline streaming", () => {
  15. benchmark("streams assistant text without remounting or oscillating", async ({ page, report }) => {
  16. benchmark.setTimeout(480_000)
  17. const cpuThrottle = Number(process.env.TIMELINE_CPU_THROTTLE ?? 30)
  18. const deltaCount = Number(process.env.TIMELINE_DELTA_COUNT ?? 160)
  19. const historyTurns = Number(process.env.TIMELINE_HISTORY_TURNS ?? 320)
  20. const eventBatch = Number(process.env.TIMELINE_EVENT_BATCH ?? 1)
  21. const minimal = process.env.TIMELINE_MINIMAL === "1"
  22. const profileCPU = process.env.TIMELINE_CPU_PROFILE === "1"
  23. const profileVisual = !minimal && profileCPU && process.env.TIMELINE_VISUAL_PROFILE !== "0"
  24. const fixture = await setupTimelineBenchmark(page, {
  25. historyTurns,
  26. eventBatch,
  27. })
  28. fixture.transport.enqueue(buildInitialStreamEvent(deltaCount))
  29. const contentStart = performance.now()
  30. await expect(fixture.text).toBeVisible()
  31. await expect(fixture.text).toContainText("Implementation plan")
  32. const initialContentObservedMs = performance.now() - contentStart
  33. await fixture.scrollToBottom()
  34. await fixture.waitForStableGeometry()
  35. const profile = await startTimelineProfile(page, { cpuThrottle, profileCPU })
  36. await installTimelineStreamProbe(page, { textPartID, finalIndex: deltaCount, profileVisual, minimal })
  37. const deltas = buildStreamDeltaEvents(deltaCount)
  38. await startTimelineStreamProbe(page)
  39. fixture.transport.enqueue(deltas)
  40. await page.waitForFunction(
  41. (finalIndex) =>
  42. (
  43. window as Window & {
  44. __timelineStreamBenchmark?: { applied: { index: number }[] }
  45. }
  46. ).__timelineStreamBenchmark?.applied.some((value) => value.index === finalIndex),
  47. deltaCount,
  48. { timeout: 420_000 },
  49. )
  50. await expect(fixture.text).toContainText("benchmark-complete")
  51. await expect(fixture.text).toContainText("Streaming")
  52. await fixture.waitForStableGeometry()
  53. const metrics = await collectTimelineStreamMetrics(page, {
  54. textPartID,
  55. finalIndex: deltaCount,
  56. navigations: benchmarkDiagnostics(page).navigations,
  57. })
  58. const delivered = deltas.length - fixture.transport.pendingCount()
  59. await profile.stop()
  60. report(
  61. {
  62. endToEndInitialContentObservedMs: initialContentObservedMs,
  63. ...metrics,
  64. deliveredDeltas: delivered,
  65. pendingDeltas: fixture.transport.pendingCount(),
  66. },
  67. {
  68. cpuThrottle,
  69. profileCPU,
  70. profileVisual,
  71. minimal,
  72. queuedDeltas: deltas.length,
  73. historyTurns,
  74. eventBatch,
  75. },
  76. )
  77. await profile.reset()
  78. })
  79. })