summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2017-06-08 09:52:27 (GMT)
committerStefan Radomski <github@mintwerk.de>2017-06-08 09:52:27 (GMT)
commite9b78b546baf50149d121c96df823d44a709a97c (patch)
tree22fd3f72bf2a43ee78ca5e4fd27e1c130b3e5dc0
parentcdc9c7da381aa296dc48c2494adcf9ca941d0851 (diff)
downloaduscxml-e9b78b546baf50149d121c96df823d44a709a97c.zip
uscxml-e9b78b546baf50149d121c96df823d44a709a97c.tar.gz
uscxml-e9b78b546baf50149d121c96df823d44a709a97c.tar.bz2
Performance improvements
-rw-r--r--src/uscxml/interpreter/BasicDelayedEventQueue.cpp4
-rw-r--r--src/uscxml/interpreter/FastMicroStep.cpp231
-rw-r--r--src/uscxml/interpreter/FastMicroStep.h8
-rw-r--r--src/uscxml/interpreter/InterpreterImpl.cpp10
-rw-r--r--src/uscxml/interpreter/InterpreterMonitor.h9
-rw-r--r--src/uscxml/messages/Event.cpp6
-rw-r--r--src/uscxml/messages/Event.h16
-rw-r--r--src/uscxml/server/HTTPServer.cpp4
-rw-r--r--test/CMakeLists.txt1
-rwxr-xr-xtest/benchmarks/createBenchmarks.pl159
-rw-r--r--test/benchmarks/findLCCA.scxml828
-rw-r--r--test/src/test-gen-c.cpp12
-rw-r--r--test/src/test-performance.cpp46
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;
+ }
+ }
+}