xstate: Bug: Memory leak appeared between xstate 4.32.1 and xstate 4.33.4
Description
We’ve recently had a memory leak in a Home Assistant addon which uses xstate under the hood (as a transitive dependency). It took a while to narrow this down to xstate (or using it), since there are two similar addons, using the exact same library with the exact same version, and only one of those exhibited a quite drastic memory leak (in the order of 100MB/h), while the other one is perfectly stable: https://github.com/home-assistant/core/issues/77767
It turns out that the difference between those installations was how the dependencies got installed. The non-leaking one uses yarn install --immutable, resulting in an install of xstate@4.32.1 from the lockfile - while the leaking one uses npm install, which installed the latest version at the time. The leak appeared starting with xstate@4.33.4 and persists with 4.33.6 - unfortunately I don’t know which versions between those two are also affected.
After pinning the xstate version in the leaking addon, the leak went away.
Sadly, I cannot provide a reproduction, since only a handful of users are affected and I haven’t been able to reproduce myself. I haven’t seen anything in the changelog that would suggest a change in behavior - like actor references not getting cleaned up or anything like that. I would be grateful for some help with tracking this down though, since I’m afraid this is going to prevent us from upgrading xstate indefinitely.
Expected result
No memory leak
Actual result
Memory leak
Reproduction
Not possible unfortunately, see description
Additional context
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 20 (9 by maintainers)
@Andarist I was able to get a minimal reproduction setup for this issue: https://github.com/beejunk/xstate-memory-leak
Details are in the
README.mdfile; let me know if you need any additional info. If debugging over a call is helpful, I could probably make that work but not until next weekend.Hope this helps!
Ran into this issue this week. Deployed a Node app that uses XState, and as soon as it faced production traffic we started seeing signs of a memory leak. This deploy included an upgrade of XState from 4.31.0 to 4.35.0. Took us a while to get an idea of what was going on, and seeing this issue confirmed our theory. We downgraded XState to 4.31.0, redeployed and the issue was no longer there.
While we were investigating the issue, we analyzed a core dump from the app and discovered that a massive number of
StateandStateNodeobjects were in memory. Following this, I was able to run the app locally, hit it with bit of traffic using K6, and analyze the memory using the Chrome dev-tools heap profiler. For v. 4.35.0 of XState, this also revealedStateandStateNodeobjects that weren’t being grabage-collected. When analyzing with XState v. 4.31.0, these objects did not appear on the profile at all (so I am assuming they were effectively GC’d).The machine in question does use parallel child machines. Additionally, the version of the app that exhibited the memory leak issue was using the
predictableActionArgumentsoption set totruefor each machine.If I have time this weekend, I’ll see if I can get together a minimal reproduction.
@beejunk thank you! this was very helpful. Thanks to the repro I located the problem really quickly - the PR with a fix is up here: https://github.com/statelyai/xstate/pull/3801
I did above, but here you go
https://github.com/zwave-js/node-zwave-js
That’s a good place for us to look. It’s either that or some code introduced with the
predictableActionArgumentsflag, I’d think.