From 8c841a05fb1acbcfce8a50aeba4fdf60bdbfa13d Mon Sep 17 00:00:00 2001 From: Darien Raymond Date: Sat, 25 Aug 2018 10:41:39 +0200 Subject: [PATCH] use readv reader by default --- common/buf/io.go | 15 +++++++++- common/buf/io_highend.go | 23 -------------- common/buf/io_lowend.go | 13 -------- common/buf/reader.go | 61 -------------------------------------- common/buf/reader_test.go | 32 ++------------------ common/buf/readv_reader.go | 7 ++++- 6 files changed, 22 insertions(+), 129 deletions(-) delete mode 100644 common/buf/io_highend.go delete mode 100644 common/buf/io_lowend.go diff --git a/common/buf/io.go b/common/buf/io.go index 182b61ed..5527529a 100644 --- a/common/buf/io.go +++ b/common/buf/io.go @@ -59,7 +59,20 @@ func NewReader(reader io.Reader) Reader { return mr } - return newReaderPlatform(reader) + if useReadv { + if sc, ok := reader.(syscall.Conn); ok { + rawConn, err := sc.SyscallConn() + if err != nil { + newError("failed to get sysconn").Base(err).WriteToLog() + } else { + return NewReadVReader(reader, rawConn) + } + } + } + + return &SingleReader{ + Reader: reader, + } } // NewWriter creates a new Writer. diff --git a/common/buf/io_highend.go b/common/buf/io_highend.go deleted file mode 100644 index b461690d..00000000 --- a/common/buf/io_highend.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build 386 amd64 s390 s390x - -package buf - -import ( - "io" - "syscall" -) - -func newReaderPlatform(reader io.Reader) Reader { - if useReadv { - if sc, ok := reader.(syscall.Conn); ok { - rawConn, err := sc.SyscallConn() - if err != nil { - newError("failed to get sysconn").Base(err).WriteToLog() - } else { - return NewReadVReader(reader, rawConn) - } - } - } - - return NewBytesToBufferReader(reader) -} diff --git a/common/buf/io_lowend.go b/common/buf/io_lowend.go deleted file mode 100644 index 83ab8f38..00000000 --- a/common/buf/io_lowend.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build mips mipsle mips64 mips64le arm arm64 - -package buf - -import ( - "io" -) - -func newReaderPlatform(reader io.Reader) Reader { - return &SingleReader{ - Reader: reader, - } -} diff --git a/common/buf/reader.go b/common/buf/reader.go index 49e37bab..833fcda5 100644 --- a/common/buf/reader.go +++ b/common/buf/reader.go @@ -4,7 +4,6 @@ import ( "io" "v2ray.com/core/common" - "v2ray.com/core/common/bytespool" "v2ray.com/core/common/errors" ) @@ -24,66 +23,6 @@ func readOne(r io.Reader) (*Buffer, error) { return nil, newError("Reader returns too many empty payloads.") } -const largeSize = 128 * 1024 - -// BytesToBufferReader is a Reader that adjusts its reading speed automatically. -type BytesToBufferReader struct { - io.Reader - buffer []byte -} - -// NewBytesToBufferReader returns a new BytesToBufferReader. -func NewBytesToBufferReader(reader io.Reader) Reader { - return &BytesToBufferReader{ - Reader: reader, - } -} - -func (r *BytesToBufferReader) readSmall() (MultiBuffer, error) { - b, err := readOne(r.Reader) - if err != nil { - return nil, err - } - if b.IsFull() && largeSize > Size { - r.buffer = bytespool.Alloc(Size + 100) - } - return NewMultiBufferValue(b), nil -} - -func (r *BytesToBufferReader) freeBuffer() { - bytespool.Free(r.buffer) - r.buffer = nil -} - -// ReadMultiBuffer implements Reader. -func (r *BytesToBufferReader) ReadMultiBuffer() (MultiBuffer, error) { - if r.buffer == nil || largeSize == Size { - return r.readSmall() - } - - nBytes, err := r.Reader.Read(r.buffer) - if nBytes > 0 { - mb := NewMultiBufferCap(int32(nBytes/Size) + 1) - common.Must2(mb.Write(r.buffer[:nBytes])) - if nBytes == len(r.buffer) && nBytes < int(largeSize) { - bytespool.Free(r.buffer) - r.buffer = bytespool.Alloc(int32(nBytes) + 100) - } else if nBytes < Size { - r.freeBuffer() - } - return mb, nil - } - - r.freeBuffer() - - if err != nil { - return nil, err - } - - // Read() returns empty payload and nil err. We don't expect this to happen, but just in case. - return r.readSmall() -} - // BufferedReader is a Reader that keeps its internal buffer. type BufferedReader struct { // Reader is the underlying reader to be read from diff --git a/common/buf/reader_test.go b/common/buf/reader_test.go index 64da6376..df383410 100644 --- a/common/buf/reader_test.go +++ b/common/buf/reader_test.go @@ -1,9 +1,7 @@ package buf_test import ( - "bytes" "io" - "runtime" "testing" . "v2ray.com/core/common/buf" @@ -11,32 +9,6 @@ import ( . "v2ray.com/ext/assert" ) -func TestAdaptiveReader(t *testing.T) { - if runtime.GOARCH != "amd64" { - t.Skip("Smart reader only works on highend devices.") - return - } - - assert := With(t) - - reader := NewReader(bytes.NewReader(make([]byte, 1024*1024))) - b, err := reader.ReadMultiBuffer() - assert(err, IsNil) - assert(b.Len(), Equals, int32(Size)) - - b, err = reader.ReadMultiBuffer() - assert(err, IsNil) - assert(b.Len(), Equals, int32(8*1024)) - - b, err = reader.ReadMultiBuffer() - assert(err, IsNil) - assert(b.Len(), Equals, int32(32*1024)) - - b, err = reader.ReadMultiBuffer() - assert(err, IsNil) - assert(b.Len(), Equals, int32(128*1024)) -} - func TestBytesReaderWriteTo(t *testing.T) { assert := With(t) @@ -87,8 +59,8 @@ func TestBytesReaderMultiBuffer(t *testing.T) { func TestReaderInterface(t *testing.T) { assert := With(t) - assert((*BytesToBufferReader)(nil), Implements, (*io.Reader)(nil)) - assert((*BytesToBufferReader)(nil), Implements, (*Reader)(nil)) + assert((*ReadVReader)(nil), Implements, (*io.Reader)(nil)) + assert((*ReadVReader)(nil), Implements, (*Reader)(nil)) assert((*BufferedReader)(nil), Implements, (*Reader)(nil)) assert((*BufferedReader)(nil), Implements, (*io.Reader)(nil)) diff --git a/common/buf/readv_reader.go b/common/buf/readv_reader.go index 1d266e2e..d4c6617a 100644 --- a/common/buf/readv_reader.go +++ b/common/buf/readv_reader.go @@ -140,7 +140,12 @@ var useReadv = false func init() { const defaultFlagValue = "NOT_DEFINED_AT_ALL" value := platform.NewEnvFlag("v2ray.buf.readv").GetValue(func() string { return defaultFlagValue }) - if value != defaultFlagValue && (runtime.GOOS == "linux" || runtime.GOOS == "darwin") { + switch value { + case defaultFlagValue, "auto": + if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin") { + useReadv = true + } + case "enable": useReadv = true } }