Cache checksum for non-empty messages.
VersionMessage and AddressMessage require some special handling. VersionMessage because it's never lazy parsed or cached. AddressMessage because when serializing PeerAddresses the time field is dynamic.
Checksum byte array is currently transient so no gains for a message extracted from java serialization then bitcoinSerialized. I don't think this would ever happen in real life but if it does then it could also be included in the serialized object.
Customize Sha256Hash.hashCode() method to only use first n bytes of the backing array. This provides uniqueness to 256^n combinations. As hashcode is not required to be guaranteed unique this fulfills the contract and reduces hashing time.
Use case is for applications that do a lot of mapping by Sha256Hash. Each put and get require several hashcode operations. Cached hashcode is already implemented in 8.patch.
Similar changes to this yielded huge performance benefits in poolserverj.
There is no point implementing a FastEquals version of equals given the bytes are essentially random and no byte is any more likely unique than another.
Add UnsafeByteArrayOutputStream. ByteArrayOutputStreams are used extensively and result in a lot of short lived byte arrays.
This patch contains two optimizations
1/ attempt to provide the final length to ByteArrayOutputStream constructor to avoid constantly resizing the backing array. Default size is 32 which means larger messages may require several array reallocations and almost all will require at least one.
2/ provides the UnsafeByteArrayOutputStream class which eliminates method synchronization. The toByteArray() will return the backing array rather than a copy if the correct length was provided in the constructor.
In the worst case scenario this cuts array allocations from 3 to 2.
In the most common worst case from 3 to 1.
In most best cases where final array size is greater than 128 bytes from > 4 to 1.
More optimizations: pre-calculate or guess various array sizes to avoid needlessly re-sizing them later.
Sha256Hash caches the hashCode.
Message classes now track their (estimated) length even when not using deserialization-related constructors.
Optimise BitcoinSerialiser for Transactions. When calculating checksum on deserialize use it prepopulate the transaction's hash. Likewise on serialize check if the Transaction already has a hash and use that to write checksum bytes. This yields performance improvesment up to 400% by saving on a double hash.
Don't parse all the subcomponents of a Transaction purely to calculate its length, instead do the minimal work possible.
Recaching on a call to bitcoinSerialise(). Prevents double serialization of transactions and inputs/outputs when calculating a merkleroot during block serialization. Also makes it more likely the original larger byte array can be GC'd
1) Added getters and setters to many objects that lacked them.
2) Introduce a parseLite method that is called even in "lazy parse" mode. This calculates the length of the message so children can be skipped when parsing a container object.
3) Full serialization for AddressMessage
4) Added a (huge, standalone) SpeedTest.
5) Add unit tests for the matrix of lazy parsing modes.
A bunch of review comments are added to the TODO list for completion after the patch series is checked in. This is to avoid large numbers of merge conflicts as later parts of the patch-series are committed.
1) Introduce partial support for caching the underlying byte arrays during message deserialization, so re-serialization can be skipped in the case where a message is not modified.
2) Add c'tors that allow a message to be configured to lazily parse on-demand.
Note that the getters/setters that make lazy parsing transparent are coming in future commits.
Don't deserialize block or tx messages that were already seen, to avoid wasting battery and causing memory spikes that can trigger OOM conditions. Updates issue 73.