Improve vectorised writer

This commit is contained in:
世界 2023-03-05 13:35:34 +08:00
parent c875a4ffab
commit e16845727f
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
4 changed files with 44 additions and 17 deletions

View file

@ -16,6 +16,14 @@ func ToSliceMulti(buffers []*Buffer) [][]byte {
}) })
} }
func CopyMulti(toBuffer []byte, buffers []*Buffer) int {
var n int
for _, buffer := range buffers {
n += copy(toBuffer[n:], buffer.Bytes())
}
return n
}
func ReleaseMulti(buffers []*Buffer) { func ReleaseMulti(buffers []*Buffer) {
for _, buffer := range buffers { for _, buffer := range buffers {
buffer.Release() buffer.Release()

View file

@ -49,11 +49,29 @@ func (c *ChunkReader) Read(p []byte) (n int, err error) {
c.cache.FullReset() c.cache.FullReset()
err = c.upstream.ReadBuffer(c.cache) err = c.upstream.ReadBuffer(c.cache)
if err != nil { if err != nil {
c.cache.Release()
c.cache = nil
return return
} }
return c.cache.Read(p) return c.cache.Read(p)
} }
func (c *ChunkReader) ReadChunk() (*buf.Buffer, error) {
if c.cache == nil {
c.cache = buf.NewSize(c.maxChunkSize)
} else if !c.cache.IsEmpty() {
return c.cache, nil
}
c.cache.FullReset()
err := c.upstream.ReadBuffer(c.cache)
if err != nil {
c.cache.Release()
c.cache = nil
return nil, err
}
return c.cache, nil
}
func (c *ChunkReader) MTU() int { func (c *ChunkReader) MTU() int {
return c.maxChunkSize return c.maxChunkSize
} }

View file

@ -3,7 +3,6 @@ package bufio
import ( import (
"io" "io"
"net" "net"
"sync"
"syscall" "syscall"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
@ -16,7 +15,7 @@ func NewVectorisedWriter(writer io.Writer) N.VectorisedWriter {
if vectorisedWriter, ok := CreateVectorisedWriter(writer); ok { if vectorisedWriter, ok := CreateVectorisedWriter(writer); ok {
return vectorisedWriter return vectorisedWriter
} }
return &SerialVectorisedWriter{upstream: writer} return &BufferedVectorisedWriter{upstream: writer}
} }
func CreateVectorisedWriter(writer any) (N.VectorisedWriter, bool) { func CreateVectorisedWriter(writer any) (N.VectorisedWriter, bool) {
@ -57,26 +56,30 @@ func CreateVectorisedPacketWriter(writer any) (N.VectorisedPacketWriter, bool) {
return nil, false return nil, false
} }
var _ N.VectorisedWriter = (*SerialVectorisedWriter)(nil) var _ N.VectorisedWriter = (*BufferedVectorisedWriter)(nil)
type SerialVectorisedWriter struct { type BufferedVectorisedWriter struct {
upstream io.Writer upstream io.Writer
access sync.Mutex
} }
func (w *SerialVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error { func (w *BufferedVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
w.access.Lock() defer buf.ReleaseMulti(buffers)
defer w.access.Unlock() bufferLen := buf.LenMulti(buffers)
for _, buffer := range buffers { var bufferBytes []byte
_, err := w.upstream.Write(buffer.Bytes()) if bufferLen > 65535 {
if err != nil { bufferBytes = make([]byte, bufferLen)
return err } else {
} _buffer := buf.StackNewSize(bufferLen)
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
bufferBytes = buffer.FreeBytes()
} }
return nil buf.CopyMulti(bufferBytes, buffers)
return common.Error(w.upstream.Write(bufferBytes))
} }
func (w *SerialVectorisedWriter) Upstream() any { func (w *BufferedVectorisedWriter) Upstream() any {
return w.upstream return w.upstream
} }

2
go.sum
View file

@ -1,4 +1,2 @@
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=