From ced8a7b78f31595bd74b78a9b5f31c8f934f343a Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Thu, 11 Sep 2014 20:31:31 +1000 Subject: [PATCH] New worst conns algorithm that takes into account connection useful chunk hit rate --- torrent.go | 11 ++++------- torrent_test.go | 9 +++++++++ worst_conns.go | 40 ++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/torrent.go b/torrent.go index 8274091c..5d6b66b7 100644 --- a/torrent.go +++ b/torrent.go @@ -69,10 +69,9 @@ type torrent struct { metadataHave []bool } -func (t *torrent) worstConnsHeap() (wcs *worstConnsHeap) { - wcs = new(worstConnsHeap) - *wcs = make([]*connection, 0, len(t.Conns)) - *wcs = append(*wcs, t.Conns...) +func (t *torrent) worstConnsHeap() (wcs *worstConns) { + wcs = new(worstConns) + *wcs = append([]*connection{}, t.Conns...) heap.Init(wcs) return } @@ -293,9 +292,7 @@ func (t *torrent) WriteStatus(w io.Writer) { fmt.Fprintln(w) fmt.Fprintf(w, "Pending peers: %d\n", len(t.Peers)) fmt.Fprintf(w, "Active peers: %d\n", len(t.Conns)) - wcs := new(worstConnsHeap) - *wcs = t.Conns - sort.Sort(wcs) + sort.Sort(worstConns(t.Conns)) for _, c := range t.Conns { c.WriteStatus(w) } diff --git a/torrent_test.go b/torrent_test.go index 18306ecf..302a9751 100644 --- a/torrent_test.go +++ b/torrent_test.go @@ -58,3 +58,12 @@ func TestTorrentDoubleClose(t *testing.T) { } wg.Wait() } + +func TestAppendToCopySlice(t *testing.T) { + orig := []int{1, 2, 3} + dupe := append([]int{}, orig...) + dupe[0] = 4 + if orig[0] != 1 { + t.FailNow() + } +} diff --git a/worst_conns.go b/worst_conns.go index 37037cb6..a1bf326b 100644 --- a/worst_conns.go +++ b/worst_conns.go @@ -4,27 +4,13 @@ import ( "time" ) -type worstConnsHeap []*connection +// Implements heap functions such that [0] is the worst connection. +type worstConns []*connection -func (me worstConnsHeap) Len() int { return len(me) } -func (me worstConnsHeap) Swap(i, j int) { me[i], me[j] = me[j], me[i] } -func (me worstConnsHeap) last(c *connection) (ret time.Time) { - ret = c.lastUsefulChunkReceived - if !ret.IsZero() { - return - } - ret = c.completedHandshake - if time.Now().Sub(ret) >= 3*time.Minute { - return - } - ret = time.Now().Add(-3 * time.Minute) - return -} -func (me worstConnsHeap) Less(i, j int) bool { - return me.last(me[i]).Before(me.last(me[j])) -} +func (me worstConns) Len() int { return len(me) } +func (me worstConns) Swap(i, j int) { me[i], me[j] = me[j], me[i] } -func (me *worstConnsHeap) Pop() (ret interface{}) { +func (me *worstConns) Pop() (ret interface{}) { old := *me n := len(old) ret = old[n-1] @@ -32,6 +18,20 @@ func (me *worstConnsHeap) Pop() (ret interface{}) { return } -func (me *worstConnsHeap) Push(x interface{}) { +func (me *worstConns) Push(x interface{}) { *me = append(*me, x.(*connection)) } + +func (me worstConns) key(i int) (ret time.Duration) { + c := me[i] + return time.Duration(1+c.UnwantedChunksReceived) * time.Now().Sub(func() time.Time { + if !c.lastUsefulChunkReceived.IsZero() { + return c.lastUsefulChunkReceived + } + return c.completedHandshake.Add(-time.Minute) + }()) / time.Duration(1+c.UsefulChunksReceived) +} + +func (me worstConns) Less(i, j int) bool { + return me.key(i) > me.key(j) +} -- 2.44.0