686 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			686 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2017 The go-ethereum Authors
 | |
| // This file is part of the go-ethereum library.
 | |
| //
 | |
| // The go-ethereum library is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU Lesser General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| //
 | |
| // The go-ethereum library is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | |
| // GNU Lesser General Public License for more details.
 | |
| //
 | |
| // You should have received a copy of the GNU Lesser General Public License
 | |
| // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 | |
| package pot
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"math/rand"
 | |
| 	"runtime"
 | |
| 	"sync"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/ethereum/go-ethereum/swarm/log"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	maxEachNeighbourTests = 420
 | |
| 	maxEachNeighbour      = 420
 | |
| 	maxSwap               = 420
 | |
| 	maxSwapTests          = 420
 | |
| )
 | |
| 
 | |
| // func init() {
 | |
| // 	log.Root().SetHandler(log.LvlFilterHandler(log.LvlTrace, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
 | |
| // }
 | |
| 
 | |
| type testAddr struct {
 | |
| 	a []byte
 | |
| 	i int
 | |
| }
 | |
| 
 | |
| func newTestAddr(s string, i int) *testAddr {
 | |
| 	return &testAddr{NewAddressFromString(s), i}
 | |
| }
 | |
| 
 | |
| func (a *testAddr) Address() []byte {
 | |
| 	return a.a
 | |
| }
 | |
| 
 | |
| func (a *testAddr) String() string {
 | |
| 	return Label(a.a)
 | |
| }
 | |
| 
 | |
| func randomTestAddr(n int, i int) *testAddr {
 | |
| 	v := RandomAddress().Bin()[:n]
 | |
| 	return newTestAddr(v, i)
 | |
| }
 | |
| 
 | |
| func randomtestAddr(n int, i int) *testAddr {
 | |
| 	v := RandomAddress().Bin()[:n]
 | |
| 	return newTestAddr(v, i)
 | |
| }
 | |
| 
 | |
| func indexes(t *Pot) (i []int, po []int) {
 | |
| 	t.Each(func(v Val, p int) bool {
 | |
| 		a := v.(*testAddr)
 | |
| 		i = append(i, a.i)
 | |
| 		po = append(po, p)
 | |
| 		return true
 | |
| 	})
 | |
| 	return i, po
 | |
| }
 | |
| 
 | |
| func testAdd(t *Pot, pof Pof, j int, values ...string) (_ *Pot, n int, f bool) {
 | |
| 	for i, val := range values {
 | |
| 		t, n, f = Add(t, newTestAddr(val, i+j), pof)
 | |
| 	}
 | |
| 	return t, n, f
 | |
| }
 | |
| 
 | |
| func TestPotAdd(t *testing.T) {
 | |
| 	pof := DefaultPof(8)
 | |
| 	n := NewPot(newTestAddr("00111100", 0), 0)
 | |
| 	// Pin set correctly
 | |
| 	exp := "00111100"
 | |
| 	got := Label(n.Pin())[:8]
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect pinned value. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 	// check size
 | |
| 	goti := n.Size()
 | |
| 	expi := 1
 | |
| 	if goti != expi {
 | |
| 		t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
 | |
| 	}
 | |
| 
 | |
| 	n, _, _ = testAdd(n, pof, 1, "01111100", "00111100", "01111100", "00011100")
 | |
| 	// check size
 | |
| 	goti = n.Size()
 | |
| 	expi = 3
 | |
| 	if goti != expi {
 | |
| 		t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
 | |
| 	}
 | |
| 	inds, po := indexes(n)
 | |
| 	got = fmt.Sprintf("%v", inds)
 | |
| 	exp = "[3 4 2]"
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 	got = fmt.Sprintf("%v", po)
 | |
| 	exp = "[1 2 0]"
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPotRemove(t *testing.T) {
 | |
| 	pof := DefaultPof(8)
 | |
| 	n := NewPot(newTestAddr("00111100", 0), 0)
 | |
| 	n, _, _ = Remove(n, newTestAddr("00111100", 0), pof)
 | |
| 	exp := "<nil>"
 | |
| 	got := Label(n.Pin())
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect pinned value. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 	n, _, _ = testAdd(n, pof, 1, "00000000", "01111100", "00111100", "00011100")
 | |
| 	n, _, _ = Remove(n, newTestAddr("00111100", 0), pof)
 | |
| 	goti := n.Size()
 | |
| 	expi := 3
 | |
| 	if goti != expi {
 | |
| 		t.Fatalf("incorrect number of elements in Pot. Expected %v, got %v", expi, goti)
 | |
| 	}
 | |
| 	inds, po := indexes(n)
 | |
| 	got = fmt.Sprintf("%v", inds)
 | |
| 	exp = "[2 4 0]"
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 	got = fmt.Sprintf("%v", po)
 | |
| 	exp = "[1 3 0]"
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect po-s in iteration over Pot. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 	// remove again
 | |
| 	n, _, _ = Remove(n, newTestAddr("00111100", 0), pof)
 | |
| 	inds, _ = indexes(n)
 | |
| 	got = fmt.Sprintf("%v", inds)
 | |
| 	exp = "[2 4]"
 | |
| 	if got != exp {
 | |
| 		t.Fatalf("incorrect indexes in iteration over Pot. Expected %v, got %v", exp, got)
 | |
| 	}
 | |
| 
 | |
| }
 | |
| 
 | |
| func TestPotSwap(t *testing.T) {
 | |
| 	for i := 0; i < maxSwapTests; i++ {
 | |
| 		alen := maxkeylen
 | |
| 		pof := DefaultPof(alen)
 | |
| 		max := rand.Intn(maxSwap)
 | |
| 
 | |
| 		n := NewPot(nil, 0)
 | |
| 		var m []*testAddr
 | |
| 		var found bool
 | |
| 		for j := 0; j < 2*max; {
 | |
| 			v := randomtestAddr(alen, j)
 | |
| 			n, _, found = Add(n, v, pof)
 | |
| 			if !found {
 | |
| 				m = append(m, v)
 | |
| 				j++
 | |
| 			}
 | |
| 		}
 | |
| 		k := make(map[string]*testAddr)
 | |
| 		for j := 0; j < max; {
 | |
| 			v := randomtestAddr(alen, 1)
 | |
| 			_, found := k[Label(v)]
 | |
| 			if !found {
 | |
| 				k[Label(v)] = v
 | |
| 				j++
 | |
| 			}
 | |
| 		}
 | |
| 		for _, v := range k {
 | |
| 			m = append(m, v)
 | |
| 		}
 | |
| 		f := func(v Val) Val {
 | |
| 			tv := v.(*testAddr)
 | |
| 			if tv.i < max {
 | |
| 				return nil
 | |
| 			}
 | |
| 			tv.i = 0
 | |
| 			return v
 | |
| 		}
 | |
| 		for _, val := range m {
 | |
| 			n, _, _, _ = Swap(n, val, pof, func(v Val) Val {
 | |
| 				if v == nil {
 | |
| 					return val
 | |
| 				}
 | |
| 				return f(v)
 | |
| 			})
 | |
| 		}
 | |
| 		sum := 0
 | |
| 		n.Each(func(v Val, i int) bool {
 | |
| 			if v == nil {
 | |
| 				return true
 | |
| 			}
 | |
| 			sum++
 | |
| 			tv := v.(*testAddr)
 | |
| 			if tv.i > 1 {
 | |
| 				t.Fatalf("item value incorrect, expected 0, got %v", tv.i)
 | |
| 			}
 | |
| 			return true
 | |
| 		})
 | |
| 		if sum != 2*max {
 | |
| 			t.Fatalf("incorrect number of elements. expected %v, got %v", 2*max, sum)
 | |
| 		}
 | |
| 		if sum != n.Size() {
 | |
| 			t.Fatalf("incorrect size. expected %v, got %v", sum, n.Size())
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func checkPo(val Val, pof Pof) func(Val, int) error {
 | |
| 	return func(v Val, po int) error {
 | |
| 		// check the po
 | |
| 		exp, _ := pof(val, v, 0)
 | |
| 		if po != exp {
 | |
| 			return fmt.Errorf("incorrect prox order for item %v in neighbour iteration for %v. Expected %v, got %v", v, val, exp, po)
 | |
| 		}
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func checkOrder(val Val) func(Val, int) error {
 | |
| 	po := maxkeylen
 | |
| 	return func(v Val, p int) error {
 | |
| 		if po < p {
 | |
| 			return fmt.Errorf("incorrect order for item %v in neighbour iteration for %v. PO %v > %v (previous max)", v, val, p, po)
 | |
| 		}
 | |
| 		po = p
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func checkValues(m map[string]bool, val Val) func(Val, int) error {
 | |
| 	return func(v Val, po int) error {
 | |
| 		duplicate, ok := m[Label(v)]
 | |
| 		if !ok {
 | |
| 			return fmt.Errorf("alien value %v", v)
 | |
| 		}
 | |
| 		if duplicate {
 | |
| 			return fmt.Errorf("duplicate value returned: %v", v)
 | |
| 		}
 | |
| 		m[Label(v)] = true
 | |
| 		return nil
 | |
| 	}
 | |
| }
 | |
| 
 | |
| var errNoCount = errors.New("not count")
 | |
| 
 | |
| func testPotEachNeighbour(n *Pot, pof Pof, val Val, expCount int, fs ...func(Val, int) error) error {
 | |
| 	var err error
 | |
| 	var count int
 | |
| 	n.EachNeighbour(val, pof, func(v Val, po int) bool {
 | |
| 		for _, f := range fs {
 | |
| 			err = f(v, po)
 | |
| 			if err != nil {
 | |
| 				return err.Error() == errNoCount.Error()
 | |
| 			}
 | |
| 		}
 | |
| 		count++
 | |
| 		return count != expCount
 | |
| 	})
 | |
| 	if err == nil && count < expCount {
 | |
| 		return fmt.Errorf("not enough neighbours returned, expected %v, got %v", expCount, count)
 | |
| 	}
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| const (
 | |
| 	mergeTestCount  = 5
 | |
| 	mergeTestChoose = 5
 | |
| )
 | |
| 
 | |
| func TestPotMergeCommon(t *testing.T) {
 | |
| 	vs := make([]*testAddr, mergeTestCount)
 | |
| 	for i := 0; i < maxEachNeighbourTests; i++ {
 | |
| 		alen := maxkeylen
 | |
| 		pof := DefaultPof(alen)
 | |
| 
 | |
| 		for j := 0; j < len(vs); j++ {
 | |
| 			vs[j] = randomtestAddr(alen, j)
 | |
| 		}
 | |
| 		max0 := rand.Intn(mergeTestChoose) + 1
 | |
| 		max1 := rand.Intn(mergeTestChoose) + 1
 | |
| 		n0 := NewPot(nil, 0)
 | |
| 		n1 := NewPot(nil, 0)
 | |
| 		log.Trace(fmt.Sprintf("round %v: %v - %v", i, max0, max1))
 | |
| 		m := make(map[string]bool)
 | |
| 		var found bool
 | |
| 		for j := 0; j < max0; {
 | |
| 			r := rand.Intn(max0)
 | |
| 			v := vs[r]
 | |
| 			n0, _, found = Add(n0, v, pof)
 | |
| 			if !found {
 | |
| 				m[Label(v)] = false
 | |
| 				j++
 | |
| 			}
 | |
| 		}
 | |
| 		expAdded := 0
 | |
| 
 | |
| 		for j := 0; j < max1; {
 | |
| 			r := rand.Intn(max1)
 | |
| 			v := vs[r]
 | |
| 			n1, _, found = Add(n1, v, pof)
 | |
| 			if !found {
 | |
| 				j++
 | |
| 			}
 | |
| 			_, found = m[Label(v)]
 | |
| 			if !found {
 | |
| 				expAdded++
 | |
| 				m[Label(v)] = false
 | |
| 			}
 | |
| 		}
 | |
| 		if i < 6 {
 | |
| 			continue
 | |
| 		}
 | |
| 		expSize := len(m)
 | |
| 		log.Trace(fmt.Sprintf("%v-0: pin: %v, size: %v", i, n0.Pin(), max0))
 | |
| 		log.Trace(fmt.Sprintf("%v-1: pin: %v, size: %v", i, n1.Pin(), max1))
 | |
| 		log.Trace(fmt.Sprintf("%v: merged tree size: %v, newly added: %v", i, expSize, expAdded))
 | |
| 		n, common := Union(n0, n1, pof)
 | |
| 		added := n1.Size() - common
 | |
| 		size := n.Size()
 | |
| 
 | |
| 		if expSize != size {
 | |
| 			t.Fatalf("%v: incorrect number of elements in merged pot, expected %v, got %v\n%v", i, expSize, size, n)
 | |
| 		}
 | |
| 		if expAdded != added {
 | |
| 			t.Fatalf("%v: incorrect number of added elements in merged pot, expected %v, got %v", i, expAdded, added)
 | |
| 		}
 | |
| 		if !checkDuplicates(n) {
 | |
| 			t.Fatalf("%v: merged pot contains duplicates: \n%v", i, n)
 | |
| 		}
 | |
| 		for k := range m {
 | |
| 			_, _, found = Add(n, newTestAddr(k, 0), pof)
 | |
| 			if !found {
 | |
| 				t.Fatalf("%v: merged pot (size:%v, added: %v) missing element %v", i, size, added, k)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPotMergeScale(t *testing.T) {
 | |
| 	for i := 0; i < maxEachNeighbourTests; i++ {
 | |
| 		alen := maxkeylen
 | |
| 		pof := DefaultPof(alen)
 | |
| 		max0 := rand.Intn(maxEachNeighbour) + 1
 | |
| 		max1 := rand.Intn(maxEachNeighbour) + 1
 | |
| 		n0 := NewPot(nil, 0)
 | |
| 		n1 := NewPot(nil, 0)
 | |
| 		log.Trace(fmt.Sprintf("round %v: %v - %v", i, max0, max1))
 | |
| 		m := make(map[string]bool)
 | |
| 		var found bool
 | |
| 		for j := 0; j < max0; {
 | |
| 			v := randomtestAddr(alen, j)
 | |
| 			n0, _, found = Add(n0, v, pof)
 | |
| 			if !found {
 | |
| 				m[Label(v)] = false
 | |
| 				j++
 | |
| 			}
 | |
| 		}
 | |
| 		expAdded := 0
 | |
| 
 | |
| 		for j := 0; j < max1; {
 | |
| 			v := randomtestAddr(alen, j)
 | |
| 			n1, _, found = Add(n1, v, pof)
 | |
| 			if !found {
 | |
| 				j++
 | |
| 			}
 | |
| 			_, found = m[Label(v)]
 | |
| 			if !found {
 | |
| 				expAdded++
 | |
| 				m[Label(v)] = false
 | |
| 			}
 | |
| 		}
 | |
| 		if i < 6 {
 | |
| 			continue
 | |
| 		}
 | |
| 		expSize := len(m)
 | |
| 		log.Trace(fmt.Sprintf("%v-0: pin: %v, size: %v", i, n0.Pin(), max0))
 | |
| 		log.Trace(fmt.Sprintf("%v-1: pin: %v, size: %v", i, n1.Pin(), max1))
 | |
| 		log.Trace(fmt.Sprintf("%v: merged tree size: %v, newly added: %v", i, expSize, expAdded))
 | |
| 		n, common := Union(n0, n1, pof)
 | |
| 		added := n1.Size() - common
 | |
| 		size := n.Size()
 | |
| 
 | |
| 		if expSize != size {
 | |
| 			t.Fatalf("%v: incorrect number of elements in merged pot, expected %v, got %v", i, expSize, size)
 | |
| 		}
 | |
| 		if expAdded != added {
 | |
| 			t.Fatalf("%v: incorrect number of added elements in merged pot, expected %v, got %v", i, expAdded, added)
 | |
| 		}
 | |
| 		if !checkDuplicates(n) {
 | |
| 			t.Fatalf("%v: merged pot contains duplicates", i)
 | |
| 		}
 | |
| 		for k := range m {
 | |
| 			_, _, found = Add(n, newTestAddr(k, 0), pof)
 | |
| 			if !found {
 | |
| 				t.Fatalf("%v: merged pot (size:%v, added: %v) missing element %v", i, size, added, k)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func checkDuplicates(t *Pot) bool {
 | |
| 	po := -1
 | |
| 	for _, c := range t.bins {
 | |
| 		if c == nil {
 | |
| 			return false
 | |
| 		}
 | |
| 		if c.po <= po || !checkDuplicates(c) {
 | |
| 			return false
 | |
| 		}
 | |
| 		po = c.po
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func TestPotEachNeighbourSync(t *testing.T) {
 | |
| 	for i := 0; i < maxEachNeighbourTests; i++ {
 | |
| 		alen := maxkeylen
 | |
| 		pof := DefaultPof(maxkeylen)
 | |
| 		max := rand.Intn(maxEachNeighbour/2) + maxEachNeighbour/2
 | |
| 		pin := randomTestAddr(alen, 0)
 | |
| 		n := NewPot(pin, 0)
 | |
| 		m := make(map[string]bool)
 | |
| 		m[Label(pin)] = false
 | |
| 		for j := 1; j <= max; j++ {
 | |
| 			v := randomTestAddr(alen, j)
 | |
| 			n, _, _ = Add(n, v, pof)
 | |
| 			m[Label(v)] = false
 | |
| 		}
 | |
| 
 | |
| 		size := n.Size()
 | |
| 		if size < 2 {
 | |
| 			continue
 | |
| 		}
 | |
| 		count := rand.Intn(size/2) + size/2
 | |
| 		val := randomTestAddr(alen, max+1)
 | |
| 		log.Trace(fmt.Sprintf("%v: pin: %v, size: %v, val: %v, count: %v", i, n.Pin(), size, val, count))
 | |
| 		err := testPotEachNeighbour(n, pof, val, count, checkPo(val, pof), checkOrder(val), checkValues(m, val))
 | |
| 		if err != nil {
 | |
| 			t.Fatal(err)
 | |
| 		}
 | |
| 		minPoFound := alen
 | |
| 		maxPoNotFound := 0
 | |
| 		for k, found := range m {
 | |
| 			po, _ := pof(val, newTestAddr(k, 0), 0)
 | |
| 			if found {
 | |
| 				if po < minPoFound {
 | |
| 					minPoFound = po
 | |
| 				}
 | |
| 			} else {
 | |
| 				if po > maxPoNotFound {
 | |
| 					maxPoNotFound = po
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		if minPoFound < maxPoNotFound {
 | |
| 			t.Fatalf("incorrect neighbours returned: found one with PO %v < there was one not found with PO %v", minPoFound, maxPoNotFound)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestPotEachNeighbourAsync(t *testing.T) {
 | |
| 	for i := 0; i < maxEachNeighbourTests; i++ {
 | |
| 		max := rand.Intn(maxEachNeighbour/2) + maxEachNeighbour/2
 | |
| 		alen := maxkeylen
 | |
| 		pof := DefaultPof(alen)
 | |
| 		n := NewPot(randomTestAddr(alen, 0), 0)
 | |
| 		size := 1
 | |
| 		var found bool
 | |
| 		for j := 1; j <= max; j++ {
 | |
| 			v := randomTestAddr(alen, j)
 | |
| 			n, _, found = Add(n, v, pof)
 | |
| 			if !found {
 | |
| 				size++
 | |
| 			}
 | |
| 		}
 | |
| 		if size != n.Size() {
 | |
| 			t.Fatal(n)
 | |
| 		}
 | |
| 		if size < 2 {
 | |
| 			continue
 | |
| 		}
 | |
| 		count := rand.Intn(size/2) + size/2
 | |
| 		val := randomTestAddr(alen, max+1)
 | |
| 
 | |
| 		mu := sync.Mutex{}
 | |
| 		m := make(map[string]bool)
 | |
| 		maxPos := rand.Intn(alen)
 | |
| 		log.Trace(fmt.Sprintf("%v: pin: %v, size: %v, val: %v, count: %v, maxPos: %v", i, n.Pin(), size, val, count, maxPos))
 | |
| 		msize := 0
 | |
| 		remember := func(v Val, po int) error {
 | |
| 			if po > maxPos {
 | |
| 				return errNoCount
 | |
| 			}
 | |
| 			m[Label(v)] = true
 | |
| 			msize++
 | |
| 			return nil
 | |
| 		}
 | |
| 		if i == 0 {
 | |
| 			continue
 | |
| 		}
 | |
| 		testPotEachNeighbour(n, pof, val, count, remember)
 | |
| 		d := 0
 | |
| 		forget := func(v Val, po int) {
 | |
| 			mu.Lock()
 | |
| 			defer mu.Unlock()
 | |
| 			d++
 | |
| 			delete(m, Label(v))
 | |
| 		}
 | |
| 
 | |
| 		n.EachNeighbourAsync(val, pof, count, maxPos, forget, true)
 | |
| 		if d != msize {
 | |
| 			t.Fatalf("incorrect number of neighbour calls in async iterator. expected %v, got %v", msize, d)
 | |
| 		}
 | |
| 		if len(m) != 0 {
 | |
| 			t.Fatalf("incorrect neighbour calls in async iterator. %v items missed:\n%v", len(m), n)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func benchmarkEachNeighbourSync(t *testing.B, max, count int, d time.Duration) {
 | |
| 	t.ReportAllocs()
 | |
| 	alen := maxkeylen
 | |
| 	pof := DefaultPof(alen)
 | |
| 	pin := randomTestAddr(alen, 0)
 | |
| 	n := NewPot(pin, 0)
 | |
| 	var found bool
 | |
| 	for j := 1; j <= max; {
 | |
| 		v := randomTestAddr(alen, j)
 | |
| 		n, _, found = Add(n, v, pof)
 | |
| 		if !found {
 | |
| 			j++
 | |
| 		}
 | |
| 	}
 | |
| 	t.ResetTimer()
 | |
| 	for i := 0; i < t.N; i++ {
 | |
| 		val := randomTestAddr(alen, max+1)
 | |
| 		m := 0
 | |
| 		n.EachNeighbour(val, pof, func(v Val, po int) bool {
 | |
| 			time.Sleep(d)
 | |
| 			m++
 | |
| 			return m != count
 | |
| 		})
 | |
| 	}
 | |
| 	t.StopTimer()
 | |
| 	stats := new(runtime.MemStats)
 | |
| 	runtime.ReadMemStats(stats)
 | |
| }
 | |
| 
 | |
| func benchmarkEachNeighbourAsync(t *testing.B, max, count int, d time.Duration) {
 | |
| 	t.ReportAllocs()
 | |
| 	alen := maxkeylen
 | |
| 	pof := DefaultPof(alen)
 | |
| 	pin := randomTestAddr(alen, 0)
 | |
| 	n := NewPot(pin, 0)
 | |
| 	var found bool
 | |
| 	for j := 1; j <= max; {
 | |
| 		v := randomTestAddr(alen, j)
 | |
| 		n, _, found = Add(n, v, pof)
 | |
| 		if !found {
 | |
| 			j++
 | |
| 		}
 | |
| 	}
 | |
| 	t.ResetTimer()
 | |
| 	for i := 0; i < t.N; i++ {
 | |
| 		val := randomTestAddr(alen, max+1)
 | |
| 		n.EachNeighbourAsync(val, pof, count, alen, func(v Val, po int) {
 | |
| 			time.Sleep(d)
 | |
| 		}, true)
 | |
| 	}
 | |
| 	t.StopTimer()
 | |
| 	stats := new(runtime.MemStats)
 | |
| 	runtime.ReadMemStats(stats)
 | |
| }
 | |
| 
 | |
| func BenchmarkEachNeighbourSync_3_1_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 10, 1*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_1_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 10, 1*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_2_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 100, 1*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_2_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 100, 1*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_3_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 1000, 1*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_3_0(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 1000, 1*time.Microsecond)
 | |
| }
 | |
| 
 | |
| func BenchmarkEachNeighbourSync_3_1_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 10, 2*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_1_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 10, 2*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_2_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 100, 2*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_2_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 100, 2*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_3_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 1000, 2*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_3_1(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 1000, 2*time.Microsecond)
 | |
| }
 | |
| 
 | |
| func BenchmarkEachNeighbourSync_3_1_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 10, 4*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_1_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 10, 4*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_2_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 100, 4*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_2_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 100, 4*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_3_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 1000, 4*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_3_2(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 1000, 4*time.Microsecond)
 | |
| }
 | |
| 
 | |
| func BenchmarkEachNeighbourSync_3_1_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 10, 8*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_1_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 10, 8*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_2_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 100, 8*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_2_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 100, 8*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_3_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 1000, 8*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_3_3(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 1000, 8*time.Microsecond)
 | |
| }
 | |
| 
 | |
| func BenchmarkEachNeighbourSync_3_1_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 10, 16*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_1_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 10, 16*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_2_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 100, 16*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_2_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 100, 16*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighbourSync_3_3_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourSync(t, 1000, 1000, 16*time.Microsecond)
 | |
| }
 | |
| func BenchmarkEachNeighboursAsync_3_3_4(t *testing.B) {
 | |
| 	benchmarkEachNeighbourAsync(t, 1000, 1000, 16*time.Microsecond)
 | |
| }
 |