Improve darwin tun performance

This commit is contained in:
世界
2025-07-02 19:16:14 +08:00
parent 8763c24e49
commit a0881ada32
16 changed files with 1894 additions and 159 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport/udp"
"github.com/sagernet/sing-tun/internal/gtcpip/header"
"github.com/sagernet/sing/common/buf"
"github.com/sagernet/sing/common/bufio"
E "github.com/sagernet/sing/common/exceptions"
)
@@ -72,10 +73,14 @@ func (m *Mixed) tunLoop() {
m.txChecksumOffload = linuxTUN.TXChecksumOffload()
batchSize := linuxTUN.BatchSize()
if batchSize > 1 {
m.batchLoop(linuxTUN, batchSize)
m.batchLoopLinux(linuxTUN, batchSize)
return
}
}
if darwinTUN, isDarwinTUN := m.tun.(DarwinTUN); isDarwinTUN {
m.batchLoopDarwin(darwinTUN)
return
}
packetBuffer := make([]byte, m.mtu+PacketOffset)
for {
n, err := m.tun.Read(packetBuffer)
@@ -119,12 +124,12 @@ func (m *Mixed) wintunLoop(winTun WinTun) {
}
}
func (m *Mixed) batchLoop(linuxTUN LinuxTUN, batchSize int) {
func (m *Mixed) batchLoopLinux(linuxTUN LinuxTUN, batchSize int) {
packetBuffers := make([][]byte, batchSize)
writeBuffers := make([][]byte, batchSize)
packetSizes := make([]int, batchSize)
for i := range packetBuffers {
packetBuffers[i] = make([]byte, m.mtu+m.frontHeadroom)
packetBuffers[i] = make([]byte, m.mtu+PacketOffset+m.frontHeadroom)
}
for {
n, err := linuxTUN.BatchRead(packetBuffers, m.frontHeadroom, packetSizes)
@@ -158,6 +163,40 @@ func (m *Mixed) batchLoop(linuxTUN LinuxTUN, batchSize int) {
}
}
func (m *Mixed) batchLoopDarwin(darwinTUN DarwinTUN) {
var writeBuffers []*buf.Buffer
for {
buffers, err := darwinTUN.BatchRead()
if err != nil {
if E.IsClosed(err) {
return
}
m.logger.Error(E.Cause(err, "batch read packet"))
}
if len(buffers) == 0 {
continue
}
writeBuffers = writeBuffers[:0]
for _, buffer := range buffers {
packetSize := buffer.Len()
if packetSize < header.IPv4MinimumSize {
continue
}
if m.processPacket(buffer.Bytes()) {
writeBuffers = append(writeBuffers, buffer)
} else {
buffer.Release()
}
}
if len(writeBuffers) > 0 {
err = darwinTUN.BatchWrite(writeBuffers)
if err != nil {
m.logger.Trace(E.Cause(err, "batch write packet"))
}
}
}
}
func (m *Mixed) processPacket(packet []byte) bool {
var (
writeBack bool