From 432ad769521704fe91f8801cc878842c68e0ad0c Mon Sep 17 00:00:00 2001 From: Tadge Dryja Date: Wed, 13 Apr 2016 20:51:02 -0700 Subject: [PATCH 1/2] fix memory allignment for 32-bit architectures (#668) having 3 int32s above the uint64s in the struct will cause misalignment for some 32-bit architectures. see https://golang.org/pkg/sync/atomic/#pkg-note-BUG This aligns bytesReceived and bytesSent. --- server.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index cf4b8c0575..b7fe2400f4 100644 --- a/server.go +++ b/server.go @@ -170,11 +170,12 @@ func (ps *peerState) forAllPeers(closure func(sp *serverPeer)) { // bitcoin peers. type server struct { // The following variables must only be used atomically. + // Putting the uint64s first makes them 64-bit aligned for 32-bit systems. + bytesReceived uint64 // Total bytes received from all peers since start. + bytesSent uint64 // Total bytes sent by all peers since start. started int32 shutdown int32 shutdownSched int32 - bytesReceived uint64 // Total bytes received from all peers since start. - bytesSent uint64 // Total bytes sent by all peers since start. listeners []net.Listener chainParams *chaincfg.Params From e15d3008cfd59756db9570da9e47da6831313196 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 14 Apr 2016 00:19:23 -0500 Subject: [PATCH 2/2] mining: Improve tests for prio queue. (#667) This improves the tests of the priority queue to include the secondary sort ordering as well as adds some manual entries to ensure the edge conditions are properly tested. This also brings the priority queue test coverage up to 100%. --- mining_test.go | 113 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/mining_test.go b/mining_test.go index c7069637a6..e0b5bd727b 100644 --- a/mining_test.go +++ b/mining_test.go @@ -15,51 +15,96 @@ import ( // TestTxFeePrioHeap ensures the priority queue for transaction fees and // priorities works as expected. func TestTxFeePrioHeap(t *testing.T) { - // Create priority items with random fees and priorites. - const numItems = 1000 - prioItems := make([]*txPrioItem, numItems) - highestFeePerKB := int64(0) - highestPrio := float64(0) - for i := 0; i < 1000; i++ { - randPrio := rand.Float64() * 100 - if randPrio > highestPrio { - highestPrio = randPrio + // Create some fake priority items that exercise the expected sort + // edge conditions. + testItems := []*txPrioItem{ + {feePerKB: 5678, priority: 3}, + {feePerKB: 5678, priority: 1}, + {feePerKB: 5678, priority: 1}, // Duplicate fee and prio + {feePerKB: 5678, priority: 5}, + {feePerKB: 5678, priority: 2}, + {feePerKB: 1234, priority: 3}, + {feePerKB: 1234, priority: 1}, + {feePerKB: 1234, priority: 5}, + {feePerKB: 1234, priority: 5}, // Duplicate fee and prio + {feePerKB: 1234, priority: 2}, + {feePerKB: 10000, priority: 0}, // Higher fee, smaller prio + {feePerKB: 0, priority: 10000}, // Higher prio, lower fee + } + + // Add random data in addition to the edge conditions already manually + // specified. + randSeed := rand.Int63() + defer func() { + if t.Failed() { + t.Logf("Random numbers using seed: %v", randSeed) } - randFeePerKB := int64(rand.Float64() * btcutil.SatoshiPerBitcoin) - if randFeePerKB > highestFeePerKB { - highestFeePerKB = randFeePerKB + }() + prng := rand.New(rand.NewSource(randSeed)) + for i := 0; i < 1000; i++ { + testItems = append(testItems, &txPrioItem{ + feePerKB: int64(prng.Float64() * btcutil.SatoshiPerBitcoin), + priority: prng.Float64() * 100, + }) + } + + // Test sorting by fee per KB then priority. + var highest *txPrioItem + priorityQueue := newTxPriorityQueue(len(testItems), true) + for i := 0; i < len(testItems); i++ { + prioItem := testItems[i] + if highest == nil { + highest = prioItem } - prioItems[i] = &txPrioItem{ - tx: nil, - priority: randPrio, - feePerKB: randFeePerKB, + if prioItem.feePerKB >= highest.feePerKB && + prioItem.priority > highest.priority { + + highest = prioItem } + heap.Push(priorityQueue, prioItem) } - // Test sorting by fee per KB. - priorityQueue := newTxPriorityQueue(numItems, true) - for i := 0; i < numItems; i++ { - heap.Push(priorityQueue, prioItems[i]) - } - for i := 0; i < numItems; i++ { + for i := 0; i < len(testItems); i++ { prioItem := heap.Pop(priorityQueue).(*txPrioItem) - if prioItem.feePerKB > highestFeePerKB { - t.Fatalf("bad pop: %v fee per KB was more than last of %v", - prioItem.feePerKB, highestFeePerKB) + if prioItem.feePerKB >= highest.feePerKB && + prioItem.priority > highest.priority { + + t.Fatalf("fee sort: item (fee per KB: %v, "+ + "priority: %v) higher than than prev "+ + "(fee per KB: %v, priority %v)", + prioItem.feePerKB, prioItem.priority, + highest.feePerKB, highest.priority) } - highestFeePerKB = prioItem.feePerKB + highest = prioItem } - // Test sorting by priority. - priorityQueue = newTxPriorityQueue(numItems, false) - for i := 0; i < numItems; i++ { - heap.Push(priorityQueue, prioItems[i]) + // Test sorting by priority then fee per KB. + highest = nil + priorityQueue = newTxPriorityQueue(len(testItems), false) + for i := 0; i < len(testItems); i++ { + prioItem := testItems[i] + if highest == nil { + highest = prioItem + } + if prioItem.priority >= highest.priority && + prioItem.feePerKB > highest.feePerKB { + + highest = prioItem + } + heap.Push(priorityQueue, prioItem) } - for i := 0; i < numItems; i++ { + + for i := 0; i < len(testItems); i++ { prioItem := heap.Pop(priorityQueue).(*txPrioItem) - if prioItem.priority > highestPrio { - t.Fatalf("bad pop: %v priority was more than last of %v", - prioItem.priority, highestPrio) + if prioItem.priority >= highest.priority && + prioItem.feePerKB > highest.feePerKB { + + t.Fatalf("priority sort: item (fee per KB: %v, "+ + "priority: %v) higher than than prev "+ + "(fee per KB: %v, priority %v)", + prioItem.feePerKB, prioItem.priority, + highest.feePerKB, highest.priority) } + highest = prioItem } }