Large speed up of getField* functions on non-free objects such as transactions and ledger nodes.

This commit is contained in:
JoelKatz
2013-02-28 23:52:53 -08:00
parent fca5683d31
commit 7a9037d1ca
9 changed files with 83 additions and 66 deletions

View File

@@ -96,6 +96,7 @@ public:
bool isKnown() const { return fieldType != STI_UNKNOWN; }
bool isBinary() const { return fieldValue < 256; }
bool isDiscardable() const { return fieldValue > 256; }
int getCode() const { return fieldCode; }
bool isSigningField() const { return signingField; }
void notSigningField() { signingField = false; }

View File

@@ -11,7 +11,7 @@ std::map<std::string, LedgerEntryFormat*> LedgerEntryFormat::byName;
#define DECLARE_LEF(name, type) lef = new LedgerEntryFormat(#name, type); (*lef) LEF_BASE
static bool LEFInit()
void LEFInit()
{
LedgerEntryFormat* lef;
@@ -111,12 +111,8 @@ static bool LEFInit()
<< SOElement(sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
;
return true;
}
bool LEFInitComplete = LEFInit();
LedgerEntryFormat* LedgerEntryFormat::getLgrFormat(LedgerEntryType t)
{
std::map<int, LedgerEntryFormat*>::iterator it = byType.find(static_cast<int>(t));

View File

@@ -58,7 +58,7 @@ class LedgerEntryFormat
public:
std::string t_name;
LedgerEntryType t_type;
std::vector<SOElement::ref> elements;
SOTemplate elements;
static std::map<int, LedgerEntryFormat*> byType;
static std::map<std::string, LedgerEntryFormat*> byName;
@@ -70,7 +70,7 @@ public:
}
LedgerEntryFormat& operator<<(const SOElement& el)
{
elements.push_back(new SOElement(el));
elements.push_back(el);
return *this;
}

View File

@@ -130,14 +130,26 @@ std::auto_ptr<SerializedType> STObject::makeDeserializedObject(SerializedTypeID
}
}
void STObject::set(const std::vector<SOElement::ref>& type)
void SOTemplate::push_back(const SOElement &r)
{
assert(mMap.find(r.e_field.getCode()) == mMap.end());
mMap[r.e_field.getCode()] = mTypes.size();
mTypes.push_back(new SOElement(r));
}
int SOTemplate::getIndex(SField::ref f) const
{
std::map<int, int>::const_iterator it = mMap.find(f.getCode());
return (it == mMap.end()) ? -1 : it->second;
}
void STObject::set(const SOTemplate& type)
{
mData.clear();
mType.clear();
mType = &type;
BOOST_FOREACH(SOElement::ref elem, type)
BOOST_FOREACH(const SOElement* elem, type.peek())
{
mType.push_back(elem);
if (elem->flags != SOE_REQUIRED)
giveObject(makeNonPresentObject(elem->e_field));
else
@@ -145,15 +157,14 @@ void STObject::set(const std::vector<SOElement::ref>& type)
}
}
bool STObject::setType(const std::vector<SOElement::ref> &type)
bool STObject::setType(const SOTemplate &type)
{
boost::ptr_vector<SerializedType> newData(type.size());
boost::ptr_vector<SerializedType> newData(type.peek().size());
bool valid = true;
mType.clear();
mType.reserve(type.size());
mType = &type;
BOOST_FOREACH(SOElement::ref elem, type)
BOOST_FOREACH(const SOElement* elem, type.peek())
{
bool match = false;
for (boost::ptr_vector<SerializedType>::iterator it = mData.begin(); it != mData.end(); ++it)
@@ -180,8 +191,6 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
}
newData.push_back(makeNonPresentObject(elem->e_field));
}
mType.push_back(elem);
}
BOOST_FOREACH(const SerializedType& t, mData)
@@ -201,7 +210,7 @@ bool STObject::setType(const std::vector<SOElement::ref> &type)
bool STObject::isValidForType()
{
boost::ptr_vector<SerializedType>::iterator it = mData.begin();
BOOST_FOREACH(SOElement::ref elem, mType)
BOOST_FOREACH(const SOElement* elem, mType->peek())
{
if (it == mData.end())
return false;
@@ -215,14 +224,9 @@ bool STObject::isValidForType()
bool STObject::isFieldAllowed(SField::ref field)
{
if (isFree())
if (mType == NULL)
return true;
BOOST_FOREACH(SOElement::ref elem, mType)
{ // are any required elemnents missing
if (elem->e_field == field)
return true;
}
return false;
return mType->getIndex(field) != -1;
}
bool STObject::set(SerializerIterator& sit, int depth)
@@ -361,6 +365,9 @@ uint256 STObject::getSigningHash(uint32 prefix) const
int STObject::getFieldIndex(SField::ref field) const
{
if (mType != NULL)
return mType->getIndex(field);
int i = 0;
BOOST_FOREACH(const SerializedType& elem, mData)
{
@@ -1243,11 +1250,11 @@ BOOST_AUTO_TEST_CASE( FieldManipulation_test )
SField sfTestU32(STI_UINT32, 255, "TestU32");
SField sfTestObject(STI_OBJECT, 255, "TestObject");
std::vector<SOElement::ref> elements;
elements.push_back(new SOElement(sfFlags, SOE_REQUIRED));
elements.push_back(new SOElement(sfTestVL, SOE_REQUIRED));
elements.push_back(new SOElement(sfTestH256, SOE_OPTIONAL));
elements.push_back(new SOElement(sfTestU32, SOE_REQUIRED));
SOTemplate elements;
elements.push_back(SOElement(sfFlags, SOE_REQUIRED));
elements.push_back(SOElement(sfTestVL, SOE_REQUIRED));
elements.push_back(SOElement(sfTestH256, SOE_OPTIONAL));
elements.push_back(SOElement(sfTestU32, SOE_REQUIRED));
STObject object1(elements, sfTestObject);
STObject object2(object1);

View File

@@ -18,32 +18,44 @@ DEFINE_INSTANCE(SerializedArray);
class SOElement
{ // An element in the description of a serialized object
public:
typedef SOElement const * ref; // used to point to one element
SField::ref e_field;
const SOE_Flags flags;
SField::ref e_field;
const SOE_Flags flags;
SOElement(SField::ref fi, SOE_Flags fl) : e_field(fi), flags(fl) { ; }
};
SOElement(SField::ref fi, SOE_Flags fl) : e_field(fi), flags(fl) { ; }
class SOTemplate
{
protected:
std::vector<const SOElement*> mTypes;
std::map<int, int> mMap; // field code -> index
public:
SOTemplate() { ; }
const std::vector<const SOElement*>& peek() const { return mTypes; }
void push_back(const SOElement& r);
int getIndex(SField::ref) const;
};
class STObject : public SerializedType, private IS_INSTANCE(SerializedObject)
{
protected:
boost::ptr_vector<SerializedType> mData;
std::vector<SOElement::ref> mType;
const SOTemplate* mType;
STObject* duplicate() const { return new STObject(*this); }
STObject(SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType(name) { mData.swap(data); }
STObject(SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType(name), mType(NULL)
{ mData.swap(data); }
public:
STObject() { ; }
STObject() : mType(NULL) { ; }
STObject(SField::ref name) : SerializedType(name) { ; }
STObject(SField::ref name) : SerializedType(name), mType(NULL) { ; }
STObject(const std::vector<SOElement::ref>& type, SField::ref name) : SerializedType(name)
STObject(const SOTemplate& type, SField::ref name) : SerializedType(name)
{ set(type); }
STObject(const std::vector<SOElement::ref>& type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
STObject(const SOTemplate& type, SerializerIterator& sit, SField::ref name) : SerializedType(name)
{ set(sit); setType(type); }
std::auto_ptr<STObject> oClone() const { return std::auto_ptr<STObject>(new STObject(*this)); }
@@ -54,12 +66,12 @@ public:
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, SField::ref name);
bool setType(const std::vector<SOElement::ref>& type);
bool setType(const SOTemplate& type);
bool isValidForType();
bool isFieldAllowed(SField::ref);
bool isFree() const { return mType.empty(); }
bool isFree() const { return mType == NULL; }
void set(const std::vector<SOElement::ref>&);
void set(const SOTemplate&);
bool set(SerializerIterator& u, int depth = 0);
virtual SerializedTypeID getSType() const { return STI_OBJECT; }

View File

@@ -6,25 +6,22 @@
DECLARE_INSTANCE(SerializedValidation);
std::vector<SOElement::ref> sValidationFormat;
SOTemplate sValidationFormat;
static bool SVFInit()
void SVFInit()
{
sValidationFormat.push_back(new SOElement(sfFlags, SOE_REQUIRED));
sValidationFormat.push_back(new SOElement(sfLedgerHash, SOE_REQUIRED));
sValidationFormat.push_back(new SOElement(sfLedgerSequence, SOE_OPTIONAL));
sValidationFormat.push_back(new SOElement(sfCloseTime, SOE_OPTIONAL));
sValidationFormat.push_back(new SOElement(sfLoadFee, SOE_OPTIONAL));
sValidationFormat.push_back(new SOElement(sfBaseFee, SOE_OPTIONAL));
sValidationFormat.push_back(new SOElement(sfFeatures, SOE_OPTIONAL));
sValidationFormat.push_back(new SOElement(sfSigningTime, SOE_REQUIRED));
sValidationFormat.push_back(new SOElement(sfSigningPubKey, SOE_REQUIRED));
sValidationFormat.push_back(new SOElement(sfSignature, SOE_OPTIONAL));
return true;
sValidationFormat.push_back(SOElement(sfFlags, SOE_REQUIRED));
sValidationFormat.push_back(SOElement(sfLedgerHash, SOE_REQUIRED));
sValidationFormat.push_back(SOElement(sfLedgerSequence, SOE_OPTIONAL));
sValidationFormat.push_back(SOElement(sfCloseTime, SOE_OPTIONAL));
sValidationFormat.push_back(SOElement(sfLoadFee, SOE_OPTIONAL));
sValidationFormat.push_back(SOElement(sfBaseFee, SOE_OPTIONAL));
sValidationFormat.push_back(SOElement(sfFeatures, SOE_OPTIONAL));
sValidationFormat.push_back(SOElement(sfSigningTime, SOE_REQUIRED));
sValidationFormat.push_back(SOElement(sfSigningPubKey, SOE_REQUIRED));
sValidationFormat.push_back(SOElement(sfSignature, SOE_OPTIONAL));
};
bool SVFinitComplete = SVFInit();
const uint32 SerializedValidation::sFullFlag = 0x1;
SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature)

View File

@@ -16,7 +16,7 @@ std::map<std::string, TransactionFormat*> TransactionFormat::byName;
#define DECLARE_TF(name, type) tf = new TransactionFormat(#name, type); (*tf) TF_BASE
static bool TFInit()
void TFInit()
{
TransactionFormat* tf;
@@ -84,12 +84,8 @@ static bool TFInit()
<< SOElement(sfReserveBase, SOE_REQUIRED)
<< SOElement(sfReserveIncrement, SOE_REQUIRED)
;
return true;
}
bool TFInitComplete = TFInit();
TransactionFormat* TransactionFormat::getTxnFormat(TransactionType t)
{
std::map<int, TransactionFormat*>::iterator it = byType.find(static_cast<int>(t));

View File

@@ -31,7 +31,7 @@ class TransactionFormat
public:
std::string t_name;
TransactionType t_type;
std::vector<SOElement::ref> elements;
SOTemplate elements;
static std::map<int, TransactionFormat*> byType;
static std::map<std::string, TransactionFormat*> byName;
@@ -43,7 +43,7 @@ public:
}
TransactionFormat& operator<<(const SOElement& el)
{
elements.push_back(new SOElement(el));
elements.push_back(el);
return *this;
}

View File

@@ -16,6 +16,10 @@
namespace po = boost::program_options;
extern bool AddSystemEntropy();
extern void TFInit();
extern void LEFInit();
extern void SVFInit();
using namespace std;
using namespace boost::unit_test;
@@ -188,6 +192,10 @@ int main(int argc, char* argv[])
InstanceType::multiThread();
TFInit();
LEFInit();
SVFInit();
if (vm.count("unittest"))
{
unit_test_main(init_unit_test, argc, argv);