Files
v2ray_simple/utils/readv.go
e1732a364fed a704f77eb4 重构readv代码,将MultiReader分为 BuffersReader和Readver两种
Readver是因为可以暴露出底层连接所以能加速;而BuffersReader是
因为协议对于多buf的读取支持良好所以可以加速,逻辑完全不同
2022-12-26 07:50:44 +08:00

138 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"io"
"sync"
"syscall"
)
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)
}
/*
ReadvFrom 用于读端 为rawRead的情况如 从socks5或direct读取 数据, 等裸协议的情况。
rm可为nil但不建议因为提供非nil的readvMem 可以节省内存分配开销。
返回错误时,会返回 原buffer 或 在函数内部新分配的buffer.
本函数不负责 释放分配的内存. 因为有时需要重复利用缓存。
TryCopy函数使用到了本函数 来进行readv相关操作。
*/
func ReadvFrom(rawReadConn syscall.RawConn, rm *ReadvMem) ([][]byte, error) {
if rm == nil {
rm = Get_readvMem()
}
allocedBuffers := rm.Buffers
var nBytes uint32
err := rawReadConn.Read(func(fd uintptr) bool {
n, e := rm.Mr.Read(fd)
if e != nil {
return false
}
nBytes = n
return true
})
if err != nil {
return allocedBuffers, err
}
if nBytes == 0 {
return allocedBuffers, io.EOF
}
nBuf := ShrinkBuffers(allocedBuffers, int(nBytes), ReadvSingleBufLen)
return allocedBuffers[:nBuf], nil
}
/*
// 依次试图使用 readv、ReadBuffers 以及 原始 Read 读取数据
func ReadBuffersFrom(c io.Reader, rawReadConn syscall.RawConn, mr MultiReader) (buffers [][]byte, err error) {
if rawReadConn != nil {
readv_mem := Get_readvMem()
//defer put_readvMem(readv_mem) //因为返回的buffers还需使用, 所以不能立刻放回 readv_mem
buffers, err = ReadvFrom(rawReadConn, readv_mem)
} else if mr != nil {
return mr.ReadBuffers()
} else {
packet := GetPacket()
var n int
n, err = c.Read(packet)
if err != nil {
return
}
buffers = append(buffers, packet[:n])
}
return
}
*/