Fix some isEmptyBranch and getNodeID performance issues.

This commit is contained in:
JoelKatz
2013-03-05 22:16:07 -08:00
parent eccb6eb936
commit 22111adbaa
3 changed files with 30 additions and 23 deletions

View File

@@ -23,9 +23,11 @@ DECLARE_INSTANCE(SHAMapTreeNode);
void SHAMapNode::setHash() const void SHAMapNode::setHash() const
{ {
#if 0
std::size_t h = theApp->getNonceST() + (mDepth * 0x9e3779b9); std::size_t h = theApp->getNonceST() + (mDepth * 0x9e3779b9);
mHash = mNodeID.hash_combine(h); mHash = mNodeID.hash_combine(h);
#if 0 #else
std::size_t h = theApp->getNonceST() + (mDepth * 0x9e3779b9);
const unsigned int *ptr = reinterpret_cast<const unsigned int *>(mNodeID.begin()); const unsigned int *ptr = reinterpret_cast<const unsigned int *>(mNodeID.begin());
for (int i = (mDepth + 3) / 4; i != 0; --i) for (int i = (mDepth + 3) / 4; i != 0; --i)
boost::hash_combine(h, *ptr++); boost::hash_combine(h, *ptr++);

View File

@@ -4,7 +4,6 @@
#include <list> #include <list>
#include <map> #include <map>
#include <stack> #include <stack>
#include <bitset>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/enable_shared_from_this.hpp>
@@ -166,10 +165,10 @@ public:
private: private:
uint256 mHash; uint256 mHash;
uint256 mHashes[16]; uint256 mHashes[16];
std::bitset<16> mIsBranch;
SHAMapItem::pointer mItem; SHAMapItem::pointer mItem;
uint32 mSeq, mAccessSeq; uint32 mSeq, mAccessSeq;
TNType mType; TNType mType;
int mIsBranch;
bool mFullBelow; bool mFullBelow;
bool updateHash(); bool updateHash();
@@ -208,7 +207,7 @@ public:
// inner node functions // inner node functions
bool isInnerNode() const { return !mItem; } bool isInnerNode() const { return !mItem; }
bool setChildHash(int m, const uint256& hash); bool setChildHash(int m, const uint256& hash);
bool isEmptyBranch(int m) const { return !mIsBranch.test(m); } bool isEmptyBranch(int m) const { return (mIsBranch & (1 << m)) == 0; }
bool isEmpty() const; bool isEmpty() const;
int getBranchCount() const; int getBranchCount() const;
void makeInner(); void makeInner();

View File

@@ -102,10 +102,9 @@ uint256 SHAMapNode::getNodeID(int depth, const uint256& hash)
return hash & smMasks[depth]; return hash & smMasks[depth];
} }
SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth), mHash(0) SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth), mHash(0), mNodeID(getNodeID(depth, hash))
{ // canonicalize the hash to a node ID for this depth { // canonicalize the hash to a node ID for this depth
assert((depth >= 0) && (depth < 65)); assert((depth >= 0) && (depth < 65));
mNodeID = getNodeID(depth, hash);
} }
SHAMapNode::SHAMapNode(const void *ptr, int len) : mHash(0) SHAMapNode::SHAMapNode(const void *ptr, int len) : mHash(0)
@@ -177,12 +176,12 @@ void SHAMapNode::dump() const
} }
SHAMapTreeNode::SHAMapTreeNode(uint32 seq, const SHAMapNode& nodeID) : SHAMapNode(nodeID), mHash(0), SHAMapTreeNode::SHAMapTreeNode(uint32 seq, const SHAMapNode& nodeID) : SHAMapNode(nodeID), mHash(0),
mSeq(seq), mAccessSeq(seq), mType(tnERROR), mFullBelow(false) mSeq(seq), mAccessSeq(seq), mIsBranch(0), mType(tnERROR), mFullBelow(false)
{ {
} }
SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapNode(node), SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapNode(node),
mHash(node.mHash), mSeq(seq), mType(node.mType), mFullBelow(false) mHash(node.mHash), mSeq(seq), mIsBranch(0), mType(node.mType), mFullBelow(false)
{ {
if (node.mItem) if (node.mItem)
mItem = boost::make_shared<SHAMapItem>(*node.mItem); mItem = boost::make_shared<SHAMapItem>(*node.mItem);
@@ -191,18 +190,19 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
if (mHashes[i].isNonZero()) if (mHashes[i].isNonZero())
mIsBranch.set(i); mIsBranch |= (1 << i);
} }
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::ref item, TNType type, uint32 seq) : SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::ref item, TNType type, uint32 seq) :
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true) SHAMapNode(node), mItem(item), mSeq(seq), mIsBranch(0), mType(type), mFullBelow(true)
{ {
assert(item->peekData().size() >= 12); assert(item->peekData().size() >= 12);
updateHash(); updateHash();
} }
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned char>& rawNode, uint32 seq, SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned char>& rawNode, uint32 seq,
SHANodeFormat format, const uint256& hash) : SHAMapNode(id), mSeq(seq), mType(tnERROR), mFullBelow(false) SHANodeFormat format, const uint256& hash) :
SHAMapNode(id), mSeq(seq), mIsBranch(0), mType(tnERROR), mFullBelow(false)
{ {
if (format == snfWIRE) if (format == snfWIRE)
{ {
@@ -243,7 +243,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
{ {
s.get256(mHashes[i], i * 32); s.get256(mHashes[i], i * 32);
if (mHashes[i].isNonZero()) if (mHashes[i].isNonZero())
mIsBranch.set(i); mIsBranch |= (1 << i);
} }
mType = tnINNER; mType = tnINNER;
} }
@@ -255,10 +255,9 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
s.get8(pos, 32 + (i * 33)); s.get8(pos, 32 + (i * 33));
if ((pos < 0) || (pos >= 16)) throw std::runtime_error("invalid CI node"); if ((pos < 0) || (pos >= 16)) throw std::runtime_error("invalid CI node");
s.get256(mHashes[pos], i * 33); s.get256(mHashes[pos], i * 33);
if (mHashes[pos].isNonZero())
mIsBranch |= (1 << pos);
} }
for (int i = 0; i < 16; ++i)
if (mHashes[i].isNonZero())
mIsBranch.set(i);
mType = tnINNER; mType = tnINNER;
} }
else if (type == 4) else if (type == 4)
@@ -315,7 +314,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
{ {
s.get256(mHashes[i] , i * 32); s.get256(mHashes[i] , i * 32);
if (mHashes[i].isNonZero()) if (mHashes[i].isNonZero())
mIsBranch.set(i); mIsBranch |= (1 << i);
} }
mType = tnINNER; mType = tnINNER;
} }
@@ -360,7 +359,7 @@ bool SHAMapTreeNode::updateHash()
if (mType == tnINNER) if (mType == tnINNER)
{ {
if(mIsBranch.any()) if (mIsBranch != 0)
{ {
nh = Serializer::getPrefixHash(sHP_InnerNode, reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes)); nh = Serializer::getPrefixHash(sHP_InnerNode, reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
#ifdef PARANOID #ifdef PARANOID
@@ -422,10 +421,10 @@ void SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format)
} }
else else
{ {
if (mIsBranch.count() < 12) if (getBranchCount() < 12)
{ // compressed node { // compressed node
for (int i = 0; i < 16; ++i) for (int i = 0; i < 16; ++i)
if (mIsBranch.test(i)) if (!isEmptyBranch(i))
{ {
s.add256(mHashes[i]); s.add256(mHashes[i]);
s.add8(i); s.add8(i);
@@ -505,19 +504,23 @@ SHAMapItem::pointer SHAMapTreeNode::getItem() const
bool SHAMapTreeNode::isEmpty() const bool SHAMapTreeNode::isEmpty() const
{ {
return mIsBranch.none(); return mIsBranch == 0;
} }
int SHAMapTreeNode::getBranchCount() const int SHAMapTreeNode::getBranchCount() const
{ {
assert(isInner()); assert(isInner());
return mIsBranch.count(); int count = 0;
for (int i = 0; i < 16; ++i)
if (!isEmptyBranch(i))
++count;
return count;
} }
void SHAMapTreeNode::makeInner() void SHAMapTreeNode::makeInner()
{ {
mItem.reset(); mItem.reset();
mIsBranch.reset(); mIsBranch = 0;
memset(mHashes, 0, sizeof(mHashes)); memset(mHashes, 0, sizeof(mHashes));
mType = tnINNER; mType = tnINNER;
mHash.zero(); mHash.zero();
@@ -574,7 +577,10 @@ bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
if(mHashes[m] == hash) if(mHashes[m] == hash)
return false; return false;
mHashes[m] = hash; mHashes[m] = hash;
mIsBranch.set(m, hash.isNonZero()); if (hash.isNonZero())
mIsBranch |= (1 << m);
else
mIsBranch &= ~(1 << m);
return updateHash(); return updateHash();
} }