Repository navigation
fix(performance): prevent memory leak by scoping trace engine model per parse - #2720
Merged
Merged
Conversation
…er parse DevTools' TraceModel permanently appends parsed traces to an internal recordings list that is not cleared by resetProcessor. Reusing a module-level singleton retains every parsed trace in memory for the lifetime of the process, causing unbounded heap growth across consecutive recordings. Instantiating a new TraceModel for each buffer parse isolates the engine lifecycle to the parse operation and allows completed traces to be garbage-collected once caller references are released.
Contributor
Author
|
PTAL. I found this when debugging the buffer overflow issue. Until we support >1 traces at once, let's ensure we clean up the memory. |
OrKoN
reviewed
Sep 10, 2026
OrKoN
left a comment
Collaborator
There was a problem hiding this comment.
Could you please add a regression-scenario to https://github.com/ChromeDevTools/chrome-devtools-mcp/tree/main/scripts/profile/scenarios?
OrKoN
approved these changes
Sep 10, 2026
Validates MCP process heap stability across consecutive performance trace recordings. Running multiple iterations of starting and stopping page reload traces guards against regressions where DevTools TraceModel retains trace data in memory across recording sessions.
jackfranklin
enabled auto-merge
September 10, 2026 15:30
pull Bot
pushed a commit
to oogalieboogalie/chrome-devtools-mcp
that referenced
this pull request
Sep 23, 2026
🤖 I have created a release *beep* *boop* --- ## [1.10.0](ChromeDevTools/chrome-devtools-mcp@chrome-devtools-mcp-v1.9.0...chrome-devtools-mcp-v1.10.0) (2026-09-23) ### 🎉 Features * add css formatter class ([ChromeDevTools#2707](ChromeDevTools#2707)) ([f0b5fa4](ChromeDevTools@f0b5fa4)) * add get_css_style tool ([ChromeDevTools#2612](ChromeDevTools#2612)) ([4454ae0](ChromeDevTools@4454ae0)) * **performance:** chunked trace buffer parser for large recordings ([ChromeDevTools#2721](ChromeDevTools#2721)) ([23b9a48](ChromeDevTools@23b9a48)) * set default pageSize and pageIdx for get_css_styles tool ([ChromeDevTools#2799](ChromeDevTools#2799)) ([dc9d14d](ChromeDevTools@dc9d14d)) * support config file ([ChromeDevTools#2661](ChromeDevTools#2661)) ([314a5fa](ChromeDevTools@314a5fa)) * **telemetry:** persist date of the last tool call. ([ChromeDevTools#2705](ChromeDevTools#2705)) ([c54a493](ChromeDevTools@c54a493)) * **telemetry:** recording a sanitized version of the client name ([ChromeDevTools#2757](ChromeDevTools#2757)) ([55fbc57](ChromeDevTools@55fbc57)) * **telemetry:** report hermes client usage. ([ChromeDevTools#2703](ChromeDevTools#2703)) ([fb47e6c](ChromeDevTools@fb47e6c)) * update css formatter class to add AtRule, PositionTryRule, PropertyRule, FunctionRule ([ChromeDevTools#2717](ChromeDevTools#2717)) ([d4a0620](ChromeDevTools@d4a0620)) * update css formatter class to add inherited rules ([ChromeDevTools#2715](ChromeDevTools#2715)) ([3d7e7bb](ChromeDevTools@3d7e7bb)) * update css formatter class to add matched rules ([ChromeDevTools#2713](ChromeDevTools#2713)) ([8c8616f](ChromeDevTools@8c8616f)) * update css formatter class to add pseudo element ([ChromeDevTools#2716](ChromeDevTools#2716)) ([df1469a](ChromeDevTools@df1469a)) * update css formatter to add keyframes rules ([ChromeDevTools#2718](ChromeDevTools#2718)) ([cdc365c](ChromeDevTools@cdc365c)) ### 🛠️ Fixes * bound ConsoleCollector retention per navigation ([ChromeDevTools#2773](ChromeDevTools#2773)) ([e98a3ca](ChromeDevTools@e98a3ca)) * **cli:** forward explicit false options on start ([ChromeDevTools#2702](ChromeDevTools#2702)) ([d9a8cb6](ChromeDevTools@d9a8cb6)) * **config:** preserve raw values for config coercion ([ChromeDevTools#2747](ChromeDevTools#2747)) ([906c83b](ChromeDevTools@906c83b)) * don't log Puppeteer logs to file unless requested ([ChromeDevTools#2743](ChromeDevTools#2743)) ([4fbfbc4](ChromeDevTools@4fbfbc4)) * explain launch failures caused by running as root ([ChromeDevTools#2634](ChromeDevTools#2634)) ([9d29223](ChromeDevTools@9d29223)) * handle JavaScript dialogs opened during input tool actions ([ChromeDevTools#2794](ChromeDevTools#2794)) ([266112b](ChromeDevTools@266112b)) * **performance:** prevent memory leak by scoping trace engine model per parse ([ChromeDevTools#2720](ChromeDevTools#2720)) ([d05cbc0](ChromeDevTools@d05cbc0)) * preserve console history across same-document navigations ([ChromeDevTools#2676](ChromeDevTools#2676)) ([aa25562](ChromeDevTools@aa25562)) * preserve underlying error message in input tool actions ([ChromeDevTools#2792](ChromeDevTools#2792)) ([6e47dbb](ChromeDevTools@6e47dbb)) * set emulatedUserAgent and use finalDisplayedUrl in lighthouse_audit ([ChromeDevTools#2795](ChromeDevTools#2795)) ([941f82a](ChromeDevTools@941f82a)) * timout in WaitForHelper.ts ([ChromeDevTools#2772](ChromeDevTools#2772)) ([dc1d055](ChromeDevTools@dc1d055)) ### 📄 Documentation * add FLUJO client configuration ([ChromeDevTools#2690](ChromeDevTools#2690)) ([65a679e](ChromeDevTools@65a679e)) * fix categories not being configured correclty ([ChromeDevTools#2807](ChromeDevTools#2807)) ([2250cdc](ChromeDevTools@2250cdc)) * fix defaults for non-boolean values ([ChromeDevTools#2744](ChromeDevTools#2744)) ([342d243](ChromeDevTools@342d243)) * update page routing option name ([ChromeDevTools#2748](ChromeDevTools#2748)) ([8939965](ChromeDevTools@8939965)) * update SKILL for chrome-devtools to use get_css_styles tool ([ChromeDevTools#2760](ChromeDevTools#2760)) ([421011e](ChromeDevTools@421011e)) ### 🏗️ Refactor * disable tools instead of not registering them ([ChromeDevTools#2636](ChromeDevTools#2636)) ([b455469](ChromeDevTools@b455469)) * extract browser in a BrowserManager class ([ChromeDevTools#2787](ChromeDevTools#2787)) ([3228f44](ChromeDevTools@3228f44)) * migrate the MCP SDK to v2 ([ChromeDevTools#2408](ChromeDevTools#2408)) ([da3c406](ChromeDevTools@da3c406)) * move comments formatting to CommentFormatter class ([ChromeDevTools#2719](ChromeDevTools#2719)) ([e3cded0](ChromeDevTools@e3cded0)) * prepare for SDK v2 ([ChromeDevTools#2771](ChromeDevTools#2771)) ([61780c7](ChromeDevTools@61780c7)) * simplify our gen scritps ([ChromeDevTools#2793](ChromeDevTools#2793)) ([5068584](ChromeDevTools@5068584)) * unify call type and ensure typesafety ([ChromeDevTools#2659](ChromeDevTools#2659)) ([882f93e](ChromeDevTools@882f93e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rationale
DevTools'
TraceEngine.TraceModel.Modelpermanently retains parsed traces in an internal recordings array (#traces). Callingengine.resetProcessor()between runs only resets the underlying processor and does not clear#traces.Because
enginewas previously instantiated as a module-scoped singleton, every performance trace recorded or parsed in a session remained permanently held in heap memory for the lifetime of the process.Changes
src/processors/PerformanceTrace.ts, instantiateDevTools.TraceEngine.TraceModel.Model.createWithAllHandlers()per invocation ofparseRawTraceBuffer().enginesingleton and the obsoleteengine.resetProcessor()call.tests/trace-processing/parse.test.tsverifying that consecutive trace parses construct isolatedModelinstances and keep internal trace retention bounded at 1.scripts/profile/scenarios/performance_trace.tsto guard against memory retention across consecutive traces duringnpm run test:memory.