R22 Fast XState
npm i fast-xstate
XState interpreter with pure unadultered thread hogging speed
Philosophy​
The XState interpreter simply determines what order to call the user supplied code in, passing context between them all, in response to external events being inserted. This should be an extremely fast and lightweight process, but the current XState implementation carries significant overhead for high performance uses.
Debugging these functions is also difficult as seeing the state of the machine during previous states is hard, and with transient states is near impossible. We need a system that lets us use traditional debugging tools to quickly and clearly see what are the problems with our user supplied code, and in what order things have been called.
Background​
Over the past 18 months, XState has served us immensely well.
However, we have found the implementation lacking for our admitedly very specific needs, which are:
- As fast as possible execution
- Tracing by stepping thru all transitions, including transient transitions
When we attempt to reuse the code of the current XState implementation, we are surpised that:
- Some of the code files are large, making it difficult to decipher
- None of XState seems to be written in XState
For our application, which is a blockchain that is written almost entirely using XState to manage the complexity of the project, we also have the ability to run XState machines inside of the blockchain itself.
This all begs the question: Can a small core of XState functionality be used to write all the extended functionality of XState in the XState language itself ?
Benefits are:
- Smaller core code
- Implementation can leverage the same tools XState applications do, such as visualization, testing
- Contributors to the project, who will most likely be using XState for their own projects, will immediately understand how the system works
- Possibly greater speed, with configurable thread hogging capability, when raw speed matters
- All the tools of XState can be brought to bear on the XState project itself
- writing the core and using XState become close to the same thing, meaning core developer time is spent more on the usage of XState, making them heavy power users, rather than two separate software disciplines taking place, with core more focused on conventional development, and users more focused on XState language
- In the visual debugger, can present the underlying state machines, so users can understand what is happening under the hood, and can express bugs easier
- The mere fact that it runs proves the utility of XState and the correctness of the implementation
- Dicussion can focus more on what is the best statechart for processing the Xstate language ?
- A degree of self provability - self proving that complex tasks can be handled, that the tooling and architectural skills are present within the process to use it for complex things
- Add XState to the list of projects using XState - this is not true currently and it should be the largest user of its own produce
Features provided by a higher order state chart​
The HOSC expands on the features of the core by running at the start and at every transition, in effect decorating the core behaviour. Seeing statecharts visually is about the most illuminating thing a programmer could hope for, and so by jumping into statechart land as early as possible, we can gain these benefits for the majority of the XState codebase.
- invoke
- parallel states
- Format checking of machine and config
- Actors
- Error checking and handling
- Transformation of shorthand expressions into core format
- History
- Jumping across states using id's
- Statecharts ? Use core for only flat state machines ?
Interpreter state chart​
This statechart calls the HOSC to do pure transition functions, then it takes the result and executes all the actions, updating the context.
- Timers
- start, stop, pause of running interpreter
- receiving external events
Could the core be a statechart too ?​
Transition to next node, resolve current node, then lob up an action to self to cause the processing of each step ?
In effect, there would be no single program that could execute the core statechart, just something to start the operation, ways to process each node, then actions send to self to move the system forwards.
Minimum subset of features required to implement all other features​
- receieve action
- always transition
- conditional transition
- transition actions
- single dimensional transitions With these features, can write a statechart that when executed
Debugging features​
- Each transition, along with exec() to call all functions, should contain a list of function names in the order they will be called in, so users can see what order their code will be called in each transition
- Debugging for each piece of user code, where the call params and output result can be traced
- each subsequent call to exec actually takes place within the last one, so debugger can walk the stack to see values of execution