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
{
#if 0
std::size_t h = theApp->getNonceST() + (mDepth * 0x9e3779b9);
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());
for (int i = (mDepth + 3) / 4; i != 0; --i)
boost::hash_combine(h, *ptr++);

View File

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

View File

@@ -102,10 +102,9 @@ uint256 SHAMapNode::getNodeID(int depth, const uint256& hash)
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
assert((depth >= 0) && (depth < 65));
mNodeID = getNodeID(depth, hash);
}
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),
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),
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)
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)
if (mHashes[i].isNonZero())
mIsBranch.set(i);
mIsBranch |= (1 << i);
}
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);
updateHash();
}
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)
{
@@ -243,7 +243,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
{
s.get256(mHashes[i], i * 32);
if (mHashes[i].isNonZero())
mIsBranch.set(i);
mIsBranch |= (1 << i);
}
mType = tnINNER;
}
@@ -255,10 +255,9 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
s.get8(pos, 32 + (i * 33));
if ((pos < 0) || (pos >= 16)) throw std::runtime_error("invalid CI node");
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;
}
else if (type == 4)
@@ -315,7 +314,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
{
s.get256(mHashes[i] , i * 32);
if (mHashes[i].isNonZero())
mIsBranch.set(i);
mIsBranch |= (1 << i);
}
mType = tnINNER;
}
@@ -360,7 +359,7 @@ bool SHAMapTreeNode::updateHash()
if (mType == tnINNER)
{
if(mIsBranch.any())
if (mIsBranch != 0)
{
nh = Serializer::getPrefixHash(sHP_InnerNode, reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
#ifdef PARANOID
@@ -422,10 +421,10 @@ void SHAMapTreeNode::addRaw(Serializer& s, SHANodeFormat format)
}
else
{
if (mIsBranch.count() < 12)
if (getBranchCount() < 12)
{ // compressed node
for (int i = 0; i < 16; ++i)
if (mIsBranch.test(i))
if (!isEmptyBranch(i))
{
s.add256(mHashes[i]);
s.add8(i);
@@ -505,19 +504,23 @@ SHAMapItem::pointer SHAMapTreeNode::getItem() const
bool SHAMapTreeNode::isEmpty() const
{
return mIsBranch.none();
return mIsBranch == 0;
}
int SHAMapTreeNode::getBranchCount() const
{
assert(isInner());
return mIsBranch.count();
int count = 0;
for (int i = 0; i < 16; ++i)
if (!isEmptyBranch(i))
++count;
return count;
}
void SHAMapTreeNode::makeInner()
{
mItem.reset();
mIsBranch.reset();
mIsBranch = 0;
memset(mHashes, 0, sizeof(mHashes));
mType = tnINNER;
mHash.zero();
@@ -574,7 +577,10 @@ bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
if(mHashes[m] == hash)
return false;
mHashes[m] = hash;
mIsBranch.set(m, hash.isNonZero());
if (hash.isNonZero())
mIsBranch |= (1 << m);
else
mIsBranch &= ~(1 << m);
return updateHash();
}