diff --git a/common/alloc/buffer.go b/common/alloc/buffer.go index 9f4be27fc..eddccdf08 100644 --- a/common/alloc/buffer.go +++ b/common/alloc/buffer.go @@ -205,18 +205,9 @@ func NewBuffer() *Buffer { return mediumPool.Allocate() } -// NewLargeBuffer creates a Buffer with 64K bytes of arbitrary content. -//func NewLargeBuffer() *Buffer { -// return largePool.Allocate() -//} - -//func NewBufferWithSize(size int) *Buffer { -// if size <= BufferSize { -// return NewBuffer() -// } -// -// return NewLargeBuffer() -//} +func NewSmallBuffer() *Buffer { + return smallPool.Allocate() +} func NewLocalBuffer(size int) *Buffer { return CreateBuffer(make([]byte, size), nil) diff --git a/common/alloc/buffer_pool.go b/common/alloc/buffer_pool.go index 808e32bd2..4a2d64481 100644 --- a/common/alloc/buffer_pool.go +++ b/common/alloc/buffer_pool.go @@ -11,6 +11,31 @@ type Pool interface { Free(*Buffer) } +type SyncPool struct { + allocator *sync.Pool +} + +func NewSyncPool(bufferSize uint32) *SyncPool { + pool := &SyncPool{ + allocator: &sync.Pool{ + New: func() interface{} { return make([]byte, bufferSize) }, + }, + } + return pool +} + +func (p *SyncPool) Allocate() *Buffer { + return CreateBuffer(p.allocator.Get().([]byte), p) +} + +func (p *SyncPool) Free(buffer *Buffer) { + rawBuffer := buffer.head + if rawBuffer == nil { + return + } + p.allocator.Put(rawBuffer) +} + type BufferPool struct { chain chan []byte allocator *sync.Pool @@ -55,14 +80,15 @@ const ( mediumBufferByteSize = 8 * 1024 BufferSize = mediumBufferByteSize - defaultOffset - largeBufferByteSize = 64 * 1024 - LargeBufferSize = largeBufferByteSize - defaultOffset + smallBufferByteSize = 2 * 1024 + SmallBufferSize = smallBufferByteSize - defaultOffset PoolSizeEnvKey = "v2ray.buffer.size" ) var ( mediumPool *BufferPool + smallPool = NewSyncPool(2048) ) func init() { diff --git a/common/alloc/buffer_test.go b/common/alloc/buffer_test.go index 4198028b7..4d3ed2787 100644 --- a/common/alloc/buffer_test.go +++ b/common/alloc/buffer_test.go @@ -58,3 +58,31 @@ func TestBufferString(t *testing.T) { buffer.AppendString("Test String") assert.String(buffer.String()).Equals("Test String") } + +func BenchmarkNewBuffer8192(b *testing.B) { + for i := 0; i < b.N; i++ { + buffer := NewBuffer() + buffer.Release() + } +} + +func BenchmarkNewLocalBuffer8192(b *testing.B) { + for i := 0; i < b.N; i++ { + buffer := NewLocalBuffer(8192) + buffer.Release() + } +} + +func BenchmarkNewBuffer2048(b *testing.B) { + for i := 0; i < b.N; i++ { + buffer := NewSmallBuffer() + buffer.Release() + } +} + +func BenchmarkNewLocalBuffer2048(b *testing.B) { + for i := 0; i < b.N; i++ { + buffer := NewLocalBuffer(2048) + buffer.Release() + } +} diff --git a/proxy/shadowsocks/protocol.go b/proxy/shadowsocks/protocol.go index a54585ec3..e41f1cbd0 100644 --- a/proxy/shadowsocks/protocol.go +++ b/proxy/shadowsocks/protocol.go @@ -240,7 +240,7 @@ func EncodeUDPPacket(request *protocol.RequestHeader, payload *alloc.Buffer) (*a } account := rawAccount.(*ShadowsocksAccount) - buffer := alloc.NewLocalBuffer(2048) + buffer := alloc.NewSmallBuffer() ivLen := account.Cipher.IVSize() buffer.Slice(0, ivLen) rand.Read(buffer.Value) @@ -349,7 +349,7 @@ type UDPReader struct { } func (this *UDPReader) Read() (*alloc.Buffer, error) { - buffer := alloc.NewLocalBuffer(2048) + buffer := alloc.NewSmallBuffer() nBytes, err := this.Reader.Read(buffer.Value) if err != nil { buffer.Release() diff --git a/transport/internet/authenticators/http/http.go b/transport/internet/authenticators/http/http.go index 128b413f2..37ea2d592 100644 --- a/transport/internet/authenticators/http/http.go +++ b/transport/internet/authenticators/http/http.go @@ -41,7 +41,7 @@ type HeaderReader struct { } func (*HeaderReader) Read(reader io.Reader) (*alloc.Buffer, error) { - buffer := alloc.NewLocalBuffer(2048) + buffer := alloc.NewSmallBuffer() for { _, err := buffer.FillFrom(reader) if err != nil { @@ -138,7 +138,7 @@ type HttpAuthenticator struct { } func (this HttpAuthenticator) GetClientWriter() *HeaderWriter { - header := alloc.NewLocalBuffer(2048).Clear() + header := alloc.NewSmallBuffer().Clear() config := this.config.Request header.AppendString(config.Method.GetValue()).AppendString(" ").AppendString(config.PickUri()).AppendString(" ").AppendString(config.GetFullVersion()).AppendString(CRLF) @@ -153,7 +153,7 @@ func (this HttpAuthenticator) GetClientWriter() *HeaderWriter { } func (this HttpAuthenticator) GetServerWriter() *HeaderWriter { - header := alloc.NewLocalBuffer(2048).Clear() + header := alloc.NewSmallBuffer().Clear() config := this.config.Response header.AppendString(config.GetFullVersion()).AppendString(" ").AppendString(config.Status.GetCode()).AppendString(" ").AppendString(config.Status.GetReason()).AppendString(CRLF) diff --git a/transport/internet/kcp/output.go b/transport/internet/kcp/output.go index 64f63e8fc..f1294f6a1 100644 --- a/transport/internet/kcp/output.go +++ b/transport/internet/kcp/output.go @@ -37,7 +37,7 @@ func (this *BufferedSegmentWriter) Write(seg Segment) { } if this.buffer == nil { - this.buffer = alloc.NewLocalBuffer(2048).Clear() + this.buffer = alloc.NewSmallBuffer().Clear() } this.buffer.Value = seg.Bytes(this.buffer.Value) diff --git a/transport/internet/kcp/segment.go b/transport/internet/kcp/segment.go index f011340ef..a04f0967b 100644 --- a/transport/internet/kcp/segment.go +++ b/transport/internet/kcp/segment.go @@ -50,7 +50,7 @@ func NewDataSegment() *DataSegment { func (this *DataSegment) SetData(b []byte) { if this.Data == nil { - this.Data = alloc.NewLocalBuffer(1600) + this.Data = alloc.NewSmallBuffer() } this.Data.Clear().Append(b) } diff --git a/transport/internet/udp/hub.go b/transport/internet/udp/hub.go index 4291851ca..d44b39c00 100644 --- a/transport/internet/udp/hub.go +++ b/transport/internet/udp/hub.go @@ -74,7 +74,6 @@ type ListenOption struct { type UDPHub struct { sync.RWMutex conn *net.UDPConn - pool *alloc.BufferPool cancel *signal.CancelSignal queue *UDPPayloadQueue option ListenOption @@ -105,7 +104,6 @@ func ListenUDP(address v2net.Address, port v2net.Port, option ListenOption) (*UD } hub := &UDPHub{ conn: udpConn, - pool: alloc.NewBufferPool(2048, 64), queue: NewUDPPayloadQueue(option), option: option, cancel: signal.NewCloseSignal(), @@ -137,7 +135,7 @@ func (this *UDPHub) start() { oobBytes := make([]byte, 256) for this.Running() { - buffer := this.pool.Allocate() + buffer := alloc.NewSmallBuffer() nBytes, noob, _, addr, err := ReadUDPMsg(this.conn, buffer.Value, oobBytes) if err != nil { log.Info("UDP|Hub: Failed to read UDP msg: ", err)