diff --git a/netLayer/readv.go b/netLayer/readv.go index ce26e8e..18ee5a8 100644 --- a/netLayer/readv.go +++ b/netLayer/readv.go @@ -3,7 +3,6 @@ package netLayer import ( "io" "net" - "sync" "syscall" "github.com/e1732a364fed/v2ray_simple/utils" @@ -14,75 +13,17 @@ import ( //在内网单机自己连自己测速时,readv会导致降速. const ( - readv_buffer_allocLen = 8 - ReadvSingleBufLen = 4096 - DefaultReadvOption = true ) var ( - // readv pool, 缓存 mr和buffers,进一步减轻内存分配负担 - readvPool sync.Pool // 是否会在转发过程中使用readv UseReadv bool ) -func init() { - - readvPool = sync.Pool{ - New: newReadvMem, - } - - //预先放进去两个 - - readvPool.Put(newReadvMem()) - readvPool.Put(newReadvMem()) -} - -// 缓存 readvMem 以及对应分配的系统相关的 utils.SystemReadver. -// 使用 readvMem的最大好处就是 buffers 和 mr 都是不需要 释放的. -// -// 因为不需释放mr, 所以也就节省了多次 mr.Init 的开销. -// -// 该 readvMem 以及 readvPool 专门服务于 TryCopy 函数. -type readvMem struct { - buffers [][]byte - mr utils.SystemReadver -} - -func allocReadvBuffers(mr utils.SystemReadver, len int) [][]byte { - bs := make([][]byte, len) - - for i := range bs { - // 这里单独make,而不是从 其它pool中获取, 这样可以做到专用 - bs[i] = make([]byte, ReadvSingleBufLen) - } - mr.Init(bs, ReadvSingleBufLen) - return bs -} - -func newReadvMem() any { - mr := utils.GetReadVReader() - return &readvMem{ - mr: mr, - buffers: allocReadvBuffers(mr, readv_buffer_allocLen), - } -} - -func get_readvMem() *readvMem { - return readvPool.Get().(*readvMem) - -} - -// 将创建好的rm放回 readvPool -func put_readvMem(rm *readvMem) { - rm.buffers = utils.RecoverBuffers(rm.buffers, readv_buffer_allocLen, ReadvSingleBufLen) - readvPool.Put(rm) -} - /* - readvFrom 用于读端 为rawRead的情况,如 从socks5或direct读取 数据, 等裸协议的情况。 + ReadvFrom 用于读端 为rawRead的情况,如 从socks5或direct读取 数据, 等裸协议的情况。 rm可为nil,但不建议,因为提供非nil的readvMem 可以节省内存分配开销。 @@ -92,17 +33,17 @@ rm可为nil,但不建议,因为提供非nil的readvMem 可以节省内存分 TryCopy函数使用到了本函数 来进行readv相关操作。 */ -func readvFrom(rawReadConn syscall.RawConn, rm *readvMem) ([][]byte, error) { +func ReadvFrom(rawReadConn syscall.RawConn, rm *utils.ReadvMem) ([][]byte, error) { if rm == nil { - rm = get_readvMem() + rm = utils.Get_readvMem() } - allocedBuffers := rm.buffers + allocedBuffers := rm.Buffers var nBytes uint32 err := rawReadConn.Read(func(fd uintptr) bool { - n, e := rm.mr.Read(fd) + n, e := rm.Mr.Read(fd) if e != nil { return false } @@ -118,7 +59,7 @@ func readvFrom(rawReadConn syscall.RawConn, rm *readvMem) ([][]byte, error) { return allocedBuffers, io.EOF } - nBuf := utils.ShrinkBuffers(allocedBuffers, int(nBytes), ReadvSingleBufLen) + nBuf := utils.ShrinkBuffers(allocedBuffers, int(nBytes), utils.ReadvSingleBufLen) return allocedBuffers[:nBuf], nil } @@ -127,10 +68,10 @@ func readvFrom(rawReadConn syscall.RawConn, rm *readvMem) ([][]byte, error) { func ReadBuffersFrom(c io.Reader, rawReadConn syscall.RawConn, mr utils.MultiReader) (buffers [][]byte, err error) { if rawReadConn != nil { - readv_mem := get_readvMem() + readv_mem := utils.Get_readvMem() //defer put_readvMem(readv_mem) //因为返回的buffers还需使用, 所以不能立刻放回 readv_mem - buffers, err = readvFrom(rawReadConn, readv_mem) + buffers, err = ReadvFrom(rawReadConn, readv_mem) } else if mr != nil { return mr.ReadBuffers() diff --git a/netLayer/relay.go b/netLayer/relay.go index 6a69230..f928af6 100644 --- a/netLayer/relay.go +++ b/netLayer/relay.go @@ -139,11 +139,11 @@ func TryCopy(writeConn io.Writer, readConn io.Reader, identity uint32) (allnum i } { - var readv_mem *readvMem + var readv_mem *utils.ReadvMem if !readv_withMultiReader { - readv_mem = get_readvMem() - defer put_readvMem(readv_mem) + readv_mem = utils.Get_readvMem() + defer utils.Put_readvMem(readv_mem) } //这个for循环 只会通过 return 跳出, 不会落到外部 @@ -154,7 +154,7 @@ func TryCopy(writeConn io.Writer, readConn io.Reader, identity uint32) (allnum i buffers, err = mr.ReadBuffers() } else { - buffers, err = readvFrom(rawReadConn, readv_mem) + buffers, err = ReadvFrom(rawReadConn, readv_mem) } @@ -192,7 +192,7 @@ func TryCopy(writeConn io.Writer, readConn io.Reader, identity uint32) (allnum i } if !readv_withMultiReader { - buffers = utils.RecoverBuffers(buffers, readv_buffer_allocLen, ReadvSingleBufLen) + buffers = utils.RecoverBuffers(buffers, utils.Readv_buffer_allocLen, utils.ReadvSingleBufLen) } @@ -215,7 +215,7 @@ func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err err var buffers net.Buffers var rawConn syscall.RawConn - var rm *readvMem + var rm *utils.ReadvMem if ce := utils.CanLogDebug("TryCopy"); ce != nil { ce.Write( @@ -240,10 +240,10 @@ func TryCopyOnce(writeConn io.Writer, readConn io.Reader) (allnum int64, err err ce.Write() } - rm = get_readvMem() - defer put_readvMem(rm) + rm = utils.Get_readvMem() + defer utils.Put_readvMem(rm) - buffers, err = readvFrom(rawConn, rm) + buffers, err = ReadvFrom(rawConn, rm) if err != nil { return 0, err } diff --git a/utils/readv.go b/utils/readv.go new file mode 100644 index 0000000..f7d006c --- /dev/null +++ b/utils/readv.go @@ -0,0 +1,66 @@ +package utils + +import "sync" + +var ( + // readv pool, 缓存 mr和buffers,进一步减轻内存分配负担 + readvPool sync.Pool +) + +const ( + Readv_buffer_allocLen = 8 + ReadvSingleBufLen = 4096 +) + +func init() { + + readvPool = sync.Pool{ + New: newReadvMem, + } + + //预先放进去两个 + + readvPool.Put(newReadvMem()) + readvPool.Put(newReadvMem()) +} + +// 缓存 ReadvMem 以及对应分配的系统相关的 SystemReadver. +// 使用 ReadvMem的最大好处就是 buffers 和 mr 都是不需要 释放的. +// +// 因为不需释放mr, 所以也就节省了多次 mr.Init 的开销. +// +// 该 ReadvMem 以及 readvPool 专门服务于 TryCopy 函数. +type ReadvMem struct { + Buffers [][]byte + Mr SystemReadver +} + +func allocReadvBuffers(mr SystemReadver, len int) [][]byte { + bs := make([][]byte, len) + + for i := range bs { + // 这里单独make,而不是从 其它pool中获取, 这样可以做到专用 + bs[i] = make([]byte, ReadvSingleBufLen) + } + mr.Init(bs, ReadvSingleBufLen) + return bs +} + +func newReadvMem() any { + mr := GetReadVReader() + return &ReadvMem{ + Mr: mr, + Buffers: allocReadvBuffers(mr, Readv_buffer_allocLen), + } +} + +func Get_readvMem() *ReadvMem { + return readvPool.Get().(*ReadvMem) + +} + +// 将创建好的rm放回 readvPool +func Put_readvMem(rm *ReadvMem) { + rm.Buffers = RecoverBuffers(rm.Buffers, Readv_buffer_allocLen, ReadvSingleBufLen) + readvPool.Put(rm) +}