|  | @@ -1,64 +1,84 @@
 | 
	
		
			
				|  |  | -// +build !windows
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  package buf
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  |  	"io"
 | 
	
		
			
				|  |  |  	"runtime"
 | 
	
		
			
				|  |  |  	"syscall"
 | 
	
		
			
				|  |  | -	"unsafe"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	"v2ray.com/core/common/platform"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +type allocStrategy struct {
 | 
	
		
			
				|  |  | +	current uint32
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *allocStrategy) Current() uint32 {
 | 
	
		
			
				|  |  | +	return s.current
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *allocStrategy) Adjust(n uint32) {
 | 
	
		
			
				|  |  | +	if n >= s.current {
 | 
	
		
			
				|  |  | +		s.current *= 4
 | 
	
		
			
				|  |  | +	} else {
 | 
	
		
			
				|  |  | +		s.current = n
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if s.current > 32 {
 | 
	
		
			
				|  |  | +		s.current = 32
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if s.current == 0 {
 | 
	
		
			
				|  |  | +		s.current = 1
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +func (s *allocStrategy) Alloc() []*Buffer {
 | 
	
		
			
				|  |  | +	bs := make([]*Buffer, s.current)
 | 
	
		
			
				|  |  | +	for i := range bs {
 | 
	
		
			
				|  |  | +		bs[i] = New()
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return bs
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +type multiReader interface {
 | 
	
		
			
				|  |  | +	Init([]*Buffer)
 | 
	
		
			
				|  |  | +	Read(fd uintptr) int32
 | 
	
		
			
				|  |  | +	Clear()
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  type ReadVReader struct {
 | 
	
		
			
				|  |  |  	io.Reader
 | 
	
		
			
				|  |  |  	rawConn syscall.RawConn
 | 
	
		
			
				|  |  | -	iovects []syscall.Iovec
 | 
	
		
			
				|  |  | -	nBuf    int32
 | 
	
		
			
				|  |  | +	mr      multiReader
 | 
	
		
			
				|  |  | +	alloc   allocStrategy
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) *ReadVReader {
 | 
	
		
			
				|  |  |  	return &ReadVReader{
 | 
	
		
			
				|  |  |  		Reader:  reader,
 | 
	
		
			
				|  |  |  		rawConn: rawConn,
 | 
	
		
			
				|  |  | -		nBuf:    1,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func allocN(n int32) []*Buffer {
 | 
	
		
			
				|  |  | -	bs := make([]*Buffer, 0, n)
 | 
	
		
			
				|  |  | -	for i := int32(0); i < n; i++ {
 | 
	
		
			
				|  |  | -		bs = append(bs, New())
 | 
	
		
			
				|  |  | +		alloc: allocStrategy{
 | 
	
		
			
				|  |  | +			current: 1,
 | 
	
		
			
				|  |  | +		},
 | 
	
		
			
				|  |  | +		mr: newMultiReader(),
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	return bs
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  func (r *ReadVReader) readMulti() (MultiBuffer, error) {
 | 
	
		
			
				|  |  | -	bs := allocN(r.nBuf)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	var iovecs []syscall.Iovec
 | 
	
		
			
				|  |  | -	if r.iovects != nil {
 | 
	
		
			
				|  |  | -		iovecs = r.iovects
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	for idx, b := range bs {
 | 
	
		
			
				|  |  | -		iovecs = append(iovecs, syscall.Iovec{
 | 
	
		
			
				|  |  | -			Base: &(b.v[0]),
 | 
	
		
			
				|  |  | -		})
 | 
	
		
			
				|  |  | -		iovecs[idx].SetLen(int(Size))
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	r.iovects = iovecs[:0]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	var nBytes int
 | 
	
		
			
				|  |  | +	bs := r.alloc.Alloc()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	r.mr.Init(bs)
 | 
	
		
			
				|  |  | +	var nBytes int32
 | 
	
		
			
				|  |  |  	err := r.rawConn.Read(func(fd uintptr) bool {
 | 
	
		
			
				|  |  | -		n, _, e := syscall.Syscall(syscall.SYS_READV, fd, uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs)))
 | 
	
		
			
				|  |  | -		if e != 0 {
 | 
	
		
			
				|  |  | +		n := r.mr.Read(fd)
 | 
	
		
			
				|  |  | +		if n < 0 {
 | 
	
		
			
				|  |  |  			return false
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		nBytes = int(n)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		nBytes = n
 | 
	
		
			
				|  |  |  		return true
 | 
	
		
			
				|  |  |  	})
 | 
	
		
			
				|  |  | +	r.mr.Clear()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		mb := MultiBuffer(bs)
 | 
	
	
		
			
				|  | @@ -82,7 +102,7 @@ func (r *ReadVReader) readMulti() (MultiBuffer, error) {
 | 
	
		
			
				|  |  |  			end = Size
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		bs[nBuf].end = end
 | 
	
		
			
				|  |  | -		nBytes -= int(end)
 | 
	
		
			
				|  |  | +		nBytes -= end
 | 
	
		
			
				|  |  |  		nBuf++
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -96,13 +116,13 @@ func (r *ReadVReader) readMulti() (MultiBuffer, error) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // ReadMultiBuffer implements Reader.
 | 
	
		
			
				|  |  |  func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
 | 
	
		
			
				|  |  | -	if r.nBuf == 1 {
 | 
	
		
			
				|  |  | +	if r.alloc.Current() == 1 {
 | 
	
		
			
				|  |  |  		b, err := readOne(r.Reader)
 | 
	
		
			
				|  |  |  		if err != nil {
 | 
	
		
			
				|  |  |  			return nil, err
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		if b.IsFull() {
 | 
	
		
			
				|  |  | -			r.nBuf = 2
 | 
	
		
			
				|  |  | +			r.alloc.Adjust(1)
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  		return NewMultiBufferValue(b), nil
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -111,12 +131,7 @@ func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  |  		return nil, err
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	nBuf := int32(len(mb))
 | 
	
		
			
				|  |  | -	if nBuf < r.nBuf {
 | 
	
		
			
				|  |  | -		r.nBuf = nBuf
 | 
	
		
			
				|  |  | -	} else if nBuf == r.nBuf && r.nBuf < 16 {
 | 
	
		
			
				|  |  | -		r.nBuf *= 4
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	r.alloc.Adjust(uint32(len(mb)))
 | 
	
		
			
				|  |  |  	return mb, nil
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |