mirror of
https://github.com/SagerNet/sing.git
synced 2025-04-03 03:47:38 +03:00
Improve vectorised writer
This commit is contained in:
parent
c875a4ffab
commit
e16845727f
4 changed files with 44 additions and 17 deletions
|
@ -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) {
|
||||
for _, buffer := range buffers {
|
||||
buffer.Release()
|
||||
|
|
|
@ -49,11 +49,29 @@ func (c *ChunkReader) Read(p []byte) (n int, err error) {
|
|||
c.cache.FullReset()
|
||||
err = c.upstream.ReadBuffer(c.cache)
|
||||
if err != nil {
|
||||
c.cache.Release()
|
||||
c.cache = nil
|
||||
return
|
||||
}
|
||||
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 {
|
||||
return c.maxChunkSize
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package bufio
|
|||
import (
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
|
@ -16,7 +15,7 @@ func NewVectorisedWriter(writer io.Writer) N.VectorisedWriter {
|
|||
if vectorisedWriter, ok := CreateVectorisedWriter(writer); ok {
|
||||
return vectorisedWriter
|
||||
}
|
||||
return &SerialVectorisedWriter{upstream: writer}
|
||||
return &BufferedVectorisedWriter{upstream: writer}
|
||||
}
|
||||
|
||||
func CreateVectorisedWriter(writer any) (N.VectorisedWriter, bool) {
|
||||
|
@ -57,26 +56,30 @@ func CreateVectorisedPacketWriter(writer any) (N.VectorisedPacketWriter, bool) {
|
|||
return nil, false
|
||||
}
|
||||
|
||||
var _ N.VectorisedWriter = (*SerialVectorisedWriter)(nil)
|
||||
var _ N.VectorisedWriter = (*BufferedVectorisedWriter)(nil)
|
||||
|
||||
type SerialVectorisedWriter struct {
|
||||
type BufferedVectorisedWriter struct {
|
||||
upstream io.Writer
|
||||
access sync.Mutex
|
||||
}
|
||||
|
||||
func (w *SerialVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
|
||||
w.access.Lock()
|
||||
defer w.access.Unlock()
|
||||
for _, buffer := range buffers {
|
||||
_, err := w.upstream.Write(buffer.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (w *BufferedVectorisedWriter) WriteVectorised(buffers []*buf.Buffer) error {
|
||||
defer buf.ReleaseMulti(buffers)
|
||||
bufferLen := buf.LenMulti(buffers)
|
||||
var bufferBytes []byte
|
||||
if bufferLen > 65535 {
|
||||
bufferBytes = make([]byte, bufferLen)
|
||||
} 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
|
||||
}
|
||||
|
||||
|
|
2
go.sum
2
go.sum
|
@ -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/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue