Files
v2ray_simple/netLayer/readv_test.go
e1732a364fed 2e7dda7c18 修订代码,文档;logfile标准配置以及-sp行为改变,见下:
在标准 toml 配置中 配置 logfile 配置文件路径。 如 `logfile = "/var/log/verysimple/vs_log"`

将 -sp 的行为 改为 打印完毕后立即退出。
2022-04-29 21:40:01 +08:00

385 lines
6.5 KiB
Go
Raw Permalink 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 netLayer
import (
"bytes"
"crypto/rand"
"io"
"net"
"strings"
"testing"
"github.com/e1732a364fed/v2ray_simple/utils"
)
/*
我们本地benchmark实际benchmark readv 是比 经典拷贝慢的
BenchmarkReadVCopy-8 426525 2934 ns/op
BenchmarkClassicCopy-8 531406 2185 ns/op
BenchmarkClassicCopy_SimulateRealWorld-8 60873 19631 ns/op
BenchmarkClassicCopy_SimulateRealWorld_ReadV-8 66138 17907 ns/op
我们添加一种情况 SimulateRealWorld, 分10次写入, 每次写入长度均小于MTU此时即可发现readv更快
总之这种本地benchmark 对于 readv来说意义不大因为本地回环太快了, readv只能徒增各种附加操作.
理论上来说在非本地测试环境下只要每次传输的包超过了MTU那么readv就应该是有优势的包长度越大越有优势因为越大越容易被割包那么readv就越好用
*/
//我们不断向一个net.Conn 发送大数据
func TestReadVCopy(t *testing.T) {
utils.InitLog("")
listenAddr := GetRandLocalAddr(true, false)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
t.Log(err)
t.FailNow()
}
bigBytes := make([]byte, 10240) //10k
n, err := rand.Reader.Read(bigBytes)
if err != nil || n != 10240 {
t.Log(err)
t.FailNow()
}
transmitCount := 10
go func() {
conn, err := listener.Accept()
if err != nil {
//t.Log(err)
t.Fail()
return
}
for i := 0; i < transmitCount; i++ {
buf := &bytes.Buffer{}
_, err := TryCopyOnce(buf, conn)
if err != nil {
if strings.Contains(err.Error(), "close") {
t.Fail()
}
//t.Log(err)
return
}
}
}()
tcpConn, err := net.Dial("tcp", listenAddr)
if err != nil {
t.Log(err)
t.FailNow()
}
for i := 0; i < transmitCount; i++ {
_, e := tcpConn.Write(bigBytes)
if e != nil {
t.Log(err)
t.FailNow()
}
}
tcpConn.Close()
}
func BenchmarkReadVCopy(b *testing.B) {
transmitCount := b.N
listenAddr := GetRandLocalAddr(true, false)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
bigBytes := make([]byte, 10240) //10k
n, err := rand.Reader.Read(bigBytes)
if err != nil || n != 10240 {
b.Log(n, err)
b.FailNow()
}
go func() {
conn, err := listener.Accept()
if err != nil {
//b.Log(err)
b.Fail()
}
//buf := &bytes.Buffer{}
for i := 0; i < transmitCount; i++ {
buf := utils.GetBuf()
_, err := TryCopyOnce(buf, conn)
if err != nil {
if strings.Contains(err.Error(), "close") {
b.Fail()
}
}
utils.PutBuf(buf)
//buf.Reset()
}
}()
tcpConn, err := net.Dial("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
for i := 0; i < transmitCount; i++ {
_, e := tcpConn.Write(bigBytes)
if e != nil {
b.Log(err)
b.FailNow()
}
}
tcpConn.Close()
}
func BenchmarkClassicCopy(b *testing.B) {
b.StopTimer()
b.ResetTimer()
transmitCount := b.N
listenAddr := GetRandLocalAddr(true, false)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
const bigBytesLen = 10240
bigBytes := make([]byte, bigBytesLen) //10k
n, err := rand.Reader.Read(bigBytes)
if err != nil || n != bigBytesLen {
b.Log(n, err)
b.FailNow()
}
go func() {
conn, err := listener.Accept()
if err != nil {
//b.Log(err)
b.Fail()
}
//bs := make([]byte, bigBytesLen)
//buf := &bytes.Buffer{}
// 不能直接使用单一buf否则对readv来说不公平必须同样从pool中存取
for {
buf := utils.GetBuf()
//bs := utils.GetMTU()
bs := utils.GetPacket()
n, err := conn.Read(bs)
if err != nil {
if err != io.EOF && !strings.Contains(err.Error(), "close") {
b.Fail()
}
return
}
buf.Write(bs[:n])
utils.PutBuf(buf)
utils.PutPacket(bs)
//utils.PutBytes(bs)
//buf.Reset()
}
}()
tcpConn, err := net.Dial("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
b.StartTimer()
for i := 0; i < transmitCount; i++ {
_, e := tcpConn.Write(bigBytes)
if e != nil {
b.Log(err)
b.FailNow()
}
}
tcpConn.Close()
}
func BenchmarkClassicCopy_SimulateRealWorld(b *testing.B) {
b.StopTimer()
b.ResetTimer()
transmitCount := b.N
listenAddr := GetRandLocalAddr(true, false)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
const bigBytesLen = 10240
bigBytes := make([]byte, bigBytesLen) //10k
n, err := rand.Reader.Read(bigBytes)
if err != nil || n != bigBytesLen {
b.Log(err)
b.FailNow()
}
go func() {
conn, err := listener.Accept()
if err != nil {
b.Log(err)
b.Fail()
return
}
//bs := make([]byte, bigBytesLen)
for {
//bs := utils.GetMTU()
bs := utils.GetPacket()
n, err := conn.Read(bs)
if err != nil {
if err != io.EOF && !strings.Contains(err.Error(), "close") {
b.Log(err)
b.Fail()
}
return
}
buf := utils.GetBuf()
buf.Write(bs[:n])
utils.PutBuf(buf)
utils.PutPacket(bs)
//utils.PutBytes(bs)
}
}()
tcpConn, err := net.Dial("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
b.StartTimer()
for i := 0; i < transmitCount; i++ {
unit := bigBytesLen / 10
for cursor := 0; cursor < bigBytesLen; cursor += unit {
_, e := tcpConn.Write(bigBytes[cursor : cursor+unit])
if e != nil {
b.Log(err)
b.FailNow()
}
}
}
tcpConn.Close()
}
func BenchmarkClassicCopy_SimulateRealWorld_ReadV(b *testing.B) {
b.StopTimer()
b.ResetTimer()
transmitCount := b.N
listenAddr := GetRandLocalAddr(true, false)
listener, err := net.Listen("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
const bigBytesLen = 10240
bigBytes := make([]byte, bigBytesLen) //10k
n, err := rand.Reader.Read(bigBytes)
if err != nil || n != bigBytesLen {
b.Log(err)
b.FailNow()
}
go func() {
conn, err := listener.Accept()
if err != nil {
b.Log(err)
b.Fail()
return
}
for {
//buf := &bytes.Buffer{}
buf := utils.GetBuf()
_, err := TryCopyOnce(buf, conn)
if err != nil {
if err != io.EOF && strings.Contains(err.Error(), "close") {
b.Fail()
}
return
}
utils.PutBuf(buf)
}
}()
tcpConn, err := net.Dial("tcp", listenAddr)
if err != nil {
b.Log(err)
b.FailNow()
}
unit := bigBytesLen / 10
b.StartTimer()
for i := 0; i < transmitCount; i++ {
for cursor := 0; cursor < bigBytesLen; cursor += unit {
_, e := tcpConn.Write(bigBytes[cursor : cursor+unit])
if e != nil {
b.Log(err)
b.FailNow()
}
}
}
tcpConn.Close()
}