-
-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Shared states between FSM's #20
Comments
Hi @notsonotso, One possible workaround if you suspect TypeState as a memory culprit is to build a factory that constructs FSMs on demand given a set of shared states and transition functions. If you are building FSMs from a state enum, those pieces should be relatively small ( My example shows how to reuse handlers, and hack shared transition functions into such a factory. Profiling this with a 500 FSMs from the factory kept the heap to ~1kb (which is mostly just FSM instances and not duplicated handlers or transition functions). Let me know if this isn't what you're looking for, or if I'm off track. // typescript 2.4.2
enum States {
A = "A",
B = "B",
C = "C",
D = "D"
}
let ClientFSMFactory = function(){
let onACallback = (from) => { console.log(from) };
let onBCallback = (from) => { console.log(from) };
let onCCallback = (from) => { console.log(from) };
let onDCallback = (from) => { console.log(from) };
let fromAtoB = new typestate.TransitionFunction<States>(null, States.A, States.B);
let fromBtoC = new typestate.TransitionFunction<States>(null, States.B, States.C);
let fromCtoD = new typestate.TransitionFunction<States>(null, States.C, States.D);
let fromDtoA = new typestate.TransitionFunction<States>(null, States.D, States.A);
let tnsFcns = [fromAtoB, fromBtoC, fromCtoD, fromDtoA];
return {
getFSM: () => {
let fsm = new typestate.FiniteStateMachine<States>(States.A);
(<any>fsm)._transitionFunctions = tnsFcns;
fsm.on(States.A, onACallback);
fsm.on(States.B, onBCallback);
fsm.on(States.C, onCCallback);
fsm.on(States.D, onDCallback);
return fsm;
}
}
}
let factory = ClientFSMFactory();
let fsms: typestate.FiniteStateMachine<States>[] = [];
for (let i = 0; i < 500; i++) {
fsms.push(factory.getFSM());
}
let currentState = 1;
let possibleStates = [States.A, States.B, States.C, States.D];
function runfsms(){
for (let state of possibleStates){
for (let fsm of fsms) {
fsm.go(state)
console.log("Current state:", fsm.currentState);
console.log("Current state:", fsm.currentState);
}
}
}
runfsms(); I'm a little hesitant to create an duplicate FSM feature that shares the internal state, shared state is a recipe for subtle bugs. However, it may be worthwhile to allow transition functions to easily exist independent of a FSM since they only really describe a valid transition and contain no state so could easily be shared. This would allow for an easier experience building the factory I described. I've opened an issue to allow this behavior #21 |
Thanks for looking into this! I'll try your workaround.
To be honest, I wish this was a bit lower. This overhead will be added to all (~20.000) connected clients and is definitely enough to introduce some serious GC pressure. Not sure what can be done, though.
Fair point. That said, I would be fine with the library throwing an error if attempting to alter transitions once sharing has occurred. |
If you are facing GC pause pressure from object overhead right now, we could reorganized that factory into a pool and pre-allocate ~20,000 FSM at process start. Then you'd only see memory increases/GCs when you need to resize the pool. This is a good example of what I'm talking about https://www.html5rocks.com/en/tutorials/speed/static-mem-pools/ Reseting a FSM after a client connection should be pretty simple (I think you'll only need to zero out the transition functions and reset What kind of constraints are you working with right now on your server? |
I have a situation where I have a lot of FiniteStateMachine instances (one per connected client), but they all have the same transitions defined.
To reduce memory consumption, it would be great if these could share the defined transitions.
Would it be possible to implement an API that creates an FSM based on an existing one?
I belive this is the information that needs to be shared:
Any good workarounds in the current implementation?
The text was updated successfully, but these errors were encountered: