From 4b854d45457a5ac794e6d1f35a1b8e6a67f81d6e Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Mon, 27 Nov 2017 15:36:44 +0100 Subject: [PATCH] logic: improved performance of NodeTypeSet by internally using a bit-mask --- src/lib/CMakeLists.txt | 2 + src/lib/data/NodeType.h | 40 ++++++------ src/lib/data/NodeTypeSet.cpp | 107 +++++++++++++++++--------------- src/lib/data/NodeTypeSet.h | 10 ++- src/lib/utility/utilityMath.cpp | 13 ++++ src/lib/utility/utilityMath.h | 9 +++ 6 files changed, 108 insertions(+), 73 deletions(-) create mode 100644 src/lib/utility/utilityMath.cpp create mode 100644 src/lib/utility/utilityMath.h diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index da52c0fe..600df223 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -530,6 +530,8 @@ add_files( utility/utilityFile.cpp utility/utilityFile.h utility/utilityLibrary.h + utility/utilityMath.cpp + utility/utilityMath.h utility/utilityString.cpp utility/utilityString.h utility/utilityUuid.cpp diff --git a/src/lib/data/NodeType.h b/src/lib/data/NodeType.h index 179e3b2d..f4bd352f 100644 --- a/src/lib/data/NodeType.h +++ b/src/lib/data/NodeType.h @@ -15,29 +15,29 @@ public: typedef int TypeMask; enum Type : NodeType::TypeMask { // make sure that the value of 0x0 is not used here because it doesn't work for bitmasking. - NODE_SYMBOL = 0x1, - NODE_TYPE = 0x2, - NODE_BUILTIN_TYPE = 0x4, + NODE_SYMBOL = 1 << 0, + NODE_TYPE = 1 << 1, + NODE_BUILTIN_TYPE = 1 << 2, - NODE_NAMESPACE = 0x8, - NODE_PACKAGE = 0x10, - NODE_STRUCT = 0x20, - NODE_CLASS = 0x40, - NODE_INTERFACE = 0x80, - NODE_GLOBAL_VARIABLE = 0x100, - NODE_FIELD = 0x200, - NODE_FUNCTION = 0x400, - NODE_METHOD = 0x800, + NODE_NAMESPACE = 1 << 3, + NODE_PACKAGE = 1 << 4, + NODE_STRUCT = 1 << 5, + NODE_CLASS = 1 << 6, + NODE_INTERFACE = 1 << 7, + NODE_GLOBAL_VARIABLE = 1 << 8, + NODE_FIELD = 1 << 9, + NODE_FUNCTION = 1 << 10, + NODE_METHOD = 1 << 11, - NODE_ENUM = 0x1000, - NODE_ENUM_CONSTANT = 0x2000, - NODE_TYPEDEF = 0x4000, - NODE_TEMPLATE_PARAMETER_TYPE = 0x8000, - NODE_TYPE_PARAMETER = 0x10000, + NODE_ENUM = 1 << 12, + NODE_ENUM_CONSTANT = 1 << 13, + NODE_TYPEDEF = 1 << 14, + NODE_TEMPLATE_PARAMETER_TYPE = 1 << 15, + NODE_TYPE_PARAMETER = 1 << 16, - NODE_FILE = 0x20000, - NODE_MACRO = 0x40000, - NODE_UNION = 0x80000, + NODE_FILE = 1 << 17, + NODE_MACRO = 1 << 18, + NODE_UNION = 1 << 19, NODE_MAX_VALUE = NODE_UNION }; diff --git a/src/lib/data/NodeTypeSet.cpp b/src/lib/data/NodeTypeSet.cpp index 2429517e..e1ee2a07 100644 --- a/src/lib/data/NodeTypeSet.cpp +++ b/src/lib/data/NodeTypeSet.cpp @@ -1,32 +1,12 @@ #include "data/NodeTypeSet.h" #include "utility/utility.h" +#include "utility/utilityMath.h" NodeTypeSet NodeTypeSet::all() { NodeTypeSet ret; - - ret.add(NodeType(NodeType::NODE_SYMBOL)); - ret.add(NodeType(NodeType::NODE_TYPE)); - ret.add(NodeType(NodeType::NODE_BUILTIN_TYPE)); - ret.add(NodeType(NodeType::NODE_NAMESPACE)); - ret.add(NodeType(NodeType::NODE_PACKAGE)); - ret.add(NodeType(NodeType::NODE_STRUCT)); - ret.add(NodeType(NodeType::NODE_CLASS)); - ret.add(NodeType(NodeType::NODE_INTERFACE)); - ret.add(NodeType(NodeType::NODE_GLOBAL_VARIABLE)); - ret.add(NodeType(NodeType::NODE_FIELD)); - ret.add(NodeType(NodeType::NODE_FUNCTION)); - ret.add(NodeType(NodeType::NODE_METHOD)); - ret.add(NodeType(NodeType::NODE_ENUM)); - ret.add(NodeType(NodeType::NODE_ENUM_CONSTANT)); - ret.add(NodeType(NodeType::NODE_TYPEDEF)); - ret.add(NodeType(NodeType::NODE_TEMPLATE_PARAMETER_TYPE)); - ret.add(NodeType(NodeType::NODE_TYPE_PARAMETER)); - ret.add(NodeType(NodeType::NODE_FILE)); - ret.add(NodeType(NodeType::NODE_MACRO)); - ret.add(NodeType(NodeType::NODE_UNION)); - + ret.m_nodeTypeMask = ~0; return ret; } @@ -37,17 +17,17 @@ NodeTypeSet NodeTypeSet::none() NodeTypeSet::NodeTypeSet() { - std::string i; + m_nodeTypeMask = 0; } NodeTypeSet::NodeTypeSet(const NodeType& type) { - m_nodeTypes.insert(type); + m_nodeTypeMask = nodeTypeToMask(type); } bool NodeTypeSet::operator==(const NodeTypeSet& other) const { - return utility::isPermutation(getNodeTypeIds(), other.getNodeTypeIds()); // TODO: reimplement using mask + return m_nodeTypeMask == other.m_nodeTypeMask; } bool NodeTypeSet::operator!=(const NodeTypeSet& other) const @@ -57,8 +37,7 @@ bool NodeTypeSet::operator!=(const NodeTypeSet& other) const void NodeTypeSet::invert() { - NodeTypeSet inverse = NodeTypeSet::all().getWithRemoved(*this); - m_nodeTypes = std::move(inverse.m_nodeTypes); + m_nodeTypeMask = ~m_nodeTypeMask; } NodeTypeSet NodeTypeSet::getInverse() const @@ -70,24 +49,27 @@ NodeTypeSet NodeTypeSet::getInverse() const void NodeTypeSet::add(const NodeTypeSet& typeSet) { - utility::append(m_nodeTypes, typeSet.m_nodeTypes); + m_nodeTypeMask |= typeSet.m_nodeTypeMask; } -std::set NodeTypeSet::getNodeTypes() const +std::vector NodeTypeSet::getNodeTypes() const { - return m_nodeTypes; + std::vector nodeTypes; + + for (const NodeType& type : s_allNodeTypes) + { + if (m_nodeTypeMask & nodeTypeToMask(type)) + { + nodeTypes.push_back(type); + } + } + + return nodeTypes; } void NodeTypeSet::remove(const NodeTypeSet& typeSet) { - for (const NodeType& type : typeSet.getNodeTypes()) - { - std::set::const_iterator it = m_nodeTypes.find(type); - if (it != m_nodeTypes.end()) - { - m_nodeTypes.erase(it); - } - } + m_nodeTypeMask &= ~typeSet.m_nodeTypeMask; } NodeTypeSet NodeTypeSet::getWithRemoved(const NodeTypeSet& typeSet) const @@ -99,35 +81,58 @@ NodeTypeSet NodeTypeSet::getWithRemoved(const NodeTypeSet& typeSet) const bool NodeTypeSet::isEmpty() const { - return m_nodeTypes.empty(); + return m_nodeTypeMask == 0; } bool NodeTypeSet::contains(const NodeType& type) const { - return m_nodeTypes.find(type) != m_nodeTypes.end(); + return m_nodeTypeMask & nodeTypeToMask(type); } bool NodeTypeSet::intersectsWith(const NodeTypeSet& typeSet) const { - for (const NodeType& type : typeSet.getNodeTypes()) - { - std::set::const_iterator it = m_nodeTypes.find(type); - if (it != m_nodeTypes.end()) - { - return true; - } - } - return false; + return m_nodeTypeMask & typeSet.m_nodeTypeMask; } std::vector NodeTypeSet::getNodeTypeIds() const { std::vector ids; - for (const NodeType type : m_nodeTypes) + for (const NodeType& type: s_allNodeTypes) { - ids.push_back(type.getId()); + if (m_nodeTypeMask & nodeTypeToMask(type)) + { + ids.push_back(type.getId()); + } } return ids; } + +NodeTypeSet::MaskType NodeTypeSet::nodeTypeToMask(const NodeType& nodeType) +{ + // todo: convert to mask if ids are not power of two anymore + return nodeType.getId(); +} + +const std::vector NodeTypeSet::s_allNodeTypes = { + NodeType(NodeType::NODE_SYMBOL), + NodeType(NodeType::NODE_TYPE), + NodeType(NodeType::NODE_BUILTIN_TYPE), + NodeType(NodeType::NODE_NAMESPACE), + NodeType(NodeType::NODE_PACKAGE), + NodeType(NodeType::NODE_STRUCT), + NodeType(NodeType::NODE_CLASS), + NodeType(NodeType::NODE_INTERFACE), + NodeType(NodeType::NODE_FIELD), + NodeType(NodeType::NODE_FUNCTION), + NodeType(NodeType::NODE_METHOD), + NodeType(NodeType::NODE_ENUM), + NodeType(NodeType::NODE_ENUM_CONSTANT), + NodeType(NodeType::NODE_TYPEDEF), + NodeType(NodeType::NODE_TEMPLATE_PARAMETER_TYPE), + NodeType(NodeType::NODE_TYPE_PARAMETER), + NodeType(NodeType::NODE_FILE), + NodeType(NodeType::NODE_MACRO), + NodeType(NodeType::NODE_UNION) +}; diff --git a/src/lib/data/NodeTypeSet.h b/src/lib/data/NodeTypeSet.h index 86c016aa..23fda732 100644 --- a/src/lib/data/NodeTypeSet.h +++ b/src/lib/data/NodeTypeSet.h @@ -23,7 +23,7 @@ public: NodeTypeSet getInverse() const; void add(const NodeTypeSet& typeSet); - std::set getNodeTypes() const; + std::vector getNodeTypes() const; void remove(const NodeTypeSet& typeSet); NodeTypeSet getWithRemoved(const NodeTypeSet& typeSet) const; @@ -34,7 +34,13 @@ public: std::vector getNodeTypeIds() const; private: - std::set m_nodeTypes; + typedef unsigned long int MaskType; + + static MaskType nodeTypeToMask(const NodeType& nodeType); + static const std::vector s_allNodeTypes; + + MaskType m_nodeTypeMask; + //std::set m_nodeTypes; }; #endif // NODE_TYPE_SET_H diff --git a/src/lib/utility/utilityMath.cpp b/src/lib/utility/utilityMath.cpp new file mode 100644 index 00000000..a9e59637 --- /dev/null +++ b/src/lib/utility/utilityMath.cpp @@ -0,0 +1,13 @@ +#include "utility/utilityMath.h" + +unsigned long int utility::getPowerOfTwo(unsigned int exponent) +{ + static const long int powerOfTwos[] = + { + 1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7, + 1 << 8, 1 << 9, 1 << 10, 1 << 11, 1 << 12, 1 << 13, 1 << 14, 1 << 15, + 1 << 16, 1 << 17, 1 << 18, 1 << 19, 1 << 20, 1 << 21, 1 << 22, 1 << 23, + 1 << 24, 1 << 25, 1 << 26, 1 << 27, 1 << 28, 1 << 29, 1 << 30, 1 << 31 + }; + return powerOfTwos[exponent]; +} diff --git a/src/lib/utility/utilityMath.h b/src/lib/utility/utilityMath.h new file mode 100644 index 00000000..1f8ebb4b --- /dev/null +++ b/src/lib/utility/utilityMath.h @@ -0,0 +1,9 @@ +#ifndef UTILITY_MATH_H +#define UTILITY_MATH_H + +namespace utility +{ + unsigned long int getPowerOfTwo(unsigned int exponent); +} + +#endif // UTILITY_MATH_H