fine bandwidth calculation, fix slide window calculated size too large, fix #330

This commit is contained in:
ffdfgdfg 2019-12-27 00:32:40 +08:00
parent 258be8e67a
commit 076fc8b2e1
4 changed files with 70 additions and 10 deletions

View File

@ -246,6 +246,15 @@ func (Self *MuxPackager) UnPack(reader io.Reader) (n uint16, err error) {
return return
} }
func (Self *MuxPackager) reset() {
Self.Id = 0
Self.Flag = 0
Self.Length = 0
Self.Content = nil
Self.ReadLength = 0
Self.Window = 0
}
const ( const (
ipV4 = 1 ipV4 = 1
domainName = 3 domainName = 3

View File

@ -93,18 +93,20 @@ type windowBufferPool struct {
func (Self *windowBufferPool) New() { func (Self *windowBufferPool) New() {
Self.pool = sync.Pool{ Self.pool = sync.Pool{
New: func() interface{} { New: func() interface{} {
return make([]byte, PoolSizeWindow, PoolSizeWindow) return make([]byte, PoolSizeWindow)
}, },
} }
} }
func (Self *windowBufferPool) Get() (buf []byte) { func (Self *windowBufferPool) Get() (buf []byte) {
buf = Self.pool.Get().([]byte) buf = Self.pool.Get().([]byte)
return buf[:PoolSizeWindow] buf = buf[:PoolSizeWindow]
return buf
} }
func (Self *windowBufferPool) Put(x []byte) { func (Self *windowBufferPool) Put(x []byte) {
Self.pool.Put(x[:PoolSizeWindow]) // make buf to full x = x[:0] // clean buf
Self.pool.Put(x)
} }
type bufferPool struct { type bufferPool struct {
@ -146,6 +148,7 @@ func (Self *muxPackagerPool) Get() *MuxPackager {
} }
func (Self *muxPackagerPool) Put(pack *MuxPackager) { func (Self *muxPackagerPool) Put(pack *MuxPackager) {
pack.reset()
Self.pool.Put(pack) Self.pool.Put(pack)
} }

View File

@ -2,6 +2,7 @@ package mux
import ( import (
"errors" "errors"
"github.com/astaxie/beego/logs"
"io" "io"
"math" "math"
"net" "net"
@ -215,10 +216,10 @@ func (Self *ReceiveWindow) calcSize() {
if n < common.MAXIMUM_SEGMENT_SIZE*10 { if n < common.MAXIMUM_SEGMENT_SIZE*10 {
n = common.MAXIMUM_SEGMENT_SIZE * 10 n = common.MAXIMUM_SEGMENT_SIZE * 10
} }
bufLen := Self.bufQueue.Len() //bufLen := Self.bufQueue.Len()
if n < bufLen { //if n < bufLen {
n = bufLen // n = bufLen
} //}
if n < Self.maxSize/2 { if n < Self.maxSize/2 {
n = Self.maxSize / 2 n = Self.maxSize / 2
} }
@ -227,6 +228,7 @@ func (Self *ReceiveWindow) calcSize() {
n = 2 * Self.maxSize n = 2 * Self.maxSize
} }
if n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) { if n > (common.MAXIMUM_WINDOW_SIZE / uint32(conns)) {
logs.Warn("window too large", n)
n = common.MAXIMUM_WINDOW_SIZE / uint32(conns) n = common.MAXIMUM_WINDOW_SIZE / uint32(conns)
} }
// set the maximum size // set the maximum size

View File

@ -5,7 +5,9 @@ import (
"io" "io"
"math" "math"
"net" "net"
"os"
"sync/atomic" "sync/atomic"
"syscall"
"time" "time"
"github.com/astaxie/beego/logs" "github.com/astaxie/beego/logs"
@ -35,13 +37,17 @@ func NewMux(c net.Conn, connType string) *Mux {
//c.(*net.TCPConn).SetReadBuffer(0) //c.(*net.TCPConn).SetReadBuffer(0)
//c.(*net.TCPConn).SetWriteBuffer(0) //c.(*net.TCPConn).SetWriteBuffer(0)
_ = c.SetDeadline(time.Time{}) _ = c.SetDeadline(time.Time{})
fd, err := getConnFd(c)
if err != nil {
logs.Warn(err)
}
m := &Mux{ m := &Mux{
conn: c, conn: c,
connMap: NewConnMap(), connMap: NewConnMap(),
id: 0, id: 0,
closeChan: make(chan struct{}, 1), closeChan: make(chan struct{}, 1),
newConnCh: make(chan *conn), newConnCh: make(chan *conn),
bw: new(bandwidth), bw: NewBandwidth(fd),
IsClose: false, IsClose: false,
connType: connType, connType: connType,
pingCh: make(chan []byte), pingCh: make(chan []byte),
@ -58,6 +64,26 @@ func NewMux(c net.Conn, connType string) *Mux {
return m return m
} }
func getConnFd(c net.Conn) (fd *os.File, err error) {
switch c.(type) {
case *net.TCPConn:
fd, err = c.(*net.TCPConn).File()
if err != nil {
return
}
return
case *net.UDPConn:
fd, err = c.(*net.UDPConn).File()
if err != nil {
return
}
return
default:
err = errors.New("mux:unknown conn type, only tcp or kcp")
return
}
}
func (s *Mux) NewConn() (*conn, error) { func (s *Mux) NewConn() (*conn, error) {
if s.IsClose { if s.IsClose {
return nil, errors.New("the mux has closed") return nil, errors.New("the mux has closed")
@ -392,13 +418,19 @@ type bandwidth struct {
readStart time.Time readStart time.Time
lastReadStart time.Time lastReadStart time.Time
bufLength uint32 bufLength uint32
fd *os.File
calcThreshold uint32
}
func NewBandwidth(fd *os.File) *bandwidth {
return &bandwidth{fd: fd}
} }
func (Self *bandwidth) StartRead() { func (Self *bandwidth) StartRead() {
if Self.readStart.IsZero() { if Self.readStart.IsZero() {
Self.readStart = time.Now() Self.readStart = time.Now()
} }
if Self.bufLength >= common.MAXIMUM_SEGMENT_SIZE*300 { if Self.bufLength >= Self.calcThreshold {
Self.lastReadStart, Self.readStart = Self.readStart, time.Now() Self.lastReadStart, Self.readStart = Self.readStart, time.Now()
Self.calcBandWidth() Self.calcBandWidth()
} }
@ -410,7 +442,21 @@ func (Self *bandwidth) SetCopySize(n uint16) {
func (Self *bandwidth) calcBandWidth() { func (Self *bandwidth) calcBandWidth() {
t := Self.readStart.Sub(Self.lastReadStart) t := Self.readStart.Sub(Self.lastReadStart)
bufferSize, err := syscall.GetsockoptInt(int(Self.fd.Fd()), syscall.SOL_SOCKET, syscall.SO_RCVBUF)
//logs.Warn(bufferSize)
if err != nil {
logs.Warn(err)
Self.bufLength = 0
return
}
if Self.bufLength >= uint32(bufferSize) {
atomic.StoreUint64(&Self.readBandwidth, math.Float64bits(float64(Self.bufLength)/t.Seconds())) atomic.StoreUint64(&Self.readBandwidth, math.Float64bits(float64(Self.bufLength)/t.Seconds()))
// calculate the hole socket buffer, the time meaning to fill the buffer
//logs.Warn(Self.Get())
} else {
Self.calcThreshold = uint32(bufferSize)
}
// socket buffer size is bigger than bufLength, so we don't calculate it
Self.bufLength = 0 Self.bufLength = 0
} }