Xstate: NodeJs memory leak with interpret (xstate>=4.7.0-rc6)

Created on 22 Jan 2020  路  15Comments  路  Source: davidkpiano/xstate

Description

Occurs when using interpret.

Expected Result

After executing the request, classes using interpret will be removed from the memory by GC.

Actual Result

The memory is allocated, but not freed after the request.

Reproduction

I currently have no idea how to show a minimal working example.

Simplified application diagram:

function requestHandler(r, h) {
    ...
    new Kernel() {
        ...
        new SomeModule() {
            constructor() {
                ...
                this.interpreter = interpret(
                    Machine(machineConfig)
                );

                this.interpreter.onTransition(nextState => {
                    this.updateState(nextState);
                });
                ...
            }

            ...

            afterLoad(pageCtx) {
                ...
                this.interpreter.start(this.initialState);
                ...
            }

            beforeUnload() {
                ...
                this.interpreter.stop();
                ...
            }

            ...

            @action
            private updateState(nextState) {
                this.stateValue = nextState.value;
            }

        ...

        }
    }
    ...
    // render React to string
    // serialize App state

    return h.response('html page with serialized App state (data + xstate.StateNode)');
}

Additional context

A memory leak is not observed in version 4.7.0-rc5, but appears in 4.7.0-rc6

There are no tags for these versions, so I could not provide a link to the changes.

In tests, I used this version list: https://www.npmjs.com/package/xstate?activeTab=versions

  • xstate >= 4.7.0-rc6
  • node >= 12.13.0
bug

Most helpful comment

I've recognized the problem successfully - but it's not as trivial to fix this as I would have hoped. Gonna think about possible solutions in the following days.

All 15 comments

Thanks for the report, I think we know where it comes from. Gonna work on a fix later today.

Thanks you! I am ready to take part in testing.

That would be great! I鈥檝e already prepared a PR fixing the problem which I think is responsible for this. You could try installing the preview build from this PR. You should be able to dig to it through CodeSandbox comment posted under the PR. I鈥檝e actually not tried to use those builds outside of the CodeSandbox, but I think it should be doable - I dont think they restrict their registry access, but I might be mistaken.

@Andarist I compiled the package locally (only packages/core) https://github.com/davidkpiano/xstate/tree/267fa6d412bc13e740e5b99c5f298a2e6794d16d.

The problem has not been solved, the memory is leaking at the same pace.

Could you also check out the current release (I've released that fix like 2 hours ago)? I bet it won't help you much - but I'm pretty sure it has solved a memory leak because there was an internal map that was never freed of dead items (you can check out my PR).

There, of course, might be some other issue as well - I just knew about this one so I've quickly jumped into fixing it. Could you share any extra information? Or maybe prepare a repro case? That would allow me to jump quickly into investigating & fixing this.

@schemelev I think I've fixed another memory leak in https://github.com/davidkpiano/xstate/pull/1023 . Would you be able to check if this patch helps your case?

@Andarist Thanks! I will do a test of this patch in the near future.

A superficial check showed that a memory leak remained. After the release of version 5, I plan to do a detailed study of the problem. If the problem remains, I will make a repository with a minimal case.

Could you tell me how have you tested this?

@smirzo has provided a repro case (at least for one of the problems) and when testing this fix he has thought at first that the issue hasn't gone away because the memory was increasing but when monitoring the heap over a longer period of time he has noticed that memory is actually freed after some time. My conclusion was that GC just wasn't that eager about doing its job - it just has done it periodically or after reaching some threshold, but that could only be observed when running a script for a little bit longer.

A screenshot of the heap in time (before the fix) provided by @smirzo:
Screenshot-2020-02-24-at-18 25 16

A screenshot of the heap in time (after the fix) provided by @smirzo:
Screenshot-2020-02-25-at-10 17 00

Your problem might be of course different, so it would still be good to investigate this further.

Hi @Andarist , we recently experienced a memory leak using a simple SSR web application with Nextjs. The issue is actually being caused when we use to use actors. For now, we decided to stop using xstate and fallback to React hooks. Here you can find a reproducible repo with all the steps to follow https://github.com/ccontreras/xstate-memory-leak

Thank you for sharing the repro case i will take a look at this soon!

I've recognized the problem successfully - but it's not as trivial to fix this as I would have hoped. Gonna think about possible solutions in the following days.

Nice!!!!, Thank you!!, I'm so looking forward for it

@ccontreras this memory leak in @xstate/react has been fixed in https://github.com/davidkpiano/xstate/pull/1239 by starting machines in an effect. It has not been released yet but we plan to release a new RC version this week or so - so please keep an eye for new releases and in the meantime, I'm going to close this issue.

Thank you so much guys!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hnordt picture hnordt  路  3Comments

hnordt picture hnordt  路  3Comments

3plusalpha picture 3plusalpha  路  3Comments

bradwoods picture bradwoods  路  3Comments

rodinhart picture rodinhart  路  3Comments