diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-06-08 09:52:27 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-06-08 09:52:27 (GMT) |
commit | e9b78b546baf50149d121c96df823d44a709a97c (patch) | |
tree | 22fd3f72bf2a43ee78ca5e4fd27e1c130b3e5dc0 | |
parent | cdc9c7da381aa296dc48c2494adcf9ca941d0851 (diff) | |
download | uscxml-e9b78b546baf50149d121c96df823d44a709a97c.zip uscxml-e9b78b546baf50149d121c96df823d44a709a97c.tar.gz uscxml-e9b78b546baf50149d121c96df823d44a709a97c.tar.bz2 |
Performance improvements
-rw-r--r-- | src/uscxml/interpreter/BasicDelayedEventQueue.cpp | 4 | ||||
-rw-r--r-- | src/uscxml/interpreter/FastMicroStep.cpp | 231 | ||||
-rw-r--r-- | src/uscxml/interpreter/FastMicroStep.h | 8 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterImpl.cpp | 10 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterMonitor.h | 9 | ||||
-rw-r--r-- | src/uscxml/messages/Event.cpp | 6 | ||||
-rw-r--r-- | src/uscxml/messages/Event.h | 16 | ||||
-rw-r--r-- | src/uscxml/server/HTTPServer.cpp | 4 | ||||
-rw-r--r-- | test/CMakeLists.txt | 1 | ||||
-rwxr-xr-x | test/benchmarks/createBenchmarks.pl | 159 | ||||
-rw-r--r-- | test/benchmarks/findLCCA.scxml | 828 | ||||
-rw-r--r-- | test/src/test-gen-c.cpp | 12 | ||||
-rw-r--r-- | test/src/test-performance.cpp | 46 |
13 files changed, 1245 insertions, 89 deletions
diff --git a/src/uscxml/interpreter/BasicDelayedEventQueue.cpp b/src/uscxml/interpreter/BasicDelayedEventQueue.cpp index ef194ca..885ff2c 100644 --- a/src/uscxml/interpreter/BasicDelayedEventQueue.cpp +++ b/src/uscxml/interpreter/BasicDelayedEventQueue.cpp @@ -194,7 +194,7 @@ Data BasicDelayedEventQueue::serialize() { Data serialized; for (auto event : _queue) { - struct callbackData cb = _callbackData[event.uuid]; + struct callbackData cb = _callbackData[event.getUUID()]; struct timeval delay = {0, 0}; struct timeval now = {0, 0}; @@ -222,7 +222,7 @@ void BasicDelayedEventQueue::deserialize(const Data& data) { std::lock_guard<std::recursive_mutex> lock(_mutex); for (auto event : data["BasicDelayedEventQueue"].array) { Event e = Event::fromData(event["event"]); - enqueueDelayed(e, strTo<size_t>(event["delay"]), e.uuid); + enqueueDelayed(e, strTo<size_t>(event["delay"]), e.getUUID()); } } diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp index 2a95c9c..7ca1171 100644 --- a/src/uscxml/interpreter/FastMicroStep.cpp +++ b/src/uscxml/interpreter/FastMicroStep.cpp @@ -589,6 +589,15 @@ TARGET_SET_ESTABLISHED: } } _cache.exitSet.clear(); + + // initialize bitarrays for step() + _exitSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false); + _entrySet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false); + _targetSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false); + _tmpStates = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false); + _conflicts = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_transitions.size(), false); + _transSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_transitions.size(), false); + _isInitialized = true; } @@ -632,15 +641,16 @@ InterpreterState FastMicroStep::step(size_t blockMs) { return USCXML_INITIALIZED; } + std::set<InterpreterMonitor*> monitors = _callbacks->getMonitors(); size_t i, j, k; - boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet(_states.size(), false); - boost::dynamic_bitset<BITSET_BLOCKTYPE> entrySet(_states.size(), false); - boost::dynamic_bitset<BITSET_BLOCKTYPE> targetSet(_states.size(), false); - boost::dynamic_bitset<BITSET_BLOCKTYPE> tmpStates(_states.size(), false); + _exitSet.reset(); + _entrySet.reset(); + _targetSet.reset(); + _tmpStates.reset(); - boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts(_transitions.size(), false); - boost::dynamic_bitset<BITSET_BLOCKTYPE> transSet(_transitions.size(), false); + _conflicts.reset(); + _transSet.reset(); #ifdef USCXML_VERBOSE std::cerr << "Config: "; @@ -651,7 +661,7 @@ InterpreterState FastMicroStep::step(size_t blockMs) { return USCXML_FINISHED; if (_flags & USCXML_CTX_TOP_LEVEL_FINAL) { - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), beforeCompletion); + USCXML_MONITOR_CALLBACK(monitors, beforeCompletion); /* exit all remaining states */ i = USCXML_NUMBER_STATES; @@ -682,7 +692,7 @@ InterpreterState FastMicroStep::step(size_t blockMs) { _flags |= USCXML_CTX_FINISHED; - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), afterCompletion); + USCXML_MONITOR_CALLBACK(monitors, afterCompletion); return USCXML_FINISHED; } @@ -690,9 +700,9 @@ InterpreterState FastMicroStep::step(size_t blockMs) { if (_flags == USCXML_CTX_PRISTINE) { - targetSet |= USCXML_GET_STATE(0).completion; + _targetSet |= USCXML_GET_STATE(0).completion; _flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED; - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), beforeMicroStep); + USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep); goto ESTABLISH_ENTRYSET; } @@ -704,11 +714,44 @@ InterpreterState FastMicroStep::step(size_t blockMs) { if ((_event = _callbacks->dequeueInternal())) { - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeProcessingEvent, _event); + USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event); goto SELECT_TRANSITIONS; } +#if 1 + /* manage uninvocations */ + i = _invocations.find_first(); + while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + /* uninvoke */ + if (!BIT_HAS(i, _configuration) && USCXML_GET_STATE(i).invoke.size() > 0) { + for (auto invIter = USCXML_GET_STATE(i).invoke.begin(); invIter != USCXML_GET_STATE(i).invoke.end(); invIter++) { + _callbacks->uninvoke(*invIter); + } + BIT_CLEAR(i, _invocations); + } + i = _invocations.find_next(i); + } + /* manage invocations */ + i = _configuration.find_first(); + while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + /* invoke */ + if (!BIT_HAS(i, _invocations) && USCXML_GET_STATE(i).invoke.size() > 0) { + for (auto invIter = USCXML_GET_STATE(i).invoke.begin(); invIter != USCXML_GET_STATE(i).invoke.end(); invIter++) { + try { + _callbacks->invoke(*invIter); + } catch (ErrorEvent e) { + LOG(_callbacks->getLogger(), USCXML_WARN) << e; + // TODO: Shall we deliver the event into the interpreter runtime? + } catch (...) { + } + } + BIT_SET_AT(i, _invocations) + } + i = _configuration.find_next(i); + } +#else + for (i = 0; i < USCXML_NUMBER_STATES; i++) { /* uninvoke */ if (!BIT_HAS(i, _configuration) && BIT_HAS(i, _invocations)) { @@ -735,17 +778,18 @@ InterpreterState FastMicroStep::step(size_t blockMs) { BIT_SET_AT(i, _invocations) } } +#endif // we dequeued all internal events and ought to signal stable configuration if (!(_flags & USCXML_CTX_STABLE)) { - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), onStableConfiguration); + USCXML_MONITOR_CALLBACK(monitors, onStableConfiguration); _microstepConfigurations.clear(); _flags |= USCXML_CTX_STABLE; return USCXML_MACROSTEPPED; } if ((_event = _callbacks->dequeueExternal(blockMs))) { - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeProcessingEvent, _event); + USCXML_MONITOR_CALLBACK1(monitors, beforeProcessingEvent, _event); goto SELECT_TRANSITIONS; } @@ -773,7 +817,7 @@ SELECT_TRANSITIONS: /* is the transition active? */ if (BIT_HAS(USCXML_GET_TRANS(i).source, _configuration)) { /* is it non-conflicting? */ - if (!BIT_HAS(i, conflicts)) { + if (!BIT_HAS(i, _conflicts)) { /* is it spontaneous with an event or vice versa? */ if ((USCXML_GET_TRANS(i).event.size() == 0 && !_event) || (USCXML_GET_TRANS(i).event.size() != 0 && _event)) { @@ -785,15 +829,15 @@ SELECT_TRANSITIONS: _flags |= USCXML_CTX_TRANSITION_FOUND; /* transitions that are pre-empted */ - conflicts |= USCXML_GET_TRANS(i).conflicts; + _conflicts |= USCXML_GET_TRANS(i).conflicts; /* states that are directly targeted (resolve as entry-set later) */ - targetSet |= USCXML_GET_TRANS(i).target; + _targetSet |= USCXML_GET_TRANS(i).target; /* states that will be left */ - exitSet |= USCXML_GET_TRANS(i).exitSet; + _exitSet |= USCXML_GET_TRANS(i).exitSet; - BIT_SET_AT(i, transSet); + BIT_SET_AT(i, _transSet); } } } @@ -805,7 +849,7 @@ SELECT_TRANSITIONS: printStateNames(exitSet); #endif - exitSet &= _configuration; + _exitSet &= _configuration; if (_flags & USCXML_CTX_TRANSITION_FOUND) { // trigger more sppontaneuous transitions @@ -817,7 +861,7 @@ SELECT_TRANSITIONS: return USCXML_MICROSTEPPED; } - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), beforeMicroStep); + USCXML_MONITOR_CALLBACK(monitors, beforeMicroStep); #ifdef USCXML_VERBOSE std::cerr << "Targets: "; @@ -840,17 +884,17 @@ SELECT_TRANSITIONS: if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW || USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP) { /* a history state whose parent is about to be exited */ - if unlikely(BIT_HAS(USCXML_GET_STATE(i).parent, exitSet)) { - tmpStates = USCXML_GET_STATE(i).completion; + if unlikely(BIT_HAS(USCXML_GET_STATE(i).parent, _exitSet)) { + _tmpStates = USCXML_GET_STATE(i).completion; /* set those states who were enabled */ - tmpStates &= _configuration; + _tmpStates &= _configuration; /* clear current history with completion mask */ _history &= ~(USCXML_GET_STATE(i).completion); /* set history */ - _history |= tmpStates; + _history |= _tmpStates; } } @@ -858,27 +902,26 @@ SELECT_TRANSITIONS: ESTABLISH_ENTRYSET: /* calculate new entry set */ - entrySet = targetSet; + _entrySet = _targetSet; /* iterate for ancestors */ - i = entrySet.find_first(); + i = _entrySet.find_first(); while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { - entrySet |= USCXML_GET_STATE(i).ancestors; - i = entrySet.find_next(i); + _entrySet |= USCXML_GET_STATE(i).ancestors; + i = _entrySet.find_next(i); } /* iterate for descendants */ - i = entrySet.find_first(); + i = _entrySet.find_first(); while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { - switch (USCXML_STATE_MASK(USCXML_GET_STATE(i).type)) { case USCXML_STATE_FINAL: case USCXML_STATE_ATOMIC: break; case USCXML_STATE_PARALLEL: { - entrySet |= USCXML_GET_STATE(i).completion; + _entrySet |= USCXML_GET_STATE(i).completion; break; } @@ -890,32 +933,32 @@ ESTABLISH_ENTRYSET: /* nothing set for history, look for a default transition */ for (j = 0; j < _transitions.size(); j++) { if unlikely(USCXML_GET_TRANS(j).source == i) { - entrySet |= USCXML_GET_TRANS(j).target; + _entrySet |= USCXML_GET_TRANS(j).target; if(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP && !BIT_HAS_AND(USCXML_GET_TRANS(j).target, USCXML_GET_STATE(i).children)) { for (k = i + 1; k < _states.size(); k++) { if (BIT_HAS(k, USCXML_GET_TRANS(j).target)) { - entrySet |= USCXML_GET_STATE(k).ancestors; + _entrySet |= USCXML_GET_STATE(k).ancestors; break; } } } - BIT_SET_AT(j, transSet); + BIT_SET_AT(j, _transSet); break; } /* Note: SCXML mandates every history to have a transition! */ } } else { - tmpStates = USCXML_GET_STATE(i).completion; - tmpStates &= _history; - entrySet |= tmpStates; + _tmpStates = USCXML_GET_STATE(i).completion; + _tmpStates &= _history; + _entrySet |= _tmpStates; if (USCXML_GET_STATE(i).type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) { /* a deep history state with nested histories -> more completion */ for (j = i + 1; j < USCXML_NUMBER_STATES; j++) { if (BIT_HAS(j, USCXML_GET_STATE(i).completion) && - BIT_HAS(j, entrySet) && + BIT_HAS(j, _entrySet) && (USCXML_GET_STATE(j).type & USCXML_STATE_HAS_HISTORY)) { for (k = j + 1; k < USCXML_NUMBER_STATES; k++) { /* add nested history to entry_set */ @@ -923,7 +966,7 @@ ESTABLISH_ENTRYSET: USCXML_STATE_MASK(USCXML_GET_STATE(k).type) == USCXML_STATE_HISTORY_SHALLOW) && BIT_HAS(k, USCXML_GET_STATE(j).children)) { /* a nested history state */ - BIT_SET_AT(k, entrySet); + BIT_SET_AT(k, _entrySet); } } } @@ -936,12 +979,12 @@ ESTABLISH_ENTRYSET: case USCXML_STATE_INITIAL: { for (j = 0; j < USCXML_NUMBER_TRANS; j++) { if (USCXML_GET_TRANS(j).source == i) { - BIT_SET_AT(j, transSet); - BIT_CLEAR(i, entrySet); - entrySet |= USCXML_GET_TRANS(j).target; + BIT_SET_AT(j, _transSet); + BIT_CLEAR(i, _entrySet); + _entrySet |= USCXML_GET_TRANS(j).target; for (k = i + 1; k < USCXML_NUMBER_STATES; k++) { if (BIT_HAS(k, USCXML_GET_TRANS(j).target)) { - entrySet |= USCXML_GET_STATE(k).ancestors; + _entrySet |= USCXML_GET_STATE(k).ancestors; } } } @@ -949,15 +992,15 @@ ESTABLISH_ENTRYSET: break; } case USCXML_STATE_COMPOUND: { /* we need to check whether one child is already in entry_set */ - if (!BIT_HAS_AND(entrySet, USCXML_GET_STATE(i).children) && + if (!BIT_HAS_AND(_entrySet, USCXML_GET_STATE(i).children) && (!BIT_HAS_AND(_configuration, USCXML_GET_STATE(i).children) || - BIT_HAS_AND(exitSet, USCXML_GET_STATE(i).children))) { - entrySet |= USCXML_GET_STATE(i).completion; + BIT_HAS_AND(_exitSet, USCXML_GET_STATE(i).children))) { + _entrySet |= USCXML_GET_STATE(i).completion; if (!BIT_HAS_AND(USCXML_GET_STATE(i).completion, USCXML_GET_STATE(i).children)) { /* deep completion */ for (j = i + 1; j < USCXML_NUMBER_STATES; j++) { if (BIT_HAS(j, USCXML_GET_STATE(i).completion)) { - entrySet |= USCXML_GET_STATE(j).ancestors; + _entrySet |= USCXML_GET_STATE(j).ancestors; break; /* completion of compound is single state */ } } @@ -966,7 +1009,7 @@ ESTABLISH_ENTRYSET: break; } } - i = entrySet.find_next(i); + i = _entrySet.find_next(i); } @@ -979,9 +1022,9 @@ ESTABLISH_ENTRYSET: /* we cannot use find_first due to ordering */ i = USCXML_NUMBER_STATES; while(i-- > 0) { - if (BIT_HAS(i, exitSet) && BIT_HAS(i, _configuration)) { + if (BIT_HAS(i, _exitSet) && BIT_HAS(i, _configuration)) { - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeExitingState, USCXML_GET_STATE(i).element); + USCXML_MONITOR_CALLBACK1(monitors, beforeExitingState, USCXML_GET_STATE(i).element); /* call all on exit handlers */ for (auto exitIter = USCXML_GET_STATE(i).onExit.begin(); exitIter != USCXML_GET_STATE(i).onExit.end(); exitIter++) { @@ -993,16 +1036,16 @@ ESTABLISH_ENTRYSET: } BIT_CLEAR(i, _configuration); - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), afterExitingState, USCXML_GET_STATE(i).element); + USCXML_MONITOR_CALLBACK1(monitors, afterExitingState, USCXML_GET_STATE(i).element); } } /* TAKE_TRANSITIONS: */ - i = transSet.find_first(); + i = _transSet.find_first(); while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { if ((USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) { - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeTakingTransition, USCXML_GET_TRANS(i).element); + USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, USCXML_GET_TRANS(i).element); if (USCXML_GET_TRANS(i).onTrans != NULL) { @@ -1014,10 +1057,10 @@ ESTABLISH_ENTRYSET: } } - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), afterTakingTransition, USCXML_GET_TRANS(i).element); + USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, USCXML_GET_TRANS(i).element); } - i = transSet.find_next(i); + i = _transSet.find_next(i); } #ifdef USCXML_VERBOSE @@ -1027,12 +1070,12 @@ ESTABLISH_ENTRYSET: /* ENTER_STATES: */ - i = entrySet.find_first(); + i = _entrySet.find_first(); while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { if (BIT_HAS(i, _configuration)) { // already active - i = entrySet.find_next(i); + i = _entrySet.find_next(i); continue; } @@ -1040,11 +1083,11 @@ ESTABLISH_ENTRYSET: if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP || USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW || USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_INITIAL) { - i = entrySet.find_next(i); + i = _entrySet.find_next(i); continue; } - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeEnteringState, USCXML_GET_STATE(i).element); + USCXML_MONITOR_CALLBACK1(monitors, beforeEnteringState, USCXML_GET_STATE(i).element); BIT_SET_AT(i, _configuration); @@ -1065,15 +1108,16 @@ ESTABLISH_ENTRYSET: } } - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), afterEnteringState, USCXML_GET_STATE(i).element); + USCXML_MONITOR_CALLBACK1(monitors, afterEnteringState, USCXML_GET_STATE(i).element); /* take history and initial transitions */ +#if 0 for (j = 0; j < USCXML_NUMBER_TRANS; j++) { - if unlikely(BIT_HAS(j, transSet) && + if unlikely(BIT_HAS(j, _transSet) && (USCXML_GET_TRANS(j).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) && USCXML_GET_STATE(USCXML_GET_TRANS(j).source).parent == i) { - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), beforeTakingTransition, USCXML_GET_TRANS(j).element); + USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, USCXML_GET_TRANS(j).element); /* call executable content in transition */ if (USCXML_GET_TRANS(j).onTrans != NULL) { @@ -1084,10 +1128,33 @@ ESTABLISH_ENTRYSET: } } - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), afterTakingTransition, USCXML_GET_TRANS(j).element); + USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, USCXML_GET_TRANS(j).element); } } +#else + j = _transSet.find_first(); + while(j != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + if unlikely((USCXML_GET_TRANS(j).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) && + USCXML_GET_STATE(USCXML_GET_TRANS(j).source).parent == i) { + + USCXML_MONITOR_CALLBACK1(monitors, beforeTakingTransition, USCXML_GET_TRANS(j).element); + + /* call executable content in transition */ + if (USCXML_GET_TRANS(j).onTrans != NULL) { + try { + _callbacks->process(USCXML_GET_TRANS(j).onTrans); + } catch (...) { + // do nothing and continue with next block + } + } + + USCXML_MONITOR_CALLBACK1(monitors, afterTakingTransition, USCXML_GET_TRANS(j).element); + } + + j = _transSet.find_next(j); + } +#endif /* handle final states */ if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_FINAL) { @@ -1106,30 +1173,56 @@ ESTABLISH_ENTRYSET: * 3. Iterate all active final states and remove their ancestors * 4. If a state remains, not all children of a parallel are final */ +#if 0 for (j = 0; j < USCXML_NUMBER_STATES; j++) { if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(j).type) == USCXML_STATE_PARALLEL && BIT_HAS(j, USCXML_GET_STATE(i).ancestors)) { - tmpStates.reset(); + _tmpStates.reset(); k = _configuration.find_first(); while (k != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { if (BIT_HAS(j, USCXML_GET_STATE(k).ancestors)) { if (USCXML_STATE_MASK(USCXML_GET_STATE(k).type) == USCXML_STATE_FINAL) { - tmpStates ^= USCXML_GET_STATE(k).ancestors; + _tmpStates ^= USCXML_GET_STATE(k).ancestors; } else { - BIT_SET_AT(k, tmpStates); + BIT_SET_AT(k, _tmpStates); } } k = _configuration.find_next(k); } - if (!tmpStates.any()) { + if (!_tmpStates.any()) { // raise done for state j _callbacks->raiseDoneEvent(USCXML_GET_STATE(j).element, USCXML_GET_STATE(j).doneData); } } } +#else + j = USCXML_GET_STATE(i).ancestors.find_first(); + while(j != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(j).type) == USCXML_STATE_PARALLEL) { + _tmpStates.reset(); + k = _configuration.find_first(); + while (k != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + if (BIT_HAS(j, USCXML_GET_STATE(k).ancestors)) { + if (USCXML_STATE_MASK(USCXML_GET_STATE(k).type) == USCXML_STATE_FINAL) { + _tmpStates ^= USCXML_GET_STATE(k).ancestors; + } else { + BIT_SET_AT(k, _tmpStates); + } + } + k = _configuration.find_next(k); + } + if (!_tmpStates.any()) { + // raise done for state j + _callbacks->raiseDoneEvent(USCXML_GET_STATE(j).element, USCXML_GET_STATE(j).doneData); + } + } + + j = USCXML_GET_STATE(i).ancestors.find_next(j); + } +#endif } } - USCXML_MONITOR_CALLBACK(_callbacks->getMonitors(), afterMicroStep); + USCXML_MONITOR_CALLBACK(monitors, afterMicroStep); // are we running in circles? if (_microstepConfigurations.find(_configuration) != _microstepConfigurations.end()) { @@ -1137,7 +1230,7 @@ ESTABLISH_ENTRYSET: NULL, InterpreterIssue::USCXML_ISSUE_WARNING); - USCXML_MONITOR_CALLBACK1(_callbacks->getMonitors(), + USCXML_MONITOR_CALLBACK1(monitors, reportIssue, issue); } diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h index 6c5518d..ca1f697 100644 --- a/src/uscxml/interpreter/FastMicroStep.h +++ b/src/uscxml/interpreter/FastMicroStep.h @@ -149,6 +149,14 @@ private: CachedPredicates _cache; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _exitSet; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _entrySet; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _targetSet; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _tmpStates; + + boost::dynamic_bitset<BITSET_BLOCKTYPE> _conflicts; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _transSet; + #ifdef USCXML_VERBOSE void printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset); #endif diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp index bc8d2b9..18b27f8 100644 --- a/src/uscxml/interpreter/InterpreterImpl.cpp +++ b/src/uscxml/interpreter/InterpreterImpl.cpp @@ -507,15 +507,15 @@ Event InterpreterImpl::dequeueExternal(size_t blockMs) { void InterpreterImpl::enqueue(const std::string& type, const std::string& target, size_t delayMs, const Event& sendEvent) { std::lock_guard<std::recursive_mutex> lock(_delayMutex); - assert(sendEvent.uuid.length() > 0); - assert(_delayedEventTargets.find(sendEvent.uuid) == _delayedEventTargets.end()); + assert(sendEvent.getUUID().length() > 0); + assert(_delayedEventTargets.find(sendEvent.getUUID()) == _delayedEventTargets.end()); - _delayedEventTargets[sendEvent.uuid] = std::tuple<std::string, std::string, std::string>(sendEvent.sendid, type, target); + _delayedEventTargets[sendEvent.getUUID()] = std::tuple<std::string, std::string, std::string>(sendEvent.sendid, type, target); if (delayMs == 0) { Event copy(sendEvent); - return eventReady(copy, sendEvent.uuid); + return eventReady(copy, sendEvent.getUUID()); } else { - return _delayQueue.enqueueDelayed(sendEvent, delayMs, sendEvent.uuid); + return _delayQueue.enqueueDelayed(sendEvent, delayMs, sendEvent.getUUID()); } } diff --git a/src/uscxml/interpreter/InterpreterMonitor.h b/src/uscxml/interpreter/InterpreterMonitor.h index 27222b4..70cac0c 100644 --- a/src/uscxml/interpreter/InterpreterMonitor.h +++ b/src/uscxml/interpreter/InterpreterMonitor.h @@ -34,16 +34,19 @@ catch (...) { LOG(USCXML_ERROR) << "An exception occurred when calling " #callba if (_state == USCXML_DESTROYED) { throw std::bad_weak_ptr(); } #define USCXML_MONITOR_CALLBACK(callbacks, function) { \ +if (callbacks.size() > 0) {\ Interpreter inptr = _callbacks->getInterpreter(); \ -for (auto callback : callbacks) { callback->function(inptr); } } +for (auto callback : callbacks) { callback->function(inptr); } } } #define USCXML_MONITOR_CALLBACK1(callbacks, function, arg1) { \ +if (callbacks.size() > 0) {\ Interpreter inptr = _callbacks->getInterpreter(); \ -for (auto callback : callbacks) { callback->function(inptr, arg1); } } +for (auto callback : callbacks) { callback->function(inptr, arg1); } } } #define USCXML_MONITOR_CALLBACK2(callbacks, function, arg1, arg2) { \ +if (callbacks.size() > 0) {\ Interpreter inptr = _callbacks->getInterpreter(); \ -for (auto callback : callbacks) { callback->function(inptr, arg1, arg2); } } +for (auto callback : callbacks) { callback->function(inptr, arg1, arg2); } } } // forward declare namespace XERCESC_NS { diff --git a/src/uscxml/messages/Event.cpp b/src/uscxml/messages/Event.cpp index 5b933dc..a7863c5 100644 --- a/src/uscxml/messages/Event.cpp +++ b/src/uscxml/messages/Event.cpp @@ -21,6 +21,12 @@ namespace uscxml { +Event::Event() : eventType(INTERNAL), hideSendId(false) { +} + +Event::Event(const std::string& name, Type type) : name(name), eventType(type), hideSendId(false) { +} + Event Event::fromData(const Data& data) { Event e; if (data.hasKey("data")) diff --git a/src/uscxml/messages/Event.h b/src/uscxml/messages/Event.h index f40a672..c4d818b 100644 --- a/src/uscxml/messages/Event.h +++ b/src/uscxml/messages/Event.h @@ -107,8 +107,8 @@ public: PLATFORM = 3 }; - Event() : eventType(INTERNAL), hideSendId(false), uuid(UUID::getUUID()) {} - explicit Event(const std::string& name, Type type = INTERNAL) : name(name), eventType(type), hideSendId(false) {} + Event(); + explicit Event(const std::string& name, Type type = INTERNAL); static Event fromData(const Data& data); bool operator< (const Event& other) const { @@ -197,6 +197,14 @@ public: return false; } + const std::string& getUUID() const { + // this is expensive - lazy initialization + if (uuid.length() == 0) { + uuid = UUID::getUUID(); + } + return uuid; + } + std::string raw; std::string name; Type eventType; @@ -208,7 +216,9 @@ public: Data data; std::map<std::string, Data> namelist; std::multimap<std::string, Data> params; - std::string uuid; // the sendid is not necessarily unique! + +private: + mutable std::string uuid; // the sendid is not necessarily unique! friend USCXML_API std::ostream& operator<< (std::ostream& os, const Event& event); }; diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index aa43002..29dd9a6 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -736,7 +736,9 @@ void HTTPServer::start() { void HTTPServer::run(void* instance) { HTTPServer* INSTANCE = (HTTPServer*)instance; while(INSTANCE->_isRunning) { - event_base_dispatch(INSTANCE->_base); + // getting this to be non-polling is somewhat tricky and changes among versions + event_base_loop(INSTANCE->_base, EVLOOP_ONCE | EVLOOP_NO_EXIT_ON_EMPTY); +// event_base_dispatch(INSTANCE->_base); } LOGD(USCXML_INFO) << "HTTP Server stopped" << std::endl; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9e5b61f..89962f9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,6 +61,7 @@ if(WITH_DM_LUA AND NOT BUILD_AS_PLUGINS) endif() USCXML_TEST_COMPILE(NAME test-url LABEL general/test-url FILES src/test-url.cpp) USCXML_TEST_COMPILE(NAME test-utf8 LABEL general/test-utf8 FILES src/test-utf8.cpp) +USCXML_TEST_COMPILE(BUILD_ONLY NAME test-performance LABEL general/test-performance FILES src/test-performance.cpp) USCXML_TEST_COMPILE(NAME test-lifecycle LABEL general/test-lifecycle FILES src/test-lifecycle.cpp) USCXML_TEST_COMPILE(NAME test-validating LABEL general/test-validating FILES src/test-validating.cpp) USCXML_TEST_COMPILE(NAME test-snippets LABEL general/test-snippets FILES src/test-snippets.cpp) diff --git a/test/benchmarks/createBenchmarks.pl b/test/benchmarks/createBenchmarks.pl new file mode 100755 index 0000000..231c843 --- /dev/null +++ b/test/benchmarks/createBenchmarks.pl @@ -0,0 +1,159 @@ +#!/usr/bin/perl -w + +use strict; +use List::Util qw[min max sum]; + +use warnings; +no warnings 'recursion'; + +use Getopt::Long qw(GetOptions); +use Data::Dumper; + +my %options = (); + +GetOptions( + \%options, + "depth-max=i", + "child-max=i", + "events-max=i", + "states-max=i", + "trans-max=i", + "random-seed=i" +); + +my $seed = $options{'random-seed'} || int(rand(2**31)); + +# $maxStates = 8; +# $maxTrans = 8 + +srand($seed); + +my $machine; +my $stateId = 1; + + +sub createFindLCCABenchmark { + my $where = shift; + + my $nestingDepth = 20; + my $parallelStates = 20; + + $$where->{'name'} = 'findLCCA'; + $$where->{'type'} = 'scxml'; + $$where->{'intial'} = ""; + for (my $i = 1; $i <= $parallelStates; $i++) { + $$where->{'initial'} .= "id" . ($i*$nestingDepth) . " "; + } + + $$where->{'children'}[0]->{'type'} = 'parallel'; + $$where->{'children'}[0]->{'id'} = "p0"; + for (my $i = 0; $i < $parallelStates; $i++) { + createFindLCCANestedCompounds(\$$where->{'children'}[0]->{'children'}, $nestingDepth, $nestingDepth * $parallelStates + 1); + } + + $$where->{'children'}[1]->{'type'} = 'state'; + $$where->{'children'}[1]->{'id'} = "id".$stateId++; + $$where->{'children'}[1]->{'transitions'}[0]->{'target'} = $$where->{'initial'}; + +} + +sub createFindLCCANestedCompounds { + my $where = shift; + my $amount = shift; + my $target = shift; + + if ($amount > 0) { + my $state; + $state->{'id'} = "id".$stateId++; + $state->{'type'} = "state"; + createFindLCCANestedCompounds(\$state->{'children'}, $amount - 1, $target); + + if ($amount == 1) { + $state->{'transitions'}[0]->{'target'} = "id".$target; + } + + push @{$$where}, $state; + } + + +} + + +sub writeState { + my $state = shift; + my $fh = shift; + + print $fh '<'.$state->{'type'}; + print $fh ' id="'.$state->{'id'} . '"'; + print $fh ' type="deep"' if exists $state->{'deep'}; + print $fh '>'; + + foreach (@{$state->{'children'}}) { + writeState($_, $fh); + } + + foreach (@{$state->{'transitions'}}) { + writeTransition($_, $fh); + } + + print $fh '</'.$state->{'type'} . '>'; + +}; + +sub writeTransition { + my $trans = shift; + my $fh = shift; + + print $fh '<transition'; + print $fh ' target="' . $trans->{'target'} . '"' if $trans->{'target'}; + print $fh ' event="' . $trans->{'event'} . '"' if $trans->{'event'}; + print $fh ' cond="' . $trans->{'cond'} . '"' if $trans->{'cond'}; + + if ($trans->{'execContent'}) { + print $fh '>'; + foreach (@{$trans->{'execContent'}}) { + print $fh $_; + } + print $fh '</transition>'; + } else { + print $fh '/>'; + } + +}; + +sub writeMachine { + my $machine = shift; + my $file = shift; + + open(my $fh, ">", $file) or die "Can't open > $file: $!"; + + print $fh '<scxml'; + print $fh ' datamodel="' . $machine->{'datamodel'} . '"' if $machine->{'datamodel'}; + print $fh ' seed="' . $seed . '"'; + print $fh ' name="' . $machine->{'name'} . '"' if $machine->{'name'}; + print $fh ' initial="' . $machine->{'initial'} . '"' if $machine->{'initial'}; + print $fh '>'; + + foreach (@{$machine->{'children'}}) { + writeState($_, $fh); + } + + print $fh '</scxml>'; +} + +sub xmllint { + my $file = shift; + `mv $file $file.unformatted.xml`; + `xmllint --format $file.unformatted.xml > $file`; + `rm $file.unformatted.xml`; +} + +{ + $machine = {}; + $stateId = 1; + + createFindLCCABenchmark(\$machine); + # print Dumper($machine); + writeMachine($machine, "findLCCA.scxml"); + xmllint("findLCCA.scxml"); +} diff --git a/test/benchmarks/findLCCA.scxml b/test/benchmarks/findLCCA.scxml new file mode 100644 index 0000000..de2e8ce --- /dev/null +++ b/test/benchmarks/findLCCA.scxml @@ -0,0 +1,828 @@ +<?xml version="1.0"?> +<scxml seed="341532910" name="findLCCA" initial="id20 id40 id60 id80 id100 id120 id140 id160 id180 id200 id220 id240 id260 id280 id300 id320 id340 id360 id380 id400 "> + <parallel id="p0"> + <state id="id1"> + <state id="id2"> + <state id="id3"> + <state id="id4"> + <state id="id5"> + <state id="id6"> + <state id="id7"> + <state id="id8"> + <state id="id9"> + <state id="id10"> + <state id="id11"> + <state id="id12"> + <state id="id13"> + <state id="id14"> + <state id="id15"> + <state id="id16"> + <state id="id17"> + <state id="id18"> + <state id="id19"> + <state id="id20"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id21"> + <state id="id22"> + <state id="id23"> + <state id="id24"> + <state id="id25"> + <state id="id26"> + <state id="id27"> + <state id="id28"> + <state id="id29"> + <state id="id30"> + <state id="id31"> + <state id="id32"> + <state id="id33"> + <state id="id34"> + <state id="id35"> + <state id="id36"> + <state id="id37"> + <state id="id38"> + <state id="id39"> + <state id="id40"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id41"> + <state id="id42"> + <state id="id43"> + <state id="id44"> + <state id="id45"> + <state id="id46"> + <state id="id47"> + <state id="id48"> + <state id="id49"> + <state id="id50"> + <state id="id51"> + <state id="id52"> + <state id="id53"> + <state id="id54"> + <state id="id55"> + <state id="id56"> + <state id="id57"> + <state id="id58"> + <state id="id59"> + <state id="id60"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id61"> + <state id="id62"> + <state id="id63"> + <state id="id64"> + <state id="id65"> + <state id="id66"> + <state id="id67"> + <state id="id68"> + <state id="id69"> + <state id="id70"> + <state id="id71"> + <state id="id72"> + <state id="id73"> + <state id="id74"> + <state id="id75"> + <state id="id76"> + <state id="id77"> + <state id="id78"> + <state id="id79"> + <state id="id80"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id81"> + <state id="id82"> + <state id="id83"> + <state id="id84"> + <state id="id85"> + <state id="id86"> + <state id="id87"> + <state id="id88"> + <state id="id89"> + <state id="id90"> + <state id="id91"> + <state id="id92"> + <state id="id93"> + <state id="id94"> + <state id="id95"> + <state id="id96"> + <state id="id97"> + <state id="id98"> + <state id="id99"> + <state id="id100"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id101"> + <state id="id102"> + <state id="id103"> + <state id="id104"> + <state id="id105"> + <state id="id106"> + <state id="id107"> + <state id="id108"> + <state id="id109"> + <state id="id110"> + <state id="id111"> + <state id="id112"> + <state id="id113"> + <state id="id114"> + <state id="id115"> + <state id="id116"> + <state id="id117"> + <state id="id118"> + <state id="id119"> + <state id="id120"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id121"> + <state id="id122"> + <state id="id123"> + <state id="id124"> + <state id="id125"> + <state id="id126"> + <state id="id127"> + <state id="id128"> + <state id="id129"> + <state id="id130"> + <state id="id131"> + <state id="id132"> + <state id="id133"> + <state id="id134"> + <state id="id135"> + <state id="id136"> + <state id="id137"> + <state id="id138"> + <state id="id139"> + <state id="id140"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id141"> + <state id="id142"> + <state id="id143"> + <state id="id144"> + <state id="id145"> + <state id="id146"> + <state id="id147"> + <state id="id148"> + <state id="id149"> + <state id="id150"> + <state id="id151"> + <state id="id152"> + <state id="id153"> + <state id="id154"> + <state id="id155"> + <state id="id156"> + <state id="id157"> + <state id="id158"> + <state id="id159"> + <state id="id160"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id161"> + <state id="id162"> + <state id="id163"> + <state id="id164"> + <state id="id165"> + <state id="id166"> + <state id="id167"> + <state id="id168"> + <state id="id169"> + <state id="id170"> + <state id="id171"> + <state id="id172"> + <state id="id173"> + <state id="id174"> + <state id="id175"> + <state id="id176"> + <state id="id177"> + <state id="id178"> + <state id="id179"> + <state id="id180"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id181"> + <state id="id182"> + <state id="id183"> + <state id="id184"> + <state id="id185"> + <state id="id186"> + <state id="id187"> + <state id="id188"> + <state id="id189"> + <state id="id190"> + <state id="id191"> + <state id="id192"> + <state id="id193"> + <state id="id194"> + <state id="id195"> + <state id="id196"> + <state id="id197"> + <state id="id198"> + <state id="id199"> + <state id="id200"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id201"> + <state id="id202"> + <state id="id203"> + <state id="id204"> + <state id="id205"> + <state id="id206"> + <state id="id207"> + <state id="id208"> + <state id="id209"> + <state id="id210"> + <state id="id211"> + <state id="id212"> + <state id="id213"> + <state id="id214"> + <state id="id215"> + <state id="id216"> + <state id="id217"> + <state id="id218"> + <state id="id219"> + <state id="id220"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id221"> + <state id="id222"> + <state id="id223"> + <state id="id224"> + <state id="id225"> + <state id="id226"> + <state id="id227"> + <state id="id228"> + <state id="id229"> + <state id="id230"> + <state id="id231"> + <state id="id232"> + <state id="id233"> + <state id="id234"> + <state id="id235"> + <state id="id236"> + <state id="id237"> + <state id="id238"> + <state id="id239"> + <state id="id240"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id241"> + <state id="id242"> + <state id="id243"> + <state id="id244"> + <state id="id245"> + <state id="id246"> + <state id="id247"> + <state id="id248"> + <state id="id249"> + <state id="id250"> + <state id="id251"> + <state id="id252"> + <state id="id253"> + <state id="id254"> + <state id="id255"> + <state id="id256"> + <state id="id257"> + <state id="id258"> + <state id="id259"> + <state id="id260"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id261"> + <state id="id262"> + <state id="id263"> + <state id="id264"> + <state id="id265"> + <state id="id266"> + <state id="id267"> + <state id="id268"> + <state id="id269"> + <state id="id270"> + <state id="id271"> + <state id="id272"> + <state id="id273"> + <state id="id274"> + <state id="id275"> + <state id="id276"> + <state id="id277"> + <state id="id278"> + <state id="id279"> + <state id="id280"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id281"> + <state id="id282"> + <state id="id283"> + <state id="id284"> + <state id="id285"> + <state id="id286"> + <state id="id287"> + <state id="id288"> + <state id="id289"> + <state id="id290"> + <state id="id291"> + <state id="id292"> + <state id="id293"> + <state id="id294"> + <state id="id295"> + <state id="id296"> + <state id="id297"> + <state id="id298"> + <state id="id299"> + <state id="id300"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id301"> + <state id="id302"> + <state id="id303"> + <state id="id304"> + <state id="id305"> + <state id="id306"> + <state id="id307"> + <state id="id308"> + <state id="id309"> + <state id="id310"> + <state id="id311"> + <state id="id312"> + <state id="id313"> + <state id="id314"> + <state id="id315"> + <state id="id316"> + <state id="id317"> + <state id="id318"> + <state id="id319"> + <state id="id320"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id321"> + <state id="id322"> + <state id="id323"> + <state id="id324"> + <state id="id325"> + <state id="id326"> + <state id="id327"> + <state id="id328"> + <state id="id329"> + <state id="id330"> + <state id="id331"> + <state id="id332"> + <state id="id333"> + <state id="id334"> + <state id="id335"> + <state id="id336"> + <state id="id337"> + <state id="id338"> + <state id="id339"> + <state id="id340"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id341"> + <state id="id342"> + <state id="id343"> + <state id="id344"> + <state id="id345"> + <state id="id346"> + <state id="id347"> + <state id="id348"> + <state id="id349"> + <state id="id350"> + <state id="id351"> + <state id="id352"> + <state id="id353"> + <state id="id354"> + <state id="id355"> + <state id="id356"> + <state id="id357"> + <state id="id358"> + <state id="id359"> + <state id="id360"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id361"> + <state id="id362"> + <state id="id363"> + <state id="id364"> + <state id="id365"> + <state id="id366"> + <state id="id367"> + <state id="id368"> + <state id="id369"> + <state id="id370"> + <state id="id371"> + <state id="id372"> + <state id="id373"> + <state id="id374"> + <state id="id375"> + <state id="id376"> + <state id="id377"> + <state id="id378"> + <state id="id379"> + <state id="id380"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + <state id="id381"> + <state id="id382"> + <state id="id383"> + <state id="id384"> + <state id="id385"> + <state id="id386"> + <state id="id387"> + <state id="id388"> + <state id="id389"> + <state id="id390"> + <state id="id391"> + <state id="id392"> + <state id="id393"> + <state id="id394"> + <state id="id395"> + <state id="id396"> + <state id="id397"> + <state id="id398"> + <state id="id399"> + <state id="id400"> + <transition target="id401"/> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </state> + </parallel> + <state id="id401"> + <transition target="id20 id40 id60 id80 id100 id120 id140 id160 id180 id200 id220 id240 id260 id280 id300 id320 id340 id360 id380 id400 "/> + </state> +</scxml> diff --git a/test/src/test-gen-c.cpp b/test/src/test-gen-c.cpp index b7cee32..0f83da3 100644 --- a/test/src/test-gen-c.cpp +++ b/test/src/test-gen-c.cpp @@ -570,11 +570,11 @@ public: e.invokeid = USER_DATA(ctx)->invokeId; } - USER_DATA(ctx)->sendUUIDs[e.uuid] = std::make_tuple(e.sendid, target, type); + USER_DATA(ctx)->sendUUIDs[e.getUUID()] = std::make_tuple(e.sendid, target, type); if (delayMs > 0) { - USER_DATA(ctx)->delayQueue.enqueueDelayed(e, delayMs, e.uuid); + USER_DATA(ctx)->delayQueue.enqueueDelayed(e, delayMs, e.getUUID()); } else { - USER_DATA(ctx)->eventReady(e, e.uuid); + USER_DATA(ctx)->eventReady(e, e.getUUID()); } return USCXML_ERR_OK; @@ -840,9 +840,9 @@ public: //std::make_tuple(e.sendid, target, type); - std::string sendid = std::get<0>(sendUUIDs[e.uuid]); - std::string target = std::get<1>(sendUUIDs[e.uuid]); - std::string type = std::get<2>(sendUUIDs[e.uuid]); + std::string sendid = std::get<0>(sendUUIDs[e.getUUID()]); + std::string target = std::get<1>(sendUUIDs[e.getUUID()]); + std::string type = std::get<2>(sendUUIDs[e.getUUID()]); if (target == "#_internal") { e.eventType = Event::INTERNAL; diff --git a/test/src/test-performance.cpp b/test/src/test-performance.cpp new file mode 100644 index 0000000..8df740d --- /dev/null +++ b/test/src/test-performance.cpp @@ -0,0 +1,46 @@ +#include "uscxml/config.h" +#include "uscxml/Interpreter.h" +#include <sys/time.h> + +#include <iostream> + +using namespace uscxml; +using namespace std::chrono; + +int main(int argc, char** argv) { + if (argc < 2) { + std::cout << "Expected filename as first parameter" << std::endl; + exit(EXIT_FAILURE); + } + + Interpreter interpreter = Interpreter::fromURL(argv[1]); + + InterpreterState state; + system_clock::time_point start = system_clock::now(); + + while((state = interpreter.step()) != InterpreterState::USCXML_INITIALIZED) {} + system_clock::time_point now = system_clock::now(); + + std::cout << "init: " << duration_cast<milliseconds>(now - start).count() << "ms" << std::endl; + + start = system_clock::now(); + system_clock::time_point endTime = start + seconds(10); + system_clock::time_point report = start + seconds(1); + + unsigned long iterations = 0; + + while(true) { + now = system_clock::now(); + if (now > endTime) + break; + + interpreter.step(); + + iterations++; + if (now > report) { + report = now + seconds(1); + std::cout << "steps / sec: " << iterations << std::endl; + iterations = 0; + } + } +} |