xstate icon indicating copy to clipboard operation
xstate copied to clipboard

Performance issue with xstate inspector + rxjs Subject + fast-safe-stringify

Open snikch opened this issue 4 years ago • 4 comments

Description

I've somehow managed to create a state that takes 11s to send to the interpreter. In looking into the issue, I've discovered that the fast-safe-stringify stringify method's runtime is somewhat linear to the complexity of a state chart under certain circumstances.

The offender appears to be when you invoke an rxjs Subject. The resulting call to stringify calls decirc a large amount of times. The amount of times appears to be directly correlated to the complexity of the state chart in its entirety.

The following is a simple reproduction case.

import { inspect } from "@xstate/inspect";
import { useService } from "@xstate/react";
import { default as React } from 'react';
import { Subject } from "rxjs";
import { map } from "rxjs/operators";
import { createMachine, interpret } from "xstate";
import './App.css';

inspect({
  iframe: false
});

const child = createMachine({
    id: "child",
        initial: "init",
        states: {
          init: {
            invoke: {
              src: ({subject}:any) => subject.pipe(map((data) => ({ type: "RECV", data })))
            }
          }
  }
}
);

const parent = createMachine(
  {
    id: "machine",
    initial: "ready",
    context: { subject: new Subject() },
    states: {
      ready: {
            invoke: {
              src: child,
              data: {
                subject: ({subject}: any) => subject,
              }
            }
          },
        }
  }
);

const service = interpret(parent, { devTools: true })
service.start()

function App() {
  const [current, send] = useService(service);
    return <React.Fragment>:(</React.Fragment>;
}


export default App;

This produces a somewhat mild 3.99ms stringify call.

image

If we add 20 arbitrary sibling states, we see the stringify call nearly double to 7.68ms.

image

Now if we look at the states for my somewhat more complex application which includes services, actions, guards etc. we can see it's blown out to over 11,000ms.

image image

I haven't investigated this any deeper to determine whether this is affected more by having many services, actions etc. or whether it's simply linear with the number of states.

My temporary solution is to hack the Subject with a toJSON method.

subject.toJSON = () => "[Rxjs Subject]

I'm not actually sure if this is a "problem" per se, but I figured it's worth bringing it up as it's caused no small amount of headaches.

Expected Result

Not to wait 11s for the state to load.

Actual Result

The state takes 11s to load.

Reproduction

See above example.

Additional context

snikch avatar Jun 24 '21 03:06 snikch

I was able to reproduce this but found the issue isn't related to the Subject but having a complex object stored in context. I believe the inspector is trying to stringify the whole object to be able to show it in the state panel.

aldovelco avatar Nov 19 '21 06:11 aldovelco

This seems like something that https://github.com/statelyai/xstate/pull/2640 will fix, once we determine a proper solution.

davidkpiano avatar Nov 19 '21 22:11 davidkpiano

Had this issue while implementing a websocket solution built on top of the phoenix-js library. We store the Socket and Channel classes in context and they take around 4 seconds each to stringify.

It would be great if we could opt out of stringifying large objects. Maybe an ignore-list for context names in the inspector options or better yet, a regex ignore-list

xylophonehero avatar Feb 23 '23 09:02 xylophonehero

You can avoid serializing massive objects like this:

inspect({
  serialize: (_key, value) => {
    if (isSocket(value)) {
      return '[redacted Socket]';
    }

    if (isChannel(value)) {
      return '[redacted Channel]';
    }

    return value;
  }
})

Andarist avatar Feb 23 '23 10:02 Andarist

Closing as stale – if there are issues with the new inspector, please file them here: https://github.com/statelyai/inspect/issues/new

davidkpiano avatar Jul 15 '24 02:07 davidkpiano