Skip to content

feat(diagnostics): Native V8 Memory & Profiling Suite - #24303

Open
Mustafa0216 wants to merge 1 commit into
google-gemini:mainfrom
Mustafa0216:feat/diagnostic-suite
Open

Mustafa0216 wants to merge 1 commit into
google-gemini:mainfrom
Mustafa0216:feat/diagnostic-suite

Conversation

@Mustafa0216

Copy link
Copy Markdown

Proposed Pull Request

Repository: google/gemini-cli
Branch: feat/diagnostic-suite

PR Title

feat(diagnostics): Native V8 Memory & Profiling Suite

PR Body

GSoC 2026: Proposed PR for Terminal-Integrated Performance & Memory Investigation Companion #23365

This PR introduces a zero-dependency, pure-JavaScript diagnostic architecture designed to autonomously root-cause memory pipeline leaks and execution bloat within the Gemini CLI without relying on outdated node compatible extensions and very un optimal DAP protocols.

Key Additions:

  • Mathematical Array Striding: Added analyze_memory.js which natively parses and computes massive V8 integer graph arrays to mathematically isolate Top 5 object memory leaks.
  • Headless CDP Extraction: Intercepts Chrome DevTools Protocol over port 9229 to manually trigger physical garbage closures and snapshot bounds seamlessly.
  • Dynamic Perfetto Serialization: Reconstructs V8 native objects into chronological timeline tracing for ingestion at ui.perfetto.dev.
  • Native Differential Footprinter: Crawls local OS directories to map exact byte-for-byte binary bloat additions without invoking compilers.
  • Autonomous Root Cause Synthesizer: Deterministically generates a structured Markdown aggregate customized perfectly for LLM context reading.

Usage & Agent Integration

Because the SKILL.md definition is included directly in the /diagnostics directory, this suite operates entirely natively. To extract memory limits, you must first expose the V8 WebSocket on the target CLI:

node --inspect=9229 scripts/start.js

You can then trigger the diagnostics in two distinct ways:

1. Traditional Execution:
Open a second terminal and trigger the full CI/CD orchestration script directly:

node diagnostics/orchestrate.js

2. As a Native Gemini CLI Skill:
While chatting with the Gemini CLI prompt inside the initial --inspect terminal, you can seamlessly command the AI to background the profiler directly on itself:

"Execute node diagnostics/orchestrate.js in a background shell right now and summarize the diagnostic_report.md output for me!"


Files to be Committed

Only the strict architecture files and dependencies will be tracked. All generated .heapsnapshot, json, and .md artifacts dumped during runtime will be intentionally ignored.

  • package.json (adds chrome-remote-interface & source-map-explorer)
  • package-lock.json
  • diagnostics/3-snapshot.js
  • diagnostics/analyze_memory.js
  • diagnostics/gdb_batch.js
  • diagnostics/orchestrate.js
  • diagnostics/profile_bloat.js
  • diagnostics/root_cause.js
  • diagnostics/to_perfetto.js
  • diagnostics/README.md
  • diagnostics/SKILL.md

User Review Required

Please read the Title and Body above. If you approve of this exact PR format, click Approve and I will instantly run the git and gh sequences to push the code and open the real Pull Request on GitHub!

@Mustafa0216
Mustafa0216 requested review from a team as code owners March 31, 2026 03:40
@google-cla

google-cla Bot commented Mar 31, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, 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 introduces a comprehensive, native diagnostic suite for the Gemini CLI, designed to autonomously investigate memory leaks, execution bloat, and performance regressions. By utilizing V8's internal APIs and the Chrome DevTools Protocol, the suite provides a robust, zero-compilation alternative to traditional debugging tools, enabling the CLI to self-diagnose and generate actionable reports for LLM-driven remediation.

Highlights

  • Native Diagnostic Architecture: Introduced a zero-dependency, pure-JavaScript diagnostic suite that leverages V8's native capabilities to analyze memory leaks and performance without relying on external C++ compiler bindings.
  • Memory & Profiling Tools: Added scripts for headless Chrome DevTools Protocol (CDP) heap snapshotting, mathematical heap graph analysis, and Perfetto trace serialization for visual timeline rendering.
  • Native System Integration: Implemented native core dump generation via process.report.writeReport() and a differential file profiler to replace heavy external tools like GDB and Bloaty.
  • Orchestration & AI Integration: Created an orchestration script to automate the diagnostic pipeline and added a SKILL.md definition to allow the Gemini CLI to trigger these diagnostics natively.
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 by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

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 pull request 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.

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. ↩

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality area/extensions Issues related to Gemini CLI extensions capability 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Mar 31, 2026

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a native diagnostic suite for the Gemini CLI, providing tools for V8 heap snapshot analysis, core dumps, and performance tracing. Feedback focuses on critical security and stability improvements: sanitizing class and branch names in reports to prevent prompt injection, refactoring snapshot logic to avoid memory leaks and Promise anti-patterns, implementing streaming for large heap files to prevent OOM crashes, and handling symbolic links to avoid infinite loops during directory traversal.

Comment on lines +76 to +78
topRealLeakers.forEach((leaker, index) => {
markdownTable += `| ${index + 1} | \`${leaker.className}\` | **${leaker.mb} MB** | ${leaker.bytes} | \n`;
});

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.

security-high high

This script extracts class names directly from a V8 heap snapshot and embeds them into a Markdown report without any sanitization. Since this report is intended to be read and summarized by an AI agent, an attacker who can influence the application's memory can perform a prompt injection attack. Malicious strings in the heap could trick the AI into performing unintended actions or providing misleading summaries.

Suggested change
topRealLeakers.forEach((leaker, index) => {
markdownTable += `| ${index + 1} | \`${leaker.className}\` | **${leaker.mb} MB** | ${leaker.bytes} | \n`;
});
topRealLeakers.forEach((leaker, index) => {
const safeClassName = leaker.className.replace(/[\x60|]/g, "\\$&");
markdownTable += "| " + (index + 1) + " | " + safeClassName + " | **" + leaker.mb + " MB** | " + leaker.bytes + " | \n";
});

Comment on lines +40 to +48
const report = `
### Differential Bloat Analysis (Native File Traversal)
**Branch Target:** \`${gitOutput}\`

- **Compiled Bundles Output (./bundle/):** ${distMB} MB
- **Dependency Weights (./node_modules/):** ${depsMB} MB

*This replaces the need for native C++ \`bloaty\` footprint mapping by directly crawling the V8-compiled production payload footprints on your disk using OS bindings.*
`;

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.

security-high high

The script retrieves the current git branch name and embeds it directly into a Markdown report. Branch names are untrusted input that can be controlled by an attacker. Since this report is consumed by an AI agent, a branch name containing LLM instructions could lead to a prompt injection attack.

  const safeGitOutput = gitOutput.replace(/[\x60|]/g, "\\$&");
  const report = "\n### Differential Bloat Analysis (Native File Traversal)\n**Branch Target:** " + safeGitOutput + "\n\n- **Compiled Bundles Output (./bundle/):** " + distMB + " MB\n- **Dependency Weights (./node_modules/):** " + depsMB + " MB\n\n*This replaces the need for native C++ bloaty footprint mapping by directly crawling the V8-compiled production payload footprints on your disk using OS bindings.*\n";

Comment thread diagnostics/3-snapshot.js
Comment on lines +4 to +28
async function takeSnapshot(client, filename) {
return new Promise(async (resolve, reject) => {
const stream = fs.createWriteStream(filename);

// Listen for the chunks of the snapshot
const chunkListener = client.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => {
stream.write(chunk);
});

try {
// takeHeapSnapshot Promise formally resolves ONLY after all chunks are sent
await client.HeapProfiler.takeHeapSnapshot({ reportProgress: false });

// Explicitly flush and close the write stream
stream.end(() => {
// Cleanup the listener so we don't leak memory on consecutive snapshots
chunkListener(); // chrome-remote-interface returns an unsubscriber function
resolve(filename);
});
} catch (err) {
stream.end();
reject(err);
}
});
}

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.

high

The takeSnapshot function uses an async executor inside a new Promise, which is an anti-pattern. Errors thrown during the asynchronous execution of takeHeapSnapshot may not be properly captured by the promise's rejection logic. Furthermore, the chunkListener is not unsubscribed if an error occurs, which could lead to memory leaks or duplicate listeners in subsequent calls.

function takeSnapshot(client, filename) {
  return new Promise((resolve, reject) => {
    const stream = fs.createWriteStream(filename);
    
    const chunkListener = client.HeapProfiler.addHeapSnapshotChunk(({ chunk }) => {
      stream.write(chunk);
    });

    client.HeapProfiler.takeHeapSnapshot({ reportProgress: false })
      .then(() => {
        stream.end(() => {
          chunkListener();
          resolve(filename);
        });
      })
      .catch((err) => {
        chunkListener();
        stream.end();
        reject(err);
      });
  });
}

Comment on lines +17 to +18
const rawData = fs.readFileSync(snapshotPath, 'utf8');
snapshot = JSON.parse(rawData);

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.

high

Reading a heap snapshot file entirely into a string using fs.readFileSync and then parsing it with JSON.parse is not scalable for massive snapshots. V8 has a hard limit on string length, and JSON.parse is extremely memory-intensive. For a tool designed to diagnose memory leaks, this implementation will likely crash with ERR_STRING_TOO_LONG or an OOM error when analyzing large heaps.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Thanks for the update

Comment on lines +12 to +13
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {

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.

high

Using fs.statSync follows symbolic links. In environments with circular symlinks or complex node_modules structures, this recursive function will enter an infinite loop and crash with a stack overflow. It is safer to use fs.lstatSync and explicitly skip symbolic links to ensure the tool remains robust.

Suggested change
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
const stats = fs.lstatSync(filePath);
if (stats.isSymbolicLink()) continue;
if (stats.isDirectory()) {

@anowardear062-svg

Copy link
Copy Markdown

Thanks for the update

This branch has not been deployed

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

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality area/extensions Issues related to Gemini CLI extensions capability 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. priority/p2 Important but can be addressed in a future release. size/l A large sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants