Repository navigation
Memory leak when linking to MathJax directly #3591
Description
Activity
Thanks for your report. I am able to verify the problem you are seeing, though I haven't fully diagnosed it yet. The majority of the problem seems to be due to the large number of instances of the CHTML output jax that are involved here, so I suspect that it is the font data that is causing the problem. I will have to track it down, but wanted to give you some options in the meantime.
The
/@jajaperson+rehype-mathjaxpackage is creating the input and output jax and the MathDocument for each of the 1,900 documents that you process. You also create the DOM adaptor and register/unregister the HTML handler for each document. Not all of that is necessary to do each time, and that is contributing to the memory problem. It also degrades the performance, particularly recreating the output jax, which has to process the font data each time as it creates its ownFontDatainstance.Fortunately, the output jax can be reused, which eliminates both the performance hit, as well as reducing the memory usage. You also only need to create the DOM adaptor and register the HTML handler once up front.
Here are some changes that I think will reduce the problem that you are having:
In the
create-renderer.jsfile, addconst adapter = liteAdapter(); const handler = registerHtmlHandler(adapter);
right after all the
importcommands, and then remove/** @type {HtmlHandler<LiteElement | LiteText, LiteText, LiteDocument>} */ let handler
from the
createRenderer()function. Also, removeconst adapter = liteAdapter() handler = registerHtmlHandler(adapter)
from the
register()function within it. Finally, replacemathjax.handlers.unregister(handler)
in the
unregistered()function withconst jax = document.outputJax; jax.reset(); if (jax.chtmlStyles) jax.chtmlStyles = null; if (jax.svgStyles) jax.svgStyles = null;
Then in
chtml.js, addlet chtml;
at the top, and replace
return createRenderer(options, new Chtml(options.chtml))
with
chtml ??= new Chtml(options.chtml); return createRenderer(options, chtml);
Do the similar thing in
svg.js.These changes will allow you to reuse the output jax, rather than re-instantiating over and over again. If you are not defining new macros, it would be possible to do something similar with the input jax. Even the
mathjax.document()value could be reused in that case. It looks like you are only used\defto create\fCenteras\vdash, and one other macro. Those could be added to your main macro list, or, since you aren't redefining any standard macros, you could just reuse the input jax as it is, as those two macros won't interfere with anything if they are held over from one to the next. That gives me pretty stable memory usage; I think you should find the same.- addedAcceptedIssue has been reproduced by MathJax teamIssue has been reproduced by MathJax team
on Jul 16, 2026 Thanks, I have followed your suggestion and this has completely fixed the issue for me, memory usage is down to about 181 kB and build time has halved. I am happy if you close this, but maybe you still want to investigate why re-initializing MathJax caused a problem.
Issue Summary
I am using a fork of rehype-mathjax which upgrades from v3 to v4, in a project containing approximately 1,900 markdown files, the majority of which contains maths. Recently the build has been surpassing 4 GB of memory usage on my personal machine, and MathJax seems to be the culprit, as disabling it removes the memory leak.
Steps to Reproduce:
Run
pnpm buildon the project linked above.I know this can hardly be considered a “minimal” reproduction, but this bug obviously requires a substantial number of files to reproduce. If there is something else you would like me to try, please let me know.
For what its worth, the rehype-mathjax fork follows the approach of linking to MathJax directly. Unfortunately my PR to remark-math has been open for 5 months with no response.
Technical details: