Skip to content

Commit 25a211a

Browse files
committed
Add optimized CSizeComputer serializers
To get the advantages of faster GetSerializeSize() implementations back that were removed in "Make GetSerializeSize a wrapper on top of CSizeComputer", reintroduce them in the few places in the form of a specialized Serialize() implementation. This actually gets us in a better state than before, as these even get used when they're invoked indirectly in the serialization of another object.
1 parent a2929a2 commit 25a211a

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/pubkey.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ struct CExtPubKey {
210210
void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]);
211211
bool Derive(CExtPubKey& out, unsigned int nChild) const;
212212

213+
void Serialize(CSizeComputer& s) const
214+
{
215+
// Optimized implementation for ::GetSerializeSize that avoids copying.
216+
s.seek(BIP32_EXTKEY_SIZE + 1); // add one byte for the size (compact int)
217+
}
213218
template <typename Stream>
214219
void Serialize(Stream& s) const
215220
{

src/serialize.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@ inline float ser_uint32_to_float(uint32_t y)
151151
// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t)
152152
//
153153

154+
class CSizeComputer;
155+
154156
enum
155157
{
156158
// primary actions
@@ -225,6 +227,8 @@ inline unsigned int GetSizeOfCompactSize(uint64_t nSize)
225227
else return sizeof(unsigned char) + sizeof(uint64_t);
226228
}
227229

230+
inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize);
231+
228232
template<typename Stream>
229233
void WriteCompactSize(Stream& os, uint64_t nSize)
230234
{
@@ -319,6 +323,9 @@ inline unsigned int GetSizeOfVarInt(I n)
319323
return nRet;
320324
}
321325

326+
template<typename I>
327+
inline void WriteVarInt(CSizeComputer& os, I n);
328+
322329
template<typename Stream, typename I>
323330
void WriteVarInt(Stream& os, I n)
324331
{
@@ -800,6 +807,17 @@ inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
800807

801808

802809

810+
/* ::GetSerializeSize implementations
811+
*
812+
* Computing the serialized size of objects is done through a special stream
813+
* object of type CSizeComputer, which only records the number of bytes written
814+
* to it.
815+
*
816+
* If your Serialize or SerializationOp method has non-trivial overhead for
817+
* serialization, it may be worthwhile to implement a specialized version for
818+
* CSizeComputer, which uses the s.seek() method to record bytes that would
819+
* be written instead.
820+
*/
803821
class CSizeComputer
804822
{
805823
protected:
@@ -815,6 +833,12 @@ class CSizeComputer
815833
this->nSize += _nSize;
816834
}
817835

836+
/** Pretend _nSize bytes are written, without specifying them. */
837+
void seek(size_t _nSize)
838+
{
839+
this->nSize += _nSize;
840+
}
841+
818842
template<typename T>
819843
CSizeComputer& operator<<(const T& obj)
820844
{
@@ -878,6 +902,17 @@ inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&.
878902
::UnserializeMany(s, args...);
879903
}
880904

905+
template<typename I>
906+
inline void WriteVarInt(CSizeComputer &s, I n)
907+
{
908+
s.seek(GetSizeOfVarInt<I>(n));
909+
}
910+
911+
inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize)
912+
{
913+
s.seek(GetSizeOfCompactSize(nSize));
914+
}
915+
881916
template <typename T>
882917
size_t GetSerializeSize(const T& t, int nType, int nVersion = 0)
883918
{

0 commit comments

Comments
 (0)