diff --git a/blocklocator.go b/blocklocator.go index 5ae9d5e2..a3258f25 100644 --- a/blocklocator.go +++ b/blocklocator.go @@ -29,7 +29,8 @@ type BlockLocator []*btcwire.ShaHash // consist of the passed hash func (b *BlockChain) BlockLocatorFromHash(hash *btcwire.ShaHash) BlockLocator { // The locator contains the requested hash at the very least. - locator := BlockLocator([]*btcwire.ShaHash{hash}) + locator := make(BlockLocator, 0, btcwire.MaxBlockLocatorsPerMsg) + locator = append(locator, hash) // Nothing more to do if a locator for the genesis hash was requested. if hash.IsEqual(b.chainParams().GenesisHash) { diff --git a/process.go b/process.go index 98e120f4..60894d68 100644 --- a/process.go +++ b/process.go @@ -38,10 +38,15 @@ func (b *BlockChain) blockExists(hash *btcwire.ShaHash) bool { // It repeats the process for the newly accepted blocks (to detect further // orphans which may no longer be orphans) until there are no more. func (b *BlockChain) processOrphans(hash *btcwire.ShaHash) error { - processHashes := []*btcwire.ShaHash{hash} + // Start with processing at least the passed hash. Leave a little room + // for additional orphan blocks that need to be processed without + // needing to grow the array in the common case. + processHashes := make([]*btcwire.ShaHash, 0, 10) + processHashes = append(processHashes, hash) for len(processHashes) > 0 { // Pop the first hash to process from the slice. processHash := processHashes[0] + processHashes[0] = nil // Prevent GC leak. processHashes = processHashes[1:] // Look up all orphans that are parented by the block we just diff --git a/txlookup.go b/txlookup.go index 50f5c184..0cc08a88 100644 --- a/txlookup.go +++ b/txlookup.go @@ -215,10 +215,20 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc txInFlight[*txHash] = i } + // Make a reasonable guess for the maximum number of needed input + // transactions to use as the starting point for the needed transactions + // array. The array will dynamically grow as needed, but it's much less + // overhead to avoid growing and copying the array multiple times in the + // common case. Each block usually has no more than ten inputs per + // transaction, so use that as a reasonable starting point. A block + // with 2,000 transactions would only result in around 156KB on a 64-bit + // system using this approach. + maxNeededHint := (len(transactions) - 1) * 10 + txNeededList := make([]*btcwire.ShaHash, 0, maxNeededHint) + // Loop through all of the transaction inputs (except for the coinbase // which has no inputs) collecting them into lists of what is needed and // what is already known (in-flight). - var txNeededList []*btcwire.ShaHash txStore := make(map[btcwire.ShaHash]*txData) for i, tx := range transactions[1:] { for _, txIn := range tx.TxIn {