Switch peer.requestQueue from linked list to slice.

Only two operations are performed with this data structure: adding to
the back and removing from the front.  Because middle inserts and
deletions are never needed, a linked list results in overall worse
performance due to an extra allocation for each element's node, worse
cache locality, and the runtime cost of boxing/unboxing each item
during accesses.

On top of the performance gains, a slice is more type safe as it is a
true generic data structure making it is impossible to insert or
access an element with the wrong type.
This commit is contained in:
Josh Rickmar 2015-01-08 01:35:45 -05:00
parent 11bf021ced
commit 869363a210
2 changed files with 7 additions and 6 deletions

View file

@ -930,7 +930,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) {
}
if !haveInv {
// Add it to the request queue.
imsg.peer.requestQueue.PushBack(iv)
imsg.peer.requestQueue = append(imsg.peer.requestQueue, iv)
continue
}
@ -980,9 +980,10 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) {
numRequested := 0
gdmsg := btcwire.NewMsgGetData()
requestQueue := imsg.peer.requestQueue
for e := requestQueue.Front(); e != nil; e = requestQueue.Front() {
iv := e.Value.(*btcwire.InvVect)
imsg.peer.requestQueue.Remove(e)
for len(requestQueue) != 0 {
iv := requestQueue[0]
requestQueue[0] = nil
requestQueue = requestQueue[1:]
switch iv.Type {
case btcwire.InvTypeBlock:
@ -1010,6 +1011,7 @@ func (b *blockManager) handleInvMsg(imsg *invMsg) {
break
}
}
imsg.peer.requestQueue = requestQueue
if len(gdmsg.InvList) > 0 {
imsg.peer.QueueMessage(gdmsg, nil)
}

View file

@ -162,7 +162,7 @@ type peer struct {
prevGetBlocksStop *btcwire.ShaHash // owned by blockmanager
prevGetHdrsBegin *btcwire.ShaHash // owned by blockmanager
prevGetHdrsStop *btcwire.ShaHash // owned by blockmanager
requestQueue *list.List
requestQueue []*btcwire.InvVect
filter *bloom.Filter
relayMtx sync.Mutex
disableRelayTx bool
@ -1890,7 +1890,6 @@ func newPeerBase(s *server, inbound bool) *peer {
knownInventory: NewMruInventoryMap(maxKnownInventory),
requestedTxns: make(map[btcwire.ShaHash]struct{}),
requestedBlocks: make(map[btcwire.ShaHash]struct{}),
requestQueue: list.New(),
filter: bloom.LoadFilter(nil),
outputQueue: make(chan outMsg, outputBufferSize),
sendQueue: make(chan outMsg, 1), // nonblocking sync