diff options
author | Stefan Radomski <github@mintwerk.de> | 2017-07-10 15:13:06 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2017-07-10 15:13:06 (GMT) |
commit | 286f8d747d198a66b81396ba8197b101ae2d59ed (patch) | |
tree | 2ad222fdbcb2ba6f7ead0ca41e5a6d98ae4c4287 | |
parent | 799a95c560338643894ffd80510db8b48baa2f45 (diff) | |
download | uscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.zip uscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.tar.gz uscxml-286f8d747d198a66b81396ba8197b101ae2d59ed.tar.bz2 |
More performance for microsteppers
-rw-r--r-- | src/uscxml/interpreter/FastMicroStep.cpp | 263 | ||||
-rw-r--r-- | src/uscxml/interpreter/FastMicroStep.h | 43 | ||||
-rw-r--r-- | src/uscxml/interpreter/InterpreterImpl.cpp | 11 | ||||
-rw-r--r-- | src/uscxml/interpreter/LargeMicroStep.cpp | 70 | ||||
-rw-r--r-- | src/uscxml/interpreter/LargeMicroStep.h | 8 | ||||
-rw-r--r-- | src/uscxml/util/Convenience.cpp | 5 | ||||
-rw-r--r-- | src/uscxml/util/DOM.h | 6 | ||||
-rw-r--r-- | src/uscxml/util/Predicates.cpp | 16 | ||||
-rw-r--r-- | test/src/test-lifecycle.cpp | 36 | ||||
-rw-r--r-- | test/src/test-serialization.cpp | 5 | ||||
-rw-r--r-- | test/src/test-stress.cpp | 2 | ||||
-rw-r--r-- | test/src/test-validating.cpp | 2 |
12 files changed, 315 insertions, 152 deletions
diff --git a/src/uscxml/interpreter/FastMicroStep.cpp b/src/uscxml/interpreter/FastMicroStep.cpp index d6ad298..1345403 100644 --- a/src/uscxml/interpreter/FastMicroStep.cpp +++ b/src/uscxml/interpreter/FastMicroStep.cpp @@ -17,8 +17,6 @@ * @endcond */ -#undef USCXML_VERBOSE -//#undef WITH_CACHE_FILES #include "uscxml/config.h" #include "FastMicroStep.h" @@ -31,6 +29,12 @@ #include "uscxml/interpreter/Logging.h" +#include <stdlib.h> // strtol +#include <iostream> + +#undef USCXML_VERBOSE +#undef WITH_CACHE_FILES + #define BIT_ANY_SET(b) (!b.none()) #define BIT_HAS(idx, bitset) (bitset[idx]) #define BIT_HAS_AND(bitset1, bitset2) bitset1.intersects(bitset2) @@ -201,33 +205,89 @@ void FastMicroStep::resortStates(DOMElement* element, const X& xmlPrefix) { } } -std::list<XERCESC_NS::DOMElement*> FastMicroStep::getExitSetCached(const XERCESC_NS::DOMElement* transition, - const XERCESC_NS::DOMElement* root) { +std::pair<uint32_t, uint32_t> FastMicroStep::getExitSet(const Transition* transition) { + if (_exitSetCache.find(transition->postFixOrder) == _exitSetCache.end()) { + std::pair<uint32_t, uint32_t> statesToExit; + uint32_t domain = getTransitionDomain(transition); + if (domain == std::numeric_limits<uint32_t>::max()) + return statesToExit; + + State* domainState = _states[domain]; + + // start of exit set + statesToExit.first = domainState->documentOrder + 1; // do not include domain itself + + // end of exit set + XERCESC_NS::DOMElement* sibling = domainState->element->getNextElementSibling(); + while(sibling && !isState(sibling)) + sibling = sibling->getNextElementSibling(); + if (sibling) { + State* siblingState = (State*)sibling->getUserData(X("uscxmlState")); + statesToExit.second = siblingState->documentOrder - 1; + } else { + statesToExit.second = _states.size() - 1; + } + _exitSetCache[transition->postFixOrder] = statesToExit; + return statesToExit; + } + return _exitSetCache[transition->postFixOrder]; +} + +uint32_t FastMicroStep::getTransitionDomain(const Transition* transition) { + size_t i, j; + if (!transition->target.any()) + return std::numeric_limits<uint32_t>::max(); + + bool internal = (HAS_ATTR(transition->element, kXMLCharType) ? ATTR(transition->element, kXMLCharType) == "internal" : false); + if (internal && USCXML_STATE_MASK(_states[transition->source]->type) == USCXML_STATE_COMPOUND) { + i = transition->target.find_first(); + while(i != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + if(!(_states[i]->ancestors[transition->source])) { + goto BREAK_LOOP; + } + i = transition->target.find_next(i); - if (_cache.exitSet.find(transition) == _cache.exitSet.end()) { - _cache.exitSet[transition] = getExitSet(transition, root); + } + return _states[transition->source]->documentOrder; } +BREAK_LOOP: - return _cache.exitSet[transition]; -} + // find LCCA + uint32_t ancestor = std::numeric_limits<uint32_t>::max(); -bool FastMicroStep::conflictsCached(const DOMElement* t1, const DOMElement* t2, const DOMElement* root) { - if (getSourceState(t1) == getSourceState(t2)) - return true; + // reverse walk up! + i = _states[transition->source]->parent; + State* anc = _states[i]; - if (DOMUtils::isDescendant(getSourceState(t1), getSourceState(t2))) - return true; + while(anc) { + if (USCXML_STATE_MASK(anc->type) != USCXML_STATE_COMPOUND) { + // LCCA has to be a compound + anc = _states[anc->parent]; + continue; + } - if (DOMUtils::isDescendant(getSourceState(t2), getSourceState(t1))) - return true; + j = transition->target.find_first(); + while(j != boost::dynamic_bitset<BITSET_BLOCKTYPE>::npos) { + if (!(_states[j]->ancestors[anc->documentOrder])) { + goto NEXT_ANCESTOR; + } + j = transition->target.find_next(j); + } - if (DOMUtils::hasIntersection(getExitSetCached(t1, root), getExitSetCached(t2, root))) - return true; + ancestor = anc->documentOrder; + break; +NEXT_ANCESTOR: + anc = _states[anc->parent]; + if (anc->documentOrder == 0) + break; + } - return false; + // none found - take uppermost root as ancestor + if (ancestor == std::numeric_limits<uint32_t>::max()) + return 0; + return ancestor; } - void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { _scxml = scxml; @@ -266,8 +326,7 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { _invocations.resize(tmp.size()); for (i = 0; i < _states.size(); i++) { - _states[i] = new State(); - _states[i]->documentOrder = i; + _states[i] = new State(i); _states[i]->element = tmp.front(); if (HAS_ATTR(_states[i]->element, kXMLCharId)) { _states[i]->name = ATTR(_states[i]->element, kXMLCharId); @@ -391,12 +450,24 @@ void FastMicroStep::init(XERCESC_NS::DOMElement* scxml) { cachedState->compound["completion"] = Data(toBase64(_states[i]->completion)); COMPLETION_STABLISHED: #endif + + +#ifdef WITH_CACHE_FILES + if (withCache && cachedState->compound.find("hasHistoryChild") != cachedState->compound.end()) { + _states[i]->element->setUserData(X("hasHistoryChild"), _states[strTo<uint32_t>(cachedState->compound["hasHistoryChild"])], NULL); + } +#endif + // this is set when establishing the completion if (_states[i]->element->getUserData(X("hasHistoryChild")) == _states[i]) { _states[i]->type |= USCXML_STATE_HAS_HISTORY; +#ifdef WITH_CACHE_FILES + if (withCache) + cachedState->compound["hasHistoryChild"] = Data(((State*)_states[i]->element->getUserData(X("hasHistoryChild")))->documentOrder); +#endif } - // establish the states' ancestors + // parent relation DOMNode* parent = _states[i]->element->getParentNode(); if (parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) { State* uscxmlState = (State*)parent->getUserData(X("uscxmlState")); @@ -406,6 +477,7 @@ COMPLETION_STABLISHED: } } + // establish the states' ancestors while(parent && parent->getNodeType() == DOMNode::ELEMENT_NODE) { State* uscxmlState = (State*)parent->getUserData(X("uscxmlState")); @@ -436,12 +508,12 @@ COMPLETION_STABLISHED: tmp = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "transition", tmp); _transitions.resize(tmp.size()); + _exitSets.resize(tmp.size()); for (i = 0; i < _transitions.size(); i++) { - _transitions[i] = new Transition(); + _transitions[i] = new Transition(i); _transitions[i]->element = tmp.front(); _transitions[i]->conflicts.resize(_transitions.size()); - _transitions[i]->exitSet.resize(_states.size()); _transitions[i]->target.resize(_states.size()); tmp.pop_front(); } @@ -467,69 +539,6 @@ COMPLETION_STABLISHED: } #endif - // establish the transitions' exit set - assert(_transitions[i]->element != NULL); - -#ifdef WITH_CACHE_FILES - if (withCache && cachedTrans->compound.find("exitset") != cachedTrans->compound.end()) { - boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet = fromBase64(cachedTrans->compound["exitset"]); - if (exitSet.size() != _states.size()) { - LOG(_callbacks->getLogger(), USCXML_WARN) << "Transition exit set has wrong size: Cache corrupted" << std::endl; - } else { - _transitions[i]->exitSet = exitSet; - goto EXIT_SET_ESTABLISHED; - } - } -#endif - { - std::list<DOMElement*> exitList = getExitSetCached(_transitions[i]->element, _scxml); - - for (j = 0; j < _states.size(); j++) { - if (!exitList.empty() && _states[j]->element == exitList.front()) { - _transitions[i]->exitSet[j] = true; - exitList.pop_front(); - } else { - _transitions[i]->exitSet[j] = false; - } - } - assert(exitList.size() == 0); - } -#ifdef WITH_CACHE_FILES - if (withCache) - cachedTrans->compound["exitset"] = Data(toBase64(_transitions[i]->exitSet)); -EXIT_SET_ESTABLISHED: -#endif - - // establish the transitions' conflict set -#ifdef WITH_CACHE_FILES - if (withCache && cachedTrans->compound.find("conflicts") != cachedTrans->compound.end()) { - boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts = fromBase64(cachedTrans->compound["conflicts"]); - if (conflicts.size() != _transitions.size()) { - LOG(_callbacks->getLogger(), USCXML_WARN) << "Transition conflicts has wrong size: Cache corrupted" << std::endl; - } else { - _transitions[i]->conflicts = conflicts; - goto CONFLICTS_ESTABLISHED; - } - } -#endif - for (j = i; j < _transitions.size(); j++) { - if (conflictsCached(_transitions[i]->element, _transitions[j]->element, _scxml)) { - _transitions[i]->conflicts[j] = true; - } else { - _transitions[i]->conflicts[j] = false; - } - // std::cout << "."; - } - - // conflicts matrix is symmetric - for (j = 0; j < i; j++) { - _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i]; - } -#ifdef WITH_CACHE_FILES - if (withCache) - cachedTrans->compound["conflicts"] = Data(toBase64(_transitions[i]->conflicts)); -CONFLICTS_ESTABLISHED: -#endif // establish the transitions' target set #ifdef WITH_CACHE_FILES if (withCache && cachedTrans->compound.find("target") != cachedTrans->compound.end()) { @@ -591,8 +600,80 @@ TARGET_SET_ESTABLISHED: if (_transitions[i]->element->getChildElementCount() > 0) { _transitions[i]->onTrans = _transitions[i]->element; } + + // establish the transitions' exit set + assert(_transitions[i]->element != NULL); + + { + _exitSets[i] = getExitSet(_transitions[i]); + } + + } + + /** + * This bound by cache locality! + * Before you change anything, do benchmark! + */ + +#define anc1 _states[_transitions[i]->source]->ancestors +#define exit1 _exitSets[i] +#define exit2 _exitSets[j] + + for (i = 0; i < _transitions.size(); i++) { + anc1 = _states[_transitions[i]->source]->ancestors; + const uint32_t source1 = _transitions[i]->source; + + for (j = i + 1; j < _transitions.size(); j++) { + + if (exit1.first == 0 && exit2.first == 0) { + goto COMPATIBLE_TRANS; + } + + if (exit1.first <= exit2.first && exit1.second >= exit2.first) { + goto CONFLICTING_TRANS; + } + + if (exit2.first <= exit1.first && exit2.second >= exit1.first) { + goto CONFLICTING_TRANS; + } + +COMPATIBLE_TRANS: + if (_transitions[j]->source == source1) { + goto CONFLICTING_TRANS; + } + + if (anc1[_transitions[j]->source]) { + goto CONFLICTING_TRANS; + } + + if (_states[_transitions[j]->source]->ancestors[source1]) { + goto CONFLICTING_TRANS; + } + + _transitions[i]->conflicts[j] = false; +// _transitions[j]->conflicts[i] = false; + continue; +CONFLICTING_TRANS: + _transitions[i]->conflicts[j] = true; +// _transitions[j]->conflicts[i] = true; + + continue; + + } +#if 0 // moved down for cache locality + // conflicts matrix is symmetric + for (j = 0; j < i; j++) { + _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i]; + } +#endif + } + + for (i = 0; i < _transitions.size(); i++) { + // conflicts matrix is symmetric + for (j = 0; j < i; j++) { + _transitions[i]->conflicts[j] = _transitions[j]->conflicts[i]; + } } - _cache.exitSet.clear(); // initialize bitarrays for step() _exitSet = boost::dynamic_bitset<BITSET_BLOCKTYPE>(_states.size(), false); @@ -809,7 +890,11 @@ SELECT_TRANSITIONS: _targetSet |= USCXML_GET_TRANS(i).target; /* states that will be left */ - _exitSet |= USCXML_GET_TRANS(i).exitSet; + for (auto documentOrder = _exitSets[i].first; + documentOrder <= _exitSets[i].second; + documentOrder++) { + _exitSet[documentOrder] = true; + } BIT_SET_AT(i, _transSet); } diff --git a/src/uscxml/interpreter/FastMicroStep.h b/src/uscxml/interpreter/FastMicroStep.h index 5ff1117..543d6a9 100644 --- a/src/uscxml/interpreter/FastMicroStep.h +++ b/src/uscxml/interpreter/FastMicroStep.h @@ -72,48 +72,43 @@ protected: class Transition { public: - Transition() : element(NULL), source(0), onTrans(NULL), type(0) {} + Transition(uint32_t postFixOrder) : postFixOrder(postFixOrder) {} + const uint32_t postFixOrder; // making these const increases performance somewhat - XERCESC_NS::DOMElement* element; + XERCESC_NS::DOMElement* element = NULL; boost::dynamic_bitset<BITSET_BLOCKTYPE> conflicts; - boost::dynamic_bitset<BITSET_BLOCKTYPE> exitSet; - uint32_t source; + uint32_t source = 0; boost::dynamic_bitset<BITSET_BLOCKTYPE> target; - XERCESC_NS::DOMElement* onTrans; + XERCESC_NS::DOMElement* onTrans = NULL; std::string event; std::string cond; - unsigned char type; + unsigned char type = 0; }; class State { public: - State() : element(NULL), parent(0), documentOrder(0), doneData(NULL), type(0) {} + State(uint32_t documentOrder) : documentOrder(documentOrder) {} + const uint32_t documentOrder; - XERCESC_NS::DOMElement* element; + XERCESC_NS::DOMElement* element = NULL; boost::dynamic_bitset<BITSET_BLOCKTYPE> completion; boost::dynamic_bitset<BITSET_BLOCKTYPE> children; boost::dynamic_bitset<BITSET_BLOCKTYPE> ancestors; - uint32_t parent; - uint32_t documentOrder; + uint32_t parent = 0; std::list<XERCESC_NS::DOMElement*> data; std::list<XERCESC_NS::DOMElement*> invoke; std::list<XERCESC_NS::DOMElement*> onEntry; std::list<XERCESC_NS::DOMElement*> onExit; - XERCESC_NS::DOMElement* doneData; + XERCESC_NS::DOMElement* doneData = NULL; std::string name; - unsigned char type; - }; - - class CachedPredicates { - public: - std::map<const XERCESC_NS::DOMElement*, std::list<XERCESC_NS::DOMElement*> > exitSet; + unsigned char type = 0; }; virtual void init(XERCESC_NS::DOMElement* scxml); @@ -147,21 +142,17 @@ private: std::list<XERCESC_NS::DOMElement*> getHistoryCompletion(const XERCESC_NS::DOMElement* state); void resortStates(XERCESC_NS::DOMElement* node, const X& xmlPrefix); - bool conflictsCached(const XERCESC_NS::DOMElement* t1, const XERCESC_NS::DOMElement* t2, const XERCESC_NS::DOMElement* root); ///< overrides implementation Predicates::conflicts for speed - std::string toBase64(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset); boost::dynamic_bitset<BITSET_BLOCKTYPE> fromBase64(const std::string& encoded); - std::list<XERCESC_NS::DOMElement*> getExitSetCached(const XERCESC_NS::DOMElement* transition, - const XERCESC_NS::DOMElement* root); - - 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; + // per transition exit set, kept in a vector for cache locality (~25% faster than transition[i]->exitSet) + std::vector<std::pair<uint32_t, uint32_t> > _exitSets; + boost::dynamic_bitset<BITSET_BLOCKTYPE> _conflicts; boost::dynamic_bitset<BITSET_BLOCKTYPE> _transSet; @@ -169,6 +160,10 @@ private: void printStateNames(const boost::dynamic_bitset<BITSET_BLOCKTYPE>& bitset); #endif + uint32_t getTransitionDomain(const Transition* transition); + std::pair<uint32_t, uint32_t> getExitSet(const Transition* transition); + std::map<uint32_t, std::pair<uint32_t, uint32_t> > _exitSetCache; + friend class Factory; }; diff --git a/src/uscxml/interpreter/InterpreterImpl.cpp b/src/uscxml/interpreter/InterpreterImpl.cpp index 9e59cea..414dba2 100644 --- a/src/uscxml/interpreter/InterpreterImpl.cpp +++ b/src/uscxml/interpreter/InterpreterImpl.cpp @@ -340,6 +340,7 @@ void InterpreterImpl::init() { std::ifstream dataFS(sharedTemp + PATH_SEPERATOR + md5(_baseURL) + ".uscxml.cache"); try { if (dataFS.is_open()) { + LOGD(USCXML_INFO) << "Using cache from '" << sharedTemp << PATH_SEPERATOR << md5(_baseURL) << ".uscxml.cache'" << std::endl; std::string cacheStr((std::istreambuf_iterator<char>(dataFS)), std::istreambuf_iterator<char>()); _cache = Data::fromJSON(cacheStr); @@ -349,9 +350,11 @@ void InterpreterImpl::init() { } // get md5 of current document - std::stringstream ss; - ss << *_document; - _md5 = md5(ss.str()); + if (_md5.length() == 0) { + std::stringstream ss; + ss << *_document; + _md5 = md5(ss.str()); + } if (_cache.compound.find("InterpreterImpl") != _cache.compound.end() && _cache.compound["InterpreterImpl"].compound.find("md5") != _cache.compound["InterpreterImpl"].compound.end() && @@ -390,7 +393,7 @@ void InterpreterImpl::init() { } if (!_microStepper) { - _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new FastMicroStep(this))); + _microStepper = MicroStep(std::shared_ptr<MicroStepImpl>(new LargeMicroStep(this))); } _microStepper.init(_scxml); diff --git a/src/uscxml/interpreter/LargeMicroStep.cpp b/src/uscxml/interpreter/LargeMicroStep.cpp index eab303c..a6d90f4 100644 --- a/src/uscxml/interpreter/LargeMicroStep.cpp +++ b/src/uscxml/interpreter/LargeMicroStep.cpp @@ -111,6 +111,71 @@ void LargeMicroStep::markAsCancelled() { _isCancelled = true; } +void LargeMicroStep::deserialize(const Data& encodedState) { + if (!encodedState.hasKey("configuration") || + !encodedState.hasKey("invocations") || + !encodedState.hasKey("histories") || + !encodedState.hasKey("intializedData")) { + ERROR_PLATFORM_THROW("Data does not contain required fields for deserialization "); + } + + reset(); + + for (auto stateId : encodedState["configuration"].array) { + _configuration.insert(_states[strTo<uint32_t>(stateId.atom)]); + _configurationPostFix.insert(_states[strTo<uint32_t>(stateId.atom)]); + } + + for (auto stateId : encodedState["invocations"].array) { + _invocations.insert(_states[strTo<uint32_t>(stateId.atom)]); + } + + for (auto stateId : encodedState["histories"].array) { + _history.insert(_states[strTo<uint32_t>(stateId.atom)]); + } + + for (auto stateId : encodedState["intializedData"].array) { + _initializedData.insert(_states[strTo<uint32_t>(stateId.atom)]); + } + + for (auto invoked : _invocations) { + for (auto invoker : invoked->invoke) { + try { + _callbacks->invoke(invoker); + } catch (ErrorEvent e) { + LOG(_callbacks->getLogger(), USCXML_WARN) << e; + } catch (...) { + } + } + } + + _flags |= USCXML_CTX_INITIALIZED; +} + +Data LargeMicroStep::serialize() { + Data encodedState; + + encodedState["configuration"] = Data(); + encodedState["invocations"] = Data(); + encodedState["histories"] = Data(); + encodedState["intializedData"] = Data(); + + for (auto state : _configuration) { + encodedState["configuration"].array.push_back(Data(state->documentOrder)); + } + for (auto state : _invocations) { + encodedState["invocations"].array.push_back(Data(state->documentOrder)); + } + for (auto state : _history) { + encodedState["histories"].array.push_back(Data(state->documentOrder)); + } + for (auto state : _initializedData) { + encodedState["intializedData"].array.push_back(Data(state->documentOrder)); + } + + return encodedState; +} + void LargeMicroStep::reset() { _isCancelled = false; _flags = USCXML_CTX_PRISTINE; @@ -453,6 +518,11 @@ void LargeMicroStep::init(XERCESC_NS::DOMElement* scxml) { assert(transList.size() == 0); } +// for (i = 0; i < _transitions.size(); i++) { +// _transitions[i]->exitSet = getExitSet(_transitions[i]); +// LOGD(USCXML_DEBUG) << "" << _transitions[i]->exitSet.second << " / " << _transitions[i]->exitSet.first << std::endl; +// } + _isInitialized = true; } diff --git a/src/uscxml/interpreter/LargeMicroStep.h b/src/uscxml/interpreter/LargeMicroStep.h index 35e21de..72c2292 100644 --- a/src/uscxml/interpreter/LargeMicroStep.h +++ b/src/uscxml/interpreter/LargeMicroStep.h @@ -68,10 +68,8 @@ public: virtual std::list<XERCESC_NS::DOMElement*> getConfiguration(); void markAsCancelled(); - virtual void deserialize(const Data& encodedState) {} - virtual Data serialize() { - return Data(); - } + virtual void deserialize(const Data& encodedState); + virtual Data serialize(); protected: LargeMicroStep() {} // only for the factory @@ -135,7 +133,7 @@ protected: XERCESC_NS::DOMElement* element; boost::container::flat_set<State*, StateOrder> completion; - boost::container::flat_set<State*, StateOrder> ancestors; // TODO: leverage! + boost::container::flat_set<State*, StateOrder> ancestors; // TODO: change to indices std::vector<State*> children; State* parent = NULL; diff --git a/src/uscxml/util/Convenience.cpp b/src/uscxml/util/Convenience.cpp index 4f47449..4cfbb5e 100644 --- a/src/uscxml/util/Convenience.cpp +++ b/src/uscxml/util/Convenience.cpp @@ -61,6 +61,10 @@ bool isInteger(const char* pszInput, int nNumberBase) { bool iequals(const std::string& a, const std::string& b) { // this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml - we don't care for non-ascii yet +#if 0 + // not platform independent? + return strcasecmp(a.c_str(), b.c_str()) == 0; +#else unsigned int size = a.size(); if (b.size() != size) return false; @@ -68,6 +72,7 @@ bool iequals(const std::string& a, const std::string& b) { if (tolower(a[i]) != tolower(b[i])) return false; return true; +#endif } bool equals(const std::string& a, const std::string& b) { diff --git a/src/uscxml/util/DOM.h b/src/uscxml/util/DOM.h index 2adc675..1e0b8ce 100644 --- a/src/uscxml/util/DOM.h +++ b/src/uscxml/util/DOM.h @@ -201,6 +201,10 @@ public : return _localForm; } + int iequals(const XMLCh* const other) const { + return XERCESC_NS::XMLString::compareIString(_unicodeForm, other); + } + operator XMLCh* () const { assert(_unicodeForm != NULL); // constructor with XMLCh return _unicodeForm; @@ -217,7 +221,7 @@ public : } bool operator==(const X& other) const { - return (_unicodeForm == other._unicodeForm) != 0; + return (_localForm == other._localForm) != 0; } bool operator!=(const X& other) const { diff --git a/src/uscxml/util/Predicates.cpp b/src/uscxml/util/Predicates.cpp index 3f6128f..6649907 100644 --- a/src/uscxml/util/Predicates.cpp +++ b/src/uscxml/util/Predicates.cpp @@ -183,21 +183,23 @@ bool isState(const DOMElement* state, bool properOnly) { if (!state) return false; - std::string localName = LOCALNAME(state); - if (iequals("state", localName)) + // comparison with XMLCh* is faster than transcoding each + const XMLCh* localname = state->getLocalName(); + + if (kXMLCharState.iequals(localname) == 0) return true; - if (iequals("scxml", localName)) + if (kXMLCharScxml.iequals(localname) == 0) return true; - if (iequals("parallel", localName)) + if (kXMLCharParallel.iequals(localname) == 0) return true; - if (iequals("final", localName)) + if (kXMLCharFinal.iequals(localname) == 0) return true; if (properOnly) return false; - if (iequals("history", localName)) + if (kXMLCharHistory.iequals(localname) == 0) return true; - if (iequals("initial", localName)) + if (kXMLCharInitial.iequals(localname) == 0) return true; return false; diff --git a/test/src/test-lifecycle.cpp b/test/src/test-lifecycle.cpp index e948e3c..6b30c96 100644 --- a/test/src/test-lifecycle.cpp +++ b/test/src/test-lifecycle.cpp @@ -48,67 +48,67 @@ std::list<CallbackType> callBackSeq; class SequenceCheckingMonitor : public InterpreterMonitor { - virtual void beforeProcessingEvent(Interpreter& interpreter, const Event& event) { + virtual void beforeProcessingEvent(const std::string& sessionId, const Event& event) { CHECK_CALLBACK_TYPE(USCXML_BEFOREPROCESSINGEVENT); } - virtual void beforeMicroStep(Interpreter& interpreter) { + virtual void beforeMicroStep(const std::string& sessionId) { CHECK_CALLBACK_TYPE(USCXML_BEFOREMICROSTEP); } - virtual void beforeExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { + virtual void beforeExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) { CHECK_CALLBACK_TYPE(USCXML_BEFOREEXITINGSTATE); } - virtual void afterExitingState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { + virtual void afterExitingState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) { CHECK_CALLBACK_TYPE(USCXML_AFTEREXITINGSTATE); } - virtual void beforeExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element) { + virtual void beforeExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) { CHECK_CALLBACK_TYPE(USCXML_BEFOREEXECUTINGCONTENT); } - virtual void afterExecutingContent(Interpreter& interpreter, const XERCESC_NS::DOMElement* element) { + virtual void afterExecutingContent(const std::string& sessionId, const XERCESC_NS::DOMElement* element) { CHECK_CALLBACK_TYPE(USCXML_AFTEREXECUTINGCONTENT); } - virtual void beforeUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { + virtual void beforeUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { CHECK_CALLBACK_TYPE(USCXML_BEFOREUNINVOKING); } - virtual void afterUninvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { + virtual void afterUninvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { CHECK_CALLBACK_TYPE(USCXML_AFTERUNINVOKING); } - virtual void beforeTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { + virtual void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) { CHECK_CALLBACK_TYPE(USCXML_BEFORETAKINGTRANSITION); } - virtual void afterTakingTransition(Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { + virtual void afterTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) { CHECK_CALLBACK_TYPE(USCXML_AFTERTAKINGTRANSITION); } - virtual void beforeEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { + virtual void beforeEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) { CHECK_CALLBACK_TYPE(USCXML_BEFOREENTERINGSTATE); } - virtual void afterEnteringState(Interpreter& interpreter, const XERCESC_NS::DOMElement* state) { + virtual void afterEnteringState(const std::string& sessionId, const std::string& stateName, const XERCESC_NS::DOMElement* state) { CHECK_CALLBACK_TYPE(USCXML_AFTERENTERINGSTATE); } - virtual void beforeInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { + virtual void beforeInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { CHECK_CALLBACK_TYPE(USCXML_BEFOREINVOKING); } - virtual void afterInvoking(Interpreter& interpreter, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { + virtual void afterInvoking(const std::string& sessionId, const XERCESC_NS::DOMElement* invokeElem, const std::string& invokeid) { CHECK_CALLBACK_TYPE(USCXML_AFTERINVOKING); } - virtual void afterMicroStep(Interpreter& interpreter) { + virtual void afterMicroStep(const std::string& sessionId) { CHECK_CALLBACK_TYPE(USCXML_AFTERMICROSTEP); } - virtual void onStableConfiguration(Interpreter& interpreter) { + virtual void onStableConfiguration(const std::string& sessionId) { CHECK_CALLBACK_TYPE(USCXML_ONSTABLECONFIGURATION); } - virtual void beforeCompletion(Interpreter& interpreter) { + virtual void beforeCompletion(const std::string& sessionId) { CHECK_CALLBACK_TYPE(USCXML_BEFORECOMPLETION); } - virtual void afterCompletion(Interpreter& interpreter) { + virtual void afterCompletion(const std::string& sessionId) { CHECK_CALLBACK_TYPE(USCXML_AFTERCOMPLETION); } diff --git a/test/src/test-serialization.cpp b/test/src/test-serialization.cpp index 968bae3..da8df89 100644 --- a/test/src/test-serialization.cpp +++ b/test/src/test-serialization.cpp @@ -21,7 +21,7 @@ int lastTransitionAt; //class StatusMonitor : public uscxml::InterpreterMonitor { class StatusMonitor : public uscxml::StateTransitionMonitor { - void beforeTakingTransition(uscxml::Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { + void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) { lastTransitionAt = time(NULL); } @@ -65,6 +65,7 @@ int main(int argc, char** argv) { } DirectoryWatch* watcher = new DirectoryWatch(argv[optind], true); + watcher->setLogger(Logger::getDefault()); watcher->updateEntries(true); std::map<std::string, struct stat> entries = watcher->getAllEntries(); @@ -92,7 +93,7 @@ int main(int argc, char** argv) { lastTransitionAt = time(NULL); std::string sourceXML = std::string(argv[optind]) + PATH_SEPERATOR + entryIter->first; - sourceXML = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test557.scxml"; +// sourceXML = "/Users/sradomski/Documents/TK/Code/uscxml/test/w3c/ecma/test557.scxml"; Interpreter interpreter = Interpreter::fromURL(sourceXML); LOGD(USCXML_INFO) << "Processing " << interpreter.getImpl()->getBaseURL() << std::endl; diff --git a/test/src/test-stress.cpp b/test/src/test-stress.cpp index 4d395ab..e034e87 100644 --- a/test/src/test-stress.cpp +++ b/test/src/test-stress.cpp @@ -19,7 +19,7 @@ int startedAt; int lastTransitionAt; class StatusMonitor : public uscxml::InterpreterMonitor { - void beforeTakingTransition(uscxml::Interpreter& interpreter, const XERCESC_NS::DOMElement* transition) { + void beforeTakingTransition(const std::string& sessionId, const XERCESC_NS::DOMElement* transition) { lastTransitionAt = time(NULL); } diff --git a/test/src/test-validating.cpp b/test/src/test-validating.cpp index ae2a2f5..a0fd6dd 100644 --- a/test/src/test-validating.cpp +++ b/test/src/test-validating.cpp @@ -35,7 +35,7 @@ public: IssueMonitor() { runtimeIssues = 0; } - void reportIssue(Interpreter& intrpreter, const InterpreterIssue& issue) { + void reportIssue(const std::string& sessionId, const InterpreterIssue& issue) { runtimeIssues++; } }; |