From 5255d200546c87c990e0767de66f05c2fb541798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Fri, 3 Jun 2016 14:06:39 +0300 Subject: [PATCH] eth/downloader: use median RTT as the default for new peers --- eth/downloader/downloader.go | 20 ++------------------ eth/downloader/peer.go | 28 ++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 542934f963..37cb04e05d 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -1878,24 +1878,8 @@ func (d *Downloader) deliver(id string, destCh chan dataPack, packet dataPack, i // peer latency statistics and updates the estimated request round trip time. func (d *Downloader) qosTuner() { for atomic.LoadInt32(&d.interrupt) == 0 { - // Gather all the active RTTs and set the target RTT to the median - rtts := d.peers.RTTs() - - var rtt time.Duration - if qosTuningPeers <= len(rtts) { - rtt = rtts[qosTuningPeers/2] // Median of our tuning peers - } else if len(rtts) > 0 { - rtt = rtts[len(rtts)/2] // Median of our connected peers (maintain even like this some baseline qos) - } else { - rtt = rttMaxEstimate // No peers, reset to some sane default - } - if rtt < rttMinEstimate { - rtt = rttMinEstimate - } - if rtt > rttMaxEstimate { - rtt = rttMaxEstimate - } - rtt = time.Duration(float64(1-qosTuningImpact)*float64(atomic.LoadUint64(&d.rttEstimate)) + qosTuningImpact*float64(rtt)) + // Retrieve the current median RTT and integrate into the previoust target RTT + rtt := time.Duration(float64(1-qosTuningImpact)*float64(atomic.LoadUint64(&d.rttEstimate)) + qosTuningImpact*float64(d.peers.medianRTT())) atomic.StoreUint64(&d.rttEstimate, uint64(rtt)) // A new RTT cycle passed, increase our confidence in the estimated RTT diff --git a/eth/downloader/peer.go b/eth/downloader/peer.go index a538cad886..57f7e008ad 100644 --- a/eth/downloader/peer.go +++ b/eth/downloader/peer.go @@ -409,6 +409,10 @@ func (ps *peerSet) Reset() { // average of all existing peers, to give it a realistic chance of being used // for data retrievals. func (ps *peerSet) Register(p *peer) error { + // Retrieve the current median RTT as a sane default + p.rtt = ps.medianRTT() + + // Register the new peer with some meaningful defaults ps.lock.Lock() defer ps.lock.Unlock() @@ -417,7 +421,6 @@ func (ps *peerSet) Register(p *peer) error { } if len(ps.peers) > 0 { p.headerThroughput, p.blockThroughput, p.receiptThroughput, p.stateThroughput = 0, 0, 0, 0 - p.rtt = rttMaxEstimate for _, peer := range ps.peers { peer.lock.RLock() @@ -573,9 +576,9 @@ func (ps *peerSet) idlePeers(minProtocol, maxProtocol int, idleCheck func(*peer) return idle, total } -// RTTs retrieves all the round trip times measured for the current set of peers, -// sorted ascending. -func (ps *peerSet) RTTs() []time.Duration { +// medianRTT returns the median RTT of te peerset, considering only the tuning +// peers if there are more peers available. +func (ps *peerSet) medianRTT() time.Duration { // Gather all the currnetly measured round trip times ps.lock.RLock() defer ps.lock.RUnlock() @@ -586,7 +589,7 @@ func (ps *peerSet) RTTs() []time.Duration { rtts = append(rtts, p.rtt) p.lock.RUnlock() } - // Sort into ascending order and return them + // Sort into ascending order and retrieve the median for i := 0; i < len(rtts); i++ { for j := i + 1; j < len(rtts); j++ { if rtts[i] > rtts[j] { @@ -594,5 +597,18 @@ func (ps *peerSet) RTTs() []time.Duration { } } } - return rtts + median := rttMaxEstimate + if qosTuningPeers <= len(rtts) { + median = rtts[qosTuningPeers/2] // Median of our tuning peers + } else if len(rtts) > 0 { + median = rtts[len(rtts)/2] // Median of our connected peers (maintain even like this some baseline qos) + } + // Restrict the RTT into some QoS defaults, irrelevant of true RTT + if median < rttMinEstimate { + median = rttMinEstimate + } + if median > rttMaxEstimate { + median = rttMaxEstimate + } + return median }