Source File
bdp_estimator.go
Belonging Package
google.golang.org/grpc/internal/transport
/*** Copyright 2017 gRPC authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.**/package transportimport ()const (// bdpLimit is the maximum value the flow control windows will be increased// to. TCP typically limits this to 4MB, but some systems go up to 16MB.// Since this is only a limit, it is safe to make it optimistic.bdpLimit = (1 << 20) * 16// alpha is a constant factor used to keep a moving average// of RTTs.alpha = 0.9// If the current bdp sample is greater than or equal to// our beta * our estimated bdp and the current bandwidth// sample is the maximum bandwidth observed so far, we// increase our bbp estimate by a factor of gamma.beta = 0.66// To put our bdp to be smaller than or equal to twice the real BDP,// we should multiply our current sample with 4/3, however to round things out// we use 2 as the multiplication factor.gamma = 2)// Adding arbitrary data to ping so that its ack can be identified.// Easter-egg: what does the ping message say?var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}type bdpEstimator struct {// sentAt is the time when the ping was sent.sentAt time.Timemu sync.Mutex// bdp is the current bdp estimate.bdp uint32// sample is the number of bytes received in one measurement cycle.sample uint32// bwMax is the maximum bandwidth noted so far (bytes/sec).bwMax float64// bool to keep track of the beginning of a new measurement cycle.isSent bool// Callback to update the window sizes.updateFlowControl func(n uint32)// sampleCount is the number of samples taken so far.sampleCount uint64// round trip time (seconds)rtt float64}// timesnap registers the time bdp ping was sent out so that// network rtt can be calculated when its ack is received.// It is called (by controller) when the bdpPing is// being written on the wire.func ( *bdpEstimator) ( [8]byte) {if bdpPing.data != {return}.sentAt = time.Now()}// add adds bytes to the current sample for calculating bdp.// It returns true only if a ping must be sent. This can be used// by the caller (handleData) to make decision about batching// a window update with it.func ( *bdpEstimator) ( uint32) bool {.mu.Lock()defer .mu.Unlock()if .bdp == bdpLimit {return false}if !.isSent {.isSent = true.sample =.sentAt = time.Time{}.sampleCount++return true}.sample +=return false}// calculate is called when an ack for a bdp ping is received.// Here we calculate the current bdp and bandwidth sample and// decide if the flow control windows should go up.func ( *bdpEstimator) ( [8]byte) {// Check if the ping acked for was the bdp ping.if bdpPing.data != {return}.mu.Lock():= time.Since(.sentAt).Seconds()if .sampleCount < 10 {// Bootstrap rtt with an average of first 10 rtt samples..rtt += ( - .rtt) / float64(.sampleCount)} else {// Heed to the recent past more..rtt += ( - .rtt) * float64(alpha)}.isSent = false// The number of bytes accumulated so far in the sample is smaller// than or equal to 1.5 times the real BDP on a saturated connection.:= float64(.sample) / (.rtt * float64(1.5))if > .bwMax {.bwMax =}// If the current sample (which is smaller than or equal to the 1.5 times the real BDP) is// greater than or equal to 2/3rd our perceived bdp AND this is the maximum bandwidth seen so far, we// should update our perception of the network BDP.if float64(.sample) >= beta*float64(.bdp) && == .bwMax && .bdp != bdpLimit {:= float64(.sample).bdp = uint32(gamma * )if .bdp > bdpLimit {.bdp = bdpLimit}:= .bdp.mu.Unlock().updateFlowControl()return}.mu.Unlock()}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)