Skip to content

feat(benchmarks): Unify memory tests and add CI workflow#802

Merged
yamadashy merged 5 commits intomainfrom
chore/memory-check-ci
Aug 24, 2025
Merged

feat(benchmarks): Unify memory tests and add CI workflow#802
yamadashy merged 5 commits intomainfrom
chore/memory-check-ci

Conversation

@yamadashy
Copy link
Owner

This PR consolidates the memory testing infrastructure and adds automated CI testing.

Summary

  • Unified memory testing: Merged memory-leak-test.ts and simple-memory-test.ts into a single memory-test.ts with flexible options
  • Simplified CLI: Added --full, --continuous, --save flags for different testing scenarios
  • Updated scripts: Streamlined package.json scripts to test, test:full, test:continuous
  • CI integration: Added benchmark.yml workflow for automated memory testing on PR/push
  • Memory regression detection: CI fails if memory growth exceeds threshold

Key Features

🧪 Unified Memory Test

  • Default mode: 50 iterations, lightweight for CI
  • Full mode (--full): 200 iterations with detailed analysis
  • Continuous mode (--continuous): Run until stopped
  • Save results (--save): Export detailed JSON reports

🚀 CI Workflow

  • Automated testing: Runs on every PR/push with basic memory test
  • Manual dispatch: Full analysis available when needed
  • Failure detection: CI exits with error code if memory growth > 100%
  • Artifact storage: Test results saved for 30 days

Testing

# Basic test (CI equivalent)
cd benchmarks/memory && npm test

# Full analysis
cd benchmarks/memory && npm run test:full

# Continuous monitoring
cd benchmarks/memory && npm run test:continuous

Checklist

  • Run npm run test
  • Run npm run lint
  • Validated workflow with actionlint
  • Tested memory test script functionality

- Consolidate memory-leak-test.ts and simple-memory-test.ts into single memory-test.ts
- Add flexible CLI options: --full for comprehensive analysis, --continuous for monitoring
- Update package.json scripts to use simplified commands (test, test:full, test:continuous)
- Add benchmark.yml GitHub Actions workflow for automated memory testing
- CI runs lightweight tests on PR/push, full analysis available via manual dispatch
- Memory growth threshold causes CI failure to catch regressions early
Copilot AI review requested due to automatic review settings August 24, 2025 11:11
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 24, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds a new GitHub Actions workflow for memory benchmarking, replaces legacy memory npm scripts with standardized test commands, refactors the memory test into a single flag-driven CLI with altered summary shape, and removes the old simple-memory-test implementation.

Changes

Cohort / File(s) Summary of Changes
CI Workflow: Memory Benchmark
.github/workflows/benchmark.yml
Introduces “Memory Benchmark” workflow with two jobs: memory-test (push/PR/dispatch) and memory-test-full (dispatch only). Sets up Node, builds root and benchmark, runs memory tests with flags, and uploads JSON results as artifacts with retention policies.
Benchmark npm Scripts Standardization
benchmarks/memory/package.json
Replaces memory:check, memory:watch, memory:analyze with test, test:full, test:continuous using unified dist/memory-test.js and flags (--full, --continuous). Keeps build and --expose-gc; switches from positional args to flags.
Memory Test Refactor and CLI
benchmarks/memory/src/memory-test.ts
Consolidates to single TEST_CONFIG; adds CLI flags (--full, --continuous, --save, --help) and arg parsing for iterations/delay. Adjusts thresholds/intervals by mode, revises logging, safety bounds for CI, and final analysis behavior. Changes MemoryTestSummary shape (removes testInfo.configurations).
Removal of Legacy Test
benchmarks/memory/src/simple-memory-test.ts
Deletes the previous simple memory leak test script and its continuous/finite loop implementation in favor of the new unified memory-test.ts.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer/CI
  participant GA as GitHub Actions
  participant Job as memory-test job
  participant Node as Node + Benchmarks

  Dev->>GA: push/PR/dispatch
  GA->>Job: Start "memory-test"
  Job->>Node: Checkout, setup Node (cache)
  Job->>Node: npm ci (root) + build
  Job->>Node: npm ci (benchmarks) + build
  Job->>Node: Run node --expose-gc dist/memory-test.js [flags]
  Node-->>Job: Emit JSON results (if any)
  Job->>GA: Upload artifact (results)
  GA-->>Dev: Workflow complete
  note over Job,Node: "memory-test-full" mirrors steps with --full/--save and longer timeout
Loading
sequenceDiagram
  autonumber
  actor User as CLI User/CI
  participant MT as memory-test.js
  participant CLI as Flag Parser
  participant Runner as Test Loop
  participant FS as Filesystem

  User->>MT: node dist/memory-test.js [--full|--continuous|--save] [iterations] [delay]
  MT->>CLI: Parse flags and args
  CLI-->>MT: Mode, iterations, delay, save
  MT->>Runner: Initialize (thresholds, intervals)
  loop Iterations (∞ if continuous, bounded in CI)
    Runner->>Runner: runCli(TEST_CONFIG)
    Runner->>Runner: GC/logging per mode
    alt --save or --full
      Runner->>FS: Append memory sample
    end
  end
  MT->>Runner: Final analysis (heap/RSS growth)
  alt Growth exceeds threshold in CI
    MT->>User: Exit non-zero
  else Growth within threshold
    MT->>User: Exit zero
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/memory-check-ci

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@claude
Copy link
Contributor

claude bot commented Aug 24, 2025

Claude encountered an error —— View job


I'll analyze this and get back to you.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Summary of Changes

Hello @yamadashy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the project's memory testing capabilities by consolidating existing scripts and integrating automated memory regression detection into the CI pipeline. The core change involves unifying two separate memory test scripts into a single, highly configurable memory-test.ts file. This new script supports various modes, including a lightweight version for continuous integration, a comprehensive analysis mode, and a continuous monitoring option. Alongside this, the PR introduces a new GitHub Actions workflow that automatically runs these memory tests on every code change, ensuring that any potential memory leaks or significant memory growth are caught early in the development cycle. This improves the overall stability and performance of the codebase by proactively identifying and preventing memory-related issues.

Highlights

  • Unified Memory Testing Infrastructure: The separate memory-leak-test.ts and simple-memory-test.ts scripts have been merged into a single, more robust memory-test.ts file. This new script offers flexible options via command-line flags (--full, --continuous, --save) to cater to different testing needs, from quick CI checks to comprehensive analysis.
  • Simplified CLI and Package Scripts: The package.json scripts have been streamlined, replacing the old memory:check, memory:watch, and memory:analyze with intuitive test, test:full, and test:continuous commands. This simplifies the execution of various memory test scenarios.
  • Automated CI Integration for Memory Regression Detection: A new benchmark.yml GitHub Actions workflow has been added to automate memory testing. This workflow runs on every pull request and push, executing a basic memory test. It is configured to fail the CI build if significant memory growth (exceeding a defined threshold) is detected, preventing memory regressions from being merged.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR consolidates memory testing infrastructure into a unified solution that supports both lightweight CI testing and comprehensive analysis. The changes remove redundant test files and create a flexible, configurable memory testing tool with automated CI integration.

  • Unified simple-memory-test.ts and memory-leak-test.ts into single memory-test.ts with configurable modes
  • Added CLI flags (--full, --continuous, --save) for different testing scenarios
  • Integrated automated memory testing into CI with failure detection for memory growth > 100%

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
benchmarks/memory/src/simple-memory-test.ts Removed - functionality merged into unified memory test
benchmarks/memory/src/memory-test.ts Enhanced with configurable modes, CLI flags, and CI-friendly defaults
benchmarks/memory/package.json Updated scripts to use unified test commands
.github/workflows/benchmark.yml Added new CI workflow for automated memory testing

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Aug 24, 2025

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4f9f5ae
Status: ✅  Deploy successful!
Preview URL: https://18706689.repomix.pages.dev
Branch Preview URL: https://chore-memory-check-ci.repomix.pages.dev

View logs

@codecov
Copy link

codecov bot commented Aug 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.41%. Comparing base (3d07cfd) to head (4f9f5ae).
⚠️ Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #802   +/-   ##
=======================================
  Coverage   87.41%   87.41%           
=======================================
  Files         113      113           
  Lines        6493     6493           
  Branches     1331     1331           
=======================================
  Hits         5676     5676           
  Misses        817      817           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively unifies the memory testing scripts into a single, more flexible memory-test.ts with clear command-line options. The addition of a CI workflow with memory regression detection is a great improvement for repository health. The code is well-structured and the changes significantly improve the benchmarking infrastructure.

I have a few suggestions to improve the new test script further: one to prevent a potential runtime error, another to align its documentation with the implementation, and a third to make the argument parsing more robust.

Remove package-lock.json from .gitignore to ensure CI can run npm ci
properly with locked dependencies for reliable builds.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (10)
benchmarks/memory/package.json (1)

12-14: Avoid "node --run" unless you require Node 22+; use npm run for broader compatibility.

"node --run" is a relatively new Node feature and won’t work on Node 18/20. Your engines field allows >=18, so these scripts can break in local/dev environments. Either bump engines to Node 22+ or switch to npm run.

Apply one of the following diffs:

Option A — keep engines as is, replace "node --run" with npm:

-    "test": "node --run build:all && node --expose-gc dist/memory-test.js",
-    "test:full": "node --run build:all && node --expose-gc dist/memory-test.js --full",
-    "test:continuous": "node --run build:all && node --expose-gc dist/memory-test.js --continuous"
+    "test": "npm run build:all && node --expose-gc dist/memory-test.js",
+    "test:full": "npm run build:all && node --expose-gc dist/memory-test.js --full",
+    "test:continuous": "npm run build:all && node --expose-gc dist/memory-test.js --continuous"

Also update the internal build helpers:

-    "build:repomix": "cd ../.. && node --run build",
-    "build:all": "node --run build:repomix && node --run build",
+    "build:repomix": "cd ../.. && npm run build",
+    "build:all": "npm run build:repomix && npm run build",

Option B — require Node 22+:

-  "engines": {
-    "node": ">=18.0.0"
-  },
+  "engines": {
+    "node": ">=22.6.0"
+  },

Also applies to: 23-25

benchmarks/memory/src/memory-test.ts (6)

4-8: Comment mentions a non-existent “--configs” flag; remove or implement to avoid drift.

The header advertises “Multiple configurations support (--configs flag)” but the CLI doesn’t parse such a flag and the test runs a single TEST_CONFIG. This will confuse maintainers.

Apply this diff to correct the header comment now (or follow up with a separate feature to add the flag):

- * - Multiple configurations support (--configs flag)
+ * - Single configuration (can be extended to multiple configs in future)

52-74: Help text shows .ts entry; runtime uses built JS / shebang.

Examples and usage should reflect the built artifact (dist/memory-test.js) or the shebang form to prevent confusion.

-Usage: node memory-test.ts [iterations] [delay] [options]
+Usage: node dist/memory-test.js [iterations] [delay] [options]
@@
-  node memory-test.ts                    # Quick CI test (50 iterations)
-  node memory-test.ts --full             # Comprehensive test (200 iterations)
-  node memory-test.ts 100 200            # 100 iterations, 200ms delay
-  node memory-test.ts --continuous       # Run until Ctrl+C
+  node dist/memory-test.js                    # Quick CI test (50 iterations)
+  node dist/memory-test.js --full             # Comprehensive test (200 iterations)
+  node dist/memory-test.js 100 200            # 100 iterations, 200ms delay
+  node dist/memory-test.js --continuous       # Run until Ctrl+C

Alternatively, if you rely on the shebang: “./dist/memory-test.js …”.


28-32: Skip iterations validation when running in --continuous mode.

In continuous mode iterations are ignored, but the validator still enforces a positive count and can reject “0” even though it won’t be used.

-if (Number.isNaN(iterations) || iterations <= 0) {
+if (!flags.continuous && (Number.isNaN(iterations) || iterations <= 0)) {
   console.error('❌ Invalid iterations count. Must be a positive number.');
   process.exit(1);
}

Also applies to: 295-304


124-132: cleanupFiles swallows unexpected fs errors. Log non-ENOENT errors even if they don’t expose a “code” property.

Right now only errors with code !== ENOENT are logged; other error shapes get silently ignored.

-  } catch (error) {
-    if (error instanceof Error && 'code' in error && error.code !== 'ENOENT') {
-      console.warn(`Failed to cleanup ${TEST_CONFIG.options.output}:`, error.message);
-    }
-  }
+  } catch (error) {
+    const err = error as NodeJS.ErrnoException;
+    if (!err || (err.code && err.code !== 'ENOENT') || (!('code' in (err as object)))) {
+      console.warn(`Failed to cleanup ${TEST_CONFIG.options.output}:`, err?.message ?? String(err));
+    }
+  }

248-255: Guard against divide-by-zero in growth calculations to avoid Infinity/NaN.

While unlikely, defensive checks make the final analysis safer.

-    const heapGrowth = (((finalUsage.heapUsed - initialUsage.heapUsed) / initialUsage.heapUsed) * 100);
-    const rssGrowth = (((finalUsage.rss - initialUsage.rss) / initialUsage.rss) * 100);
+    const safeDiv = (num: number, den: number) => den > 0 ? (num / den) : 0;
+    const heapGrowth = safeDiv(finalUsage.heapUsed - initialUsage.heapUsed, initialUsage.heapUsed) * 100;
+    const rssGrowth = safeDiv(finalUsage.rss - initialUsage.rss, initialUsage.rss) * 100;

282-287: Add unhandledRejection and SIGTERM handlers for graceful cleanup.

This improves resilience in CI cancellations and promise rejection paths.

 process.on('uncaughtException', async (error) => {
   console.error('\n❌ Uncaught exception:', error);
   await saveMemoryHistory();
   await cleanupFiles();
   process.exit(1);
 });
+
+process.on('unhandledRejection', async (reason) => {
+  console.error('\n❌ Unhandled rejection:', reason);
+  await saveMemoryHistory();
+  await cleanupFiles();
+  process.exit(1);
+});
+
+process.on('SIGTERM', async () => {
+  console.log('\n\n⚠️  Received SIGTERM');
+  await saveMemoryHistory();
+  await cleanupFiles();
+  process.exit(0);
+});
.github/workflows/benchmark.yml (3)

65-71: Artifact upload may fail when no results are produced; set if-no-files-found to ignore.

Basic runs don’t save results by default, so the artifact step can be noisy or fail depending on action defaults. Make it explicit.

       - name: Upload memory test results
         uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # ratchet:actions/upload-artifact@v4
         if: always()
         with:
           name: memory-test-results-${{ github.run_id }}
           path: benchmarks/memory/memory-test-results-*.json
+          if-no-files-found: ignore
           retention-days: 30

1-123: Trim trailing spaces and add a final newline to satisfy YAML linters.

YAMLlint flagged trailing spaces at Lines 36, 41, 46, 50, 54, 63, 91, 96, 101, 105, 109, 115 and a missing newline at EOF. Please remove the trailing spaces on those lines and ensure the file ends with a newline. This keeps CI tidy.


55-63: Consider invoking npm scripts for consistency with package.json.

Not required, but using package scripts keeps flags and env aligned with local runs and reduces drift between CI and dev usage.

Possible change:

-          node --expose-gc dist/memory-test.js $ITERATIONS $DELAY
+          npm test --silent -- $ITERATIONS $DELAY

and for full:

-        run: node --expose-gc dist/memory-test.js --full --save
+        run: npm run -s test:full

Also applies to: 110-115

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3d07cfd and 24055c3.

📒 Files selected for processing (4)
  • .github/workflows/benchmark.yml (1 hunks)
  • benchmarks/memory/package.json (1 hunks)
  • benchmarks/memory/src/memory-test.ts (9 hunks)
  • benchmarks/memory/src/simple-memory-test.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • benchmarks/memory/src/simple-memory-test.ts
🧰 Additional context used
🧬 Code graph analysis (1)
benchmarks/memory/src/memory-test.ts (2)
benchmarks/memory/src/types.ts (2)
  • TestConfig (21-33)
  • MemoryHistory (9-19)
website/server/src/utils/memory.ts (1)
  • getMemoryUsage (21-39)
🪛 YAMLlint (1.37.1)
.github/workflows/benchmark.yml

[error] 36-36: trailing spaces

(trailing-spaces)


[error] 41-41: trailing spaces

(trailing-spaces)


[error] 46-46: trailing spaces

(trailing-spaces)


[error] 50-50: trailing spaces

(trailing-spaces)


[error] 54-54: trailing spaces

(trailing-spaces)


[error] 63-63: trailing spaces

(trailing-spaces)


[error] 91-91: trailing spaces

(trailing-spaces)


[error] 96-96: trailing spaces

(trailing-spaces)


[error] 101-101: trailing spaces

(trailing-spaces)


[error] 105-105: trailing spaces

(trailing-spaces)


[error] 109-109: trailing spaces

(trailing-spaces)


[error] 115-115: trailing spaces

(trailing-spaces)


[error] 123-123: no new line character at the end of file

(new-line-at-end-of-file)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build and run (windows-latest, 20.x)
  • GitHub Check: Build and run with Bun (windows-latest, latest)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
benchmarks/memory/src/memory-test.ts (1)

306-315: Nice UX touches.

Mode/features banner and Ctrl+C hint are clear; this helps operators quickly see what’s running.

.github/workflows/benchmark.yml (1)

19-27: Workflow structure looks solid.

Good defaults, timeouts, pinned SHAs, and caching. Using defaults.run.working-directory simplifies steps and reduces duplication.

Also applies to: 73-82

- Remove misleading --configs flag reference from file comment
- Add division by zero protection for memory growth calculations
- Prevent potential Infinity/NaN values in test results
Remove CI-only condition - memory leak detection should fail the command
regardless of environment for consistent behavior
@yamadashy yamadashy force-pushed the chore/memory-check-ci branch from a0c70ac to 4f9f5ae Compare August 24, 2025 12:55
@yamadashy yamadashy merged commit 30322d6 into main Aug 24, 2025
111 checks passed
@yamadashy yamadashy deleted the chore/memory-check-ci branch August 24, 2025 12:59
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.

2 participants