Skip to content

test: stabilize codspeed memory benchmarks - #7988

Open
Sheraff wants to merge 10 commits into
mainfrom
test-codspeed-memory-stabilization
Open

test: stabilize codspeed memory benchmarks#7988
Sheraff wants to merge 10 commits into
mainfrom
test-codspeed-memory-stabilization

Conversation

@Sheraff

@Sheraff Sheraff commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • Benchmark Improvements

    • Memory benchmarks now run in fresh, isolated processes for more consistent results.
    • Client and server scenarios across React, Solid, and Vue use standardized execution.
    • Added deterministic warmups, expanded workload coverage, improved cleanup, and stronger memory validation.
    • Flame profiling now begins after setup and warmup work for more focused results.
    • Benchmark failures and workload errors are reported more reliably.
  • Documentation

    • Added guidance for process isolation, deterministic execution, cleanup, and benchmark interpretation.
  • Tests

    • Added coverage for restarts, failures, cleanup, and invalid workload selections.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds isolated child-process execution for memory benchmarks. It adds shared client and server registration helpers, deterministic warmup flows, scenario migrations, IPC and lifecycle tests, configuration updates, and execution-model documentation.

Changes

Memory benchmark isolation

Layer / File(s) Summary
Process runtime and IPC contracts
benchmarks/memory/shared/*
Adds parent and child process coordination, workload validation, measurement preparation, IPC execution, error propagation, and shutdown handling.
Warmup contracts and workload loops
benchmarks/memory/client/benchmark.ts, benchmarks/memory/client/scenarios/*/shared.ts, benchmarks/memory/server/benchmark.ts, benchmarks/memory/server/scenarios/*/shared.ts, benchmarks/memory/*/flame-runner.ts
Adds warmup callbacks, deterministic warmup data, reusable workload loops, larger measured iteration counts, and warmup execution before profiling.
Client benchmark registration and migration
benchmarks/memory/client/isolated-benchmark.ts, benchmarks/memory/client/scenarios/*, benchmarks/memory/client/package.json, benchmarks/memory/client/tsconfig.json
Adds isolated client registration and migrates client scenarios to setup URLs and Node-based Vitest environments.
Server benchmark registration and validation
benchmarks/memory/server/isolated-benchmark.ts, benchmarks/memory/server/scenarios/*, benchmarks/memory/server/isolated-process.test.ts, benchmarks/memory/server/test-fixtures/*, benchmarks/memory/server/package.json, benchmarks/memory/server/tsconfig.json
Adds isolated server registration, migrates server scenarios, and adds fixtures, lifecycle tests, package targets, and TypeScript coverage.
Execution model documentation
benchmarks/memory/README.md
Documents fresh child processes, deterministic setup, cleanup, measured loops, heap checks, and profiling boundaries.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Vitest
  participant BenchmarkRegistrar
  participant IsolatedMemoryProcess
  participant isolated-process-child
  participant Workload
  Vitest->>BenchmarkRegistrar: register benchmark
  BenchmarkRegistrar->>IsolatedMemoryProcess: start isolated process
  IsolatedMemoryProcess->>isolated-process-child: send run command
  isolated-process-child->>Workload: execute workload
  Workload-->>isolated-process-child: complete or throw
  isolated-process-child-->>IsolatedMemoryProcess: return result or error
  IsolatedMemoryProcess-->>BenchmarkRegistrar: resolve or reject benchmark
  BenchmarkRegistrar-->>Vitest: complete benchmark lifecycle
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: stabilizing CodSpeed memory benchmarks through isolated processes and warmups.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test-codspeed-memory-stabilization

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
benchmarks/memory/shared/isolated-process.ts (2)

192-196: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Await child exit in the failure path.

child.kill() only requests termination. start() returns before the child exits, so a failed start can leave a live process that competes for memory with the next run. #waitForExit already handles the exit transition safely.

♻️ Proposed change
     } catch (error) {
+      const exit = this.#waitForExit(child)
       child.kill()
       this.#child = undefined
+      await exit.catch(() => {})
       throw error
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/shared/isolated-process.ts` around lines 192 - 196, Update
the catch block in start() to await `#waitForExit` after requesting child
termination, ensuring the failed child has fully exited before rethrowing the
original error. Preserve the existing child reference cleanup and error
propagation.

295-347: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider a timeout for IPC waits.

#waitForMessage settles only on a message, an error, or child exit. If a workload stalls, run() and stop() never settle, and the failure surfaces later as an opaque runner timeout. A bounded wait that kills the child and rejects with the workload name would make the failure diagnosable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/shared/isolated-process.ts` around lines 295 - 347, Add a
bounded timeout to `#waitForMessage` so stalled IPC waits terminate
deterministically. On timeout, clean up listeners, kill the child process, and
reject with an error that includes the workload name; also clear the timer
whenever the wait settles through a message, error, or exit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/memory/client/isolated-benchmark.ts`:
- Around line 31-38: Update the memory benchmark suite around isolatedProcess to
remove or neutralize the describe-level beforeEach and afterEach hooks, leaving
lifecycle management exclusively to the setup and teardown callbacks in bench
options. Preserve the existing isolatedProcess.start() and
isolatedProcess.stop() calls in those Tinybench callbacks.

In `@benchmarks/memory/server/isolated-process.test.ts`:
- Around line 24-28: Update the afterEach cleanup around runner.stop() so
environment-variable deletion and temporary-directory removal always execute in
a finally block, even when stop() rejects. Also reset the runner reference
during cleanup, using the existing runner and tempDirectory symbols.

In `@benchmarks/memory/shared/isolated-process-child.ts`:
- Around line 222-250: Update the commandQueue chain around the message handler
so failures from either the main operation or the catch-block send are contained
at every link. Reuse the handler for both fulfillment and rejection, e.g. attach
it as both callbacks to commandQueue.then, and ensure the error-reporting send
cannot leave the chain rejected so later run and stop messages continue
processing.

---

Nitpick comments:
In `@benchmarks/memory/shared/isolated-process.ts`:
- Around line 192-196: Update the catch block in start() to await `#waitForExit`
after requesting child termination, ensuring the failed child has fully exited
before rethrowing the original error. Preserve the existing child reference
cleanup and error propagation.
- Around line 295-347: Add a bounded timeout to `#waitForMessage` so stalled IPC
waits terminate deterministically. On timeout, clean up listeners, kill the
child process, and reject with an error that includes the workload name; also
clear the timer whenever the wait settles through a message, error, or exit.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fc9d0b9f-7700-4377-a465-1174a1582619

📥 Commits

Reviewing files that changed from the base of the PR and between abf9b81 and 300581b.

📒 Files selected for processing (64)
  • benchmarks/memory/README.md
  • benchmarks/memory/client/isolated-benchmark.ts
  • benchmarks/memory/client/package.json
  • benchmarks/memory/client/scenarios/interrupted-navigations/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/react/vite.config.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/vue/vite.config.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/react/vite.config.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/vue/vite.config.ts
  • benchmarks/memory/client/scenarios/mount-unmount/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/mount-unmount/react/vite.config.ts
  • benchmarks/memory/client/scenarios/mount-unmount/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/mount-unmount/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/mount-unmount/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/mount-unmount/vue/vite.config.ts
  • benchmarks/memory/client/scenarios/navigation-churn/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/navigation-churn/react/vite.config.ts
  • benchmarks/memory/client/scenarios/navigation-churn/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/navigation-churn/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/navigation-churn/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/navigation-churn/vue/vite.config.ts
  • benchmarks/memory/client/scenarios/preload-churn/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/preload-churn/react/vite.config.ts
  • benchmarks/memory/client/scenarios/preload-churn/shared.ts
  • benchmarks/memory/client/scenarios/preload-churn/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/preload-churn/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/preload-churn/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/preload-churn/vue/vite.config.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/react/memory.bench.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/react/vite.config.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/shared.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/solid/memory.bench.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/solid/vite.config.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/vue/memory.bench.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/vue/vite.config.ts
  • benchmarks/memory/client/tsconfig.json
  • benchmarks/memory/server/isolated-benchmark.ts
  • benchmarks/memory/server/isolated-process.test.ts
  • benchmarks/memory/server/package.json
  • benchmarks/memory/server/scenarios/aborted-requests/react/memory.bench.ts
  • benchmarks/memory/server/scenarios/aborted-requests/solid/memory.bench.ts
  • benchmarks/memory/server/scenarios/aborted-requests/vue/memory.bench.ts
  • benchmarks/memory/server/scenarios/error-paths/react/memory.bench.ts
  • benchmarks/memory/server/scenarios/error-paths/shared.ts
  • benchmarks/memory/server/scenarios/error-paths/solid/memory.bench.ts
  • benchmarks/memory/server/scenarios/error-paths/vue/memory.bench.ts
  • benchmarks/memory/server/scenarios/request-churn/react/memory.bench.ts
  • benchmarks/memory/server/scenarios/request-churn/shared.ts
  • benchmarks/memory/server/scenarios/request-churn/solid/memory.bench.ts
  • benchmarks/memory/server/scenarios/request-churn/vue/memory.bench.ts
  • benchmarks/memory/server/scenarios/server-fn-churn/react/memory.bench.ts
  • benchmarks/memory/server/scenarios/server-fn-churn/solid/memory.bench.ts
  • benchmarks/memory/server/scenarios/server-fn-churn/vue/memory.bench.ts
  • benchmarks/memory/server/test-fixtures/isolated-process-setup.ts
  • benchmarks/memory/server/tsconfig.json
  • benchmarks/memory/shared/isolated-process-child.ts
  • benchmarks/memory/shared/isolated-process.ts
  • benchmarks/memory/shared/tsconfig.json

Comment on lines +31 to +38
describe('memory', () => {
beforeEach(() => isolatedProcess.start())
afterEach(() => isolatedProcess.stop())

bench(options.name, run, {
...memoryBenchOptions,
setup: () => isolatedProcess.start(),
teardown: () => isolatedProcess.stop(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For Vitest 4.1.4 benchmark files, verify whether suite-level beforeEach/afterEach hooks run around bench() tasks and whether Tinybench setup/teardown run for each benchmark cycle.

💡 Result:

In Vitest 4.1.4, the behavior of suite-level hooks and Tinybench setup/teardown in benchmark files is as follows: Suite-Level Hooks (beforeEach/afterEach) Historically, Vitest's suite-level beforeEach and afterEach hooks did not run for bench tasks [1]. While there have been community efforts and pull requests (such as PR #7541) aimed at enabling this functionality, these hooks are generally not standardly supported or guaranteed to execute around benchmark tasks in the same way they do for test blocks [1][2][3]. Benchmark execution in Vitest has historically followed a distinct lifecycle from standard tests [1][3]. Tinybench Setup/Teardown Tinybench, which powers Vitest's benchmarking, explicitly provides setup and teardown options [4][5][6]. These are configured as part of the third argument (options object) passed to the bench function [4][5]. According to Tinybench documentation, these setup and teardown functions are designed to run for each benchmark cycle (task execution) [6][7][8]. They are intended for operations that need to occur immediately before and after the specific code being measured, allowing users to handle stateful setups that should not be included in the timed performance result [3][6]. In summary, you should rely on the explicit setup and teardown options provided in the bench function's configuration object to manage cycle-specific logic, rather than relying on suite-level beforeEach/afterEach hooks [3][4][6]. Top Results: [1][2][3][4][6]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate files:"
fd -a 'isolated-benchmark\.ts$|isolated.*memory.*\.ts$|memory.*\.ts$' . | sed 's#^\./##' | head -100

echo
echo "Target file outline:"
ast-grep outline benchmarks/memory/client/isolated-benchmark.ts --view compact || true

echo
echo "Target file lines:"
cat -n benchmarks/memory/client/isolated-benchmark.ts | sed -n '1,120p'

echo
echo "Search isolated process definitions/usages:"
rg -n "class IsolatedMemoryProcess|IsolatedMemoryProcess|start\(|stop\(|isolatedProcess|bench\\(" -S benchmarks . --glob '*.ts' --glob '!node_modules' | head -200

Repository: TanStack/router

Length of output: 25556


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Vitest version declarations:"
for f in package.json pnpm-lock.yaml yarn.lock package-lock.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    if [ "$f" = "package.json" ]; then
      node -e "const p=require('./package.json'); console.log({devDependencies:p.devDependencies?.vitest, dependencies:p.dependencies?.vitest, scripts:p.scripts});" 2>/dev/null || sed -n '/vitest/p' "$f"
    else
      rg -n "vitest(@|:)|version:" "$f" | head -80
    fi
  fi
done

echo
echo "Shared process start/stop implementation:"
cat -n benchmarks/memory/shared/isolated-process.ts | sed -n '140,235p'

echo
echo "Isolated process tests around duplicate start:"
cat -n benchmarks/memory/server/isolated-process.test.ts | sed -n '1,130p'

echo
echo "Memory bench options:"
cat -n benchmarks/memory/client/bench-utils.ts | sed -n '1,120p'

echo
echo "Server isolated benchmark counterpart:"
cat -n benchmarks/memory/server/isolated-benchmark.ts | sed -n '1,70p'

Repository: TanStack/router

Length of output: 10199


Use Tinybench setup/teardown for the isolated lifecycle.

In Vitest 4 benchmark mode, keep the setup and teardown in the bench() options, but remove the suite beforeEach/afterEach hooks or make them no-ops. The suite hooks can start the process before bench() setup/teardown runs, while IsolatedMemoryProcess.start() rejects a second start because a child process already exists.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/client/isolated-benchmark.ts` around lines 31 - 38, Update
the memory benchmark suite around isolatedProcess to remove or neutralize the
describe-level beforeEach and afterEach hooks, leaving lifecycle management
exclusively to the setup and teardown callbacks in bench options. Preserve the
existing isolatedProcess.start() and isolatedProcess.stop() calls in those
Tinybench callbacks.

Comment on lines +24 to +28
afterEach(async () => {
await runner?.stop()
delete process.env.TSR_MEMORY_ISOLATION_TEST_LOG
await rm(tempDirectory, { recursive: true })
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Make cleanup independent of stop() success.

If runner.stop() rejects, afterEach skips the env-var deletion and the temp-directory removal. The stale TSR_MEMORY_ISOLATION_TEST_LOG value then leaks into later tests, and temp directories accumulate. Run the cleanup in a finally block, and reset runner.

🧹 Proposed fix
   afterEach(async () => {
-    await runner?.stop()
-    delete process.env.TSR_MEMORY_ISOLATION_TEST_LOG
-    await rm(tempDirectory, { recursive: true })
+    try {
+      await runner?.stop()
+    } finally {
+      runner = undefined
+      delete process.env.TSR_MEMORY_ISOLATION_TEST_LOG
+      await rm(tempDirectory, { recursive: true, force: true })
+    }
   })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
afterEach(async () => {
await runner?.stop()
delete process.env.TSR_MEMORY_ISOLATION_TEST_LOG
await rm(tempDirectory, { recursive: true })
})
afterEach(async () => {
try {
await runner?.stop()
} finally {
runner = undefined
delete process.env.TSR_MEMORY_ISOLATION_TEST_LOG
await rm(tempDirectory, { recursive: true, force: true })
}
})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/server/isolated-process.test.ts` around lines 24 - 28,
Update the afterEach cleanup around runner.stop() so environment-variable
deletion and temporary-directory removal always execute in a finally block, even
when stop() rejects. Also reset the runner reference during cleanup, using the
existing runner and tempDirectory symbols.

Comment thread benchmarks/memory/shared/isolated-process-child.ts
@codspeed-hq

codspeed-hq Bot commented Aug 6, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 52.65%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 9 improved benchmarks
❌ 32 regressed benchmarks
✅ 139 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory mem client loader-data-retention (solid) 153.7 KB 1,495.8 KB -89.72%
Memory mem client loader-data-retention (react) 155.7 KB 1,463.6 KB -89.36%
Memory mem client interrupted-navigations (react) 248.9 KB 2,084.2 KB -88.06%
Memory mem client interrupted-navigations (solid) 341.4 KB 2,104.5 KB -83.78%
Memory mem client navigation-churn (react) 443.6 KB 2,484.5 KB -82.14%
Memory mem client interrupted-navigations (vue) 500.3 KB 2,708.6 KB -81.53%
Memory mem client unique-location-churn (solid) 516.8 KB 2,796 KB -81.52%
Memory mem client navigation-churn (solid) 540.4 KB 2,572.4 KB -78.99%
Memory mem client preload-churn (solid) 312.1 KB 1,092.1 KB -71.42%
Memory mem client mount-unmount (solid) 477.2 KB 1,501.2 KB -68.21%
Memory mem server error-paths redirect (react) 208.5 KB 646.4 KB -67.74%
Memory mem client unique-location-churn (vue) 986.6 KB 2,863.2 KB -65.54%
Memory mem client unique-location-churn (react) 962.5 KB 2,790.2 KB -65.5%
Memory mem server error-paths not-found (react) 255.9 KB 663.3 KB -61.41%
Memory mem server aborted-requests (react) 564.1 KB 1,425.5 KB -60.43%
Memory mem server error-paths unmatched (react) 262.3 KB 661.7 KB -60.36%
Memory mem client preload-churn (vue) 738.3 KB 1,764.8 KB -58.17%
Memory mem server error-paths redirect (solid) 278.2 KB 646.7 KB -56.98%
Memory mem server request-churn (solid) 414.6 KB 952.5 KB -56.47%
Memory mem client navigation-churn (vue) 1.2 MB 2.5 MB -50.63%
... ... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing test-codspeed-memory-stabilization (ea7c024) with main (2265129)

Open in CodSpeed

@nx-cloud

nx-cloud Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit ea7c024

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 2m 34s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 31s View ↗

☁️ Nx Cloud last updated this comment at 2026-08-07 18:06:28 UTC

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

No changeset entries found. Merging this PR will not cause a version bump for any packages.

@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7988

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7988

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7988

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7988

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7988

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7988

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7988

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7988

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7988

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7988

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7988

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7988

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7988

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7988

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7988

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7988

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7988

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7988

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7988

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7988

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7988

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7988

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7988

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7988

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7988

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7988

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7988

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7988

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7988

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7988

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7988

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7988

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7988

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7988

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7988

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7988

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7988

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7988

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7988

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7988

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7988

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7988

commit: ea7c024

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: 06b911d0f95e
  • Measured at: 2026-08-07T18:04:24.328Z
  • Baseline source: history:abf9b81b1f14
  • Dashboard: bundle-size history

The following scenarios have bundle-size changes compared with the baseline:

Scenario Current (gzip) Delta vs baseline Initial gzip Raw Brotli Trend
react-router.minimal 86.99 KiB +75 B (+0.08%) 86.85 KiB 267.76 KiB 75.73 KiB ▇█▁▁▁▃▃▃▃▄▄
react-router.full 90.76 KiB +58 B (+0.06%) 90.62 KiB 279.72 KiB 79.00 KiB ▇█▁▁▁▂▂▂▂▃▃
solid-router.minimal 34.65 KiB +56 B (+0.16%) 34.52 KiB 98.56 KiB 31.23 KiB ██▁▁▁▃▃▃▃▃▃
solid-router.full 39.71 KiB +40 B (+0.10%) 39.58 KiB 113.73 KiB 35.78 KiB ██▁▁▁▂▂▂▂▂▂
vue-router.minimal 51.88 KiB +42 B (+0.08%) 51.75 KiB 141.57 KiB 46.73 KiB ██▁▁▁▂▂▂▂▂▂
vue-router.full 57.79 KiB +59 B (+0.10%) 57.67 KiB 160.14 KiB 51.95 KiB ██▁▁▁▂▂▂▂▂▂
react-start.minimal 100.38 KiB +16 B (+0.02%) 100.24 KiB 310.83 KiB 87.20 KiB ██▁▁▁▂▂▂▂▁▁
react-start.deferred-hydration 101.11 KiB +12 B (+0.01%) 100.26 KiB 312.20 KiB 87.83 KiB ██▁▁▁▂▂▂▂▁▁
react-start.full 103.76 KiB +11 B (+0.01%) 103.62 KiB 320.78 KiB 90.13 KiB ▇█▁▁▁▁▁▁▁▁▁
react-start.rsbuild.minimal 99.99 KiB +63 B (+0.06%) 99.82 KiB 315.33 KiB 86.25 KiB ▇█▁▁▁▂▂▂▂▂▂
react-start.rsbuild.minimal-iife 100.40 KiB +67 B (+0.07%) 100.24 KiB 316.26 KiB 86.48 KiB ▇█▁▁▁▂▂▂▂▂▂
react-start.rsbuild.full 103.31 KiB +74 B (+0.07%) 103.14 KiB 325.42 KiB 88.94 KiB ██▁▁▁▂▂▂▂▃▃
solid-start.minimal 47.96 KiB +30 B (+0.06%) 47.83 KiB 140.63 KiB 42.69 KiB ██▁▁▁▂▂▂▂▂▂
solid-start.deferred-hydration 51.17 KiB -24 B (-0.05%) 47.89 KiB 148.31 KiB 45.63 KiB ██▂▂▂▃▃▃▁▁▁
solid-start.full 53.23 KiB +36 B (+0.07%) 53.11 KiB 156.35 KiB 47.32 KiB ██▁▁▁▂▂▂▂▂▂
vue-start.minimal 68.64 KiB +16 B (+0.02%) 68.51 KiB 193.40 KiB 61.10 KiB ██▁▁▁▁▁▁▁▁▁
vue-start.full 72.65 KiB +42 B (+0.06%) 72.52 KiB 205.90 KiB 64.57 KiB ██▁▁▁▂▂▂▂▂▂

Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/memory/client/benchmark.ts`:
- Around line 10-19: Move the before/after pairing validation in
warmClientMemoryWorkload before the !workload.warmup early return, so workloads
without warmup still require both lifecycle hooks or neither. Preserve the
existing error and return behavior after validation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0de7bae-2d8f-4949-a3a1-f217d2619dc5

📥 Commits

Reviewing files that changed from the base of the PR and between 300581b and 6fc9f20.

📒 Files selected for processing (19)
  • benchmarks/memory/README.md
  • benchmarks/memory/client/benchmark.ts
  • benchmarks/memory/client/flame-runner.ts
  • benchmarks/memory/client/scenarios/interrupted-navigations/shared.ts
  • benchmarks/memory/client/scenarios/loader-data-retention/shared.ts
  • benchmarks/memory/client/scenarios/mount-unmount/shared.ts
  • benchmarks/memory/client/scenarios/navigation-churn/shared.ts
  • benchmarks/memory/client/scenarios/preload-churn/shared.ts
  • benchmarks/memory/client/scenarios/unique-location-churn/shared.ts
  • benchmarks/memory/server/benchmark.ts
  • benchmarks/memory/server/flame-runner.ts
  • benchmarks/memory/server/isolated-process.test.ts
  • benchmarks/memory/server/scenarios/aborted-requests/shared.ts
  • benchmarks/memory/server/scenarios/error-paths/shared.ts
  • benchmarks/memory/server/scenarios/request-churn/shared.ts
  • benchmarks/memory/server/scenarios/server-fn-churn/shared.ts
  • benchmarks/memory/server/test-fixtures/isolated-process-setup.ts
  • benchmarks/memory/shared/isolated-process-child.ts
  • benchmarks/memory/shared/isolated-process.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • benchmarks/memory/shared/isolated-process-child.ts

Comment on lines +10 to +19
export async function warmClientMemoryWorkload(workload: ClientMemoryWorkload) {
if (!workload.warmup) {
return
}

if (Boolean(workload.before) !== Boolean(workload.after)) {
throw new Error(
`Client memory workload ${workload.name} must define both before and after when it defines either hook`,
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Validate paired lifecycle hooks before the early return.

Line 11 bypasses the before and after pairing check when warmup is absent. A workload with only before can then create measured state without cleanup. Validate the pair before returning.

Proposed fix
 export async function warmClientMemoryWorkload(workload: ClientMemoryWorkload) {
-  if (!workload.warmup) {
-    return
-  }
-
   if (Boolean(workload.before) !== Boolean(workload.after)) {
     throw new Error(
       `Client memory workload ${workload.name} must define both before and after when it defines either hook`,
     )
   }
 
+  if (!workload.warmup) {
+    return
+  }
+
   await workload.before?.()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export async function warmClientMemoryWorkload(workload: ClientMemoryWorkload) {
if (!workload.warmup) {
return
}
if (Boolean(workload.before) !== Boolean(workload.after)) {
throw new Error(
`Client memory workload ${workload.name} must define both before and after when it defines either hook`,
)
}
export async function warmClientMemoryWorkload(workload: ClientMemoryWorkload) {
if (Boolean(workload.before) !== Boolean(workload.after)) {
throw new Error(
`Client memory workload ${workload.name} must define both before and after when it defines either hook`,
)
}
if (!workload.warmup) {
return
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/client/benchmark.ts` around lines 10 - 19, Move the
before/after pairing validation in warmClientMemoryWorkload before the
!workload.warmup early return, so workloads without warmup still require both
lifecycle hooks or neither. Preserve the existing error and return behavior
after validation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
benchmarks/memory/shared/isolated-process.ts (1)

224-227: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Wait for child exit when startup fails.

child.kill() only requests termination. The method clears #child and rejects before the child exits. A later start() can overlap with the failed child process and affect benchmark memory results.

Register #waitForExit(child) before killing the child. Await its settlement before rethrowing the startup error.

Proposed fix
     } catch (error) {
-      child.kill()
       this.#child = undefined
+      const exit = this.#waitForExit(child)
+      if (child.exitCode === null && child.signalCode === null) {
+        child.kill()
+      }
+      await exit.catch(() => {})
       throw error
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/memory/shared/isolated-process.ts` around lines 224 - 227, Update
the startup failure catch block around `#waitForExit` and child.kill() to register
the child-exit wait before requesting termination, then await its settlement
before clearing `#child` and rethrowing the original startup error. Preserve the
existing cleanup and rejection behavior after the child has exited.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@benchmarks/memory/shared/isolated-process.ts`:
- Around line 224-227: Update the startup failure catch block around
`#waitForExit` and child.kill() to register the child-exit wait before requesting
termination, then await its settlement before clearing `#child` and rethrowing the
original startup error. Preserve the existing cleanup and rejection behavior
after the child has exited.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b0364019-16a7-4e43-a733-c1dab9e99532

📥 Commits

Reviewing files that changed from the base of the PR and between ce69001 and e7c1d50.

📒 Files selected for processing (5)
  • benchmarks/memory/README.md
  • benchmarks/memory/server/isolated-process.test.ts
  • benchmarks/memory/server/test-fixtures/isolated-process-setup.ts
  • benchmarks/memory/shared/isolated-process-child.ts
  • benchmarks/memory/shared/isolated-process.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • benchmarks/memory/server/test-fixtures/isolated-process-setup.ts
  • benchmarks/memory/server/isolated-process.test.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant