Golang与Python中的UDP性能差
我想尽快发送尽可能多的UDP数据包。我尝试了在包中发送UDP数据的不同方法,但结果如下:Golang与Python中的UDP性能差,python,go,networking,udp,Python,Go,Networking,Udp,我想尽快发送尽可能多的UDP数据包。我尝试了在包中发送UDP数据的不同方法,但结果如下: func main() { for i := 0; i < THREADS; i++ { go loopSendHello() } // Sleep forever <-make(chan bool, 1) } func loopSendHello() { for { sendHello() } } func
func main() {
for i := 0; i < THREADS; i++ {
go loopSendHello()
}
// Sleep forever
<-make(chan bool, 1)
}
func loopSendHello() {
for {
sendHello()
}
}
func sendHello() {
// Setup conn
addr := net.UDPAddr{
IP: net.IP{192, 168, 1, xxx},
Port: 1337,
}
conn, err := net.ListenPacket("udp", "")
if err != nil {
log.Fatal("Listen:", err)
}
n, err := conn.WriteTo([]byte("hello"), &addr)
if err != nil {
log.Fatal("Error while writing to conn! :", err)
}
conn.Close()
}
使用Wireshark的基准测试:。这是从1毫秒到大约10毫秒的延迟!疯狂的差异
如何才能在Go中达到python的速度?因此我决定非常快速地创建一个简单的基准,在没有任何线程或糟糕编程技术的情况下发送200000个UDP数据包。基准测试介于Go和Python之间。此外,我希望基准测试尽可能快地进行协调。我曾使用C语言进行协调,但由于我使用的是Windows,所以似乎最容易使用Rust 防锈代码:
use std::time::{SystemTime};
use std::net::UdpSocket;
const DATA: &[u8] = &[0; 1024];
fn main() {
let time_start = SystemTime::now();
let socket = UdpSocket::bind("192.168.1.155:1339").unwrap();
for _ in 0..200000 {
socket.send_to(DATA, "192.168.1.122:80").unwrap();
}
let elapsed = time_start.elapsed().unwrap();
println!("Time {} ms to send 200 000 packets", elapsed.as_millis());
}
平均结果(内置-释放模式):发送200000个数据包需要1863毫秒的时间
对于Go基准测试,这基本上就是代码:
var buff = []byte("")
func main() {
buff = []byte(RandomString(1024))
conn, err := net.ListenUDP("udp", &net.UDPAddr{})
if err != nil {
log.Fatal("Listen:", err)
}
loopSendHello(*conn)
conn.Close()
}
func loopSendHello(conn net.UDPConn) {
timeStart := time.Now()
for i:=0; i < 200000; i++ {
sendHelloEdited(&conn)
}
timeStop := time.Now()
timeDelta := timeStop.Sub(timeStart)
fmt.Println("Took", timeDelta.Milliseconds(), "ms to send 200 000 packets.")
}
// targetAddr is target address in form of net.UDPAddr
func sendHelloEdited(conn *net.UDPConn) {
_, err := conn.WriteToUDP(buff, &targetAddr)
if err != nil {
log.Fatal("Error while writing to conn! :", err)
}
}
def main():
x = 0
data = random._urandom(1024)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = (str(ip), int(port))
startTime = datetime.datetime.now()
while x < 200000:
s.sendto(data, addr)
x += 1
s.close()
endTime = datetime.datetime.now()
deltaTime = endTime - startTime
print("Took", deltaTime, "to send 200 000 packets")
main()
有趣的是,python的结果总是很快,平均输出为:需要0:00:01.831531才能发送200000个数据包
因此,Go看起来确实是最慢的,但只是稍微慢了一点。因此我决定非常快速地创建一个简单的基准,在没有任何线程或糟糕编程技术的情况下发送200000个UDP数据包。基准测试介于Go和Python之间。此外,我希望基准测试尽可能快地进行协调。我曾使用C语言进行协调,但由于我使用的是Windows,所以似乎最容易使用Rust 防锈代码:
use std::time::{SystemTime};
use std::net::UdpSocket;
const DATA: &[u8] = &[0; 1024];
fn main() {
let time_start = SystemTime::now();
let socket = UdpSocket::bind("192.168.1.155:1339").unwrap();
for _ in 0..200000 {
socket.send_to(DATA, "192.168.1.122:80").unwrap();
}
let elapsed = time_start.elapsed().unwrap();
println!("Time {} ms to send 200 000 packets", elapsed.as_millis());
}
平均结果(内置-释放模式):发送200000个数据包需要1863毫秒的时间
对于Go基准测试,这基本上就是代码:
var buff = []byte("")
func main() {
buff = []byte(RandomString(1024))
conn, err := net.ListenUDP("udp", &net.UDPAddr{})
if err != nil {
log.Fatal("Listen:", err)
}
loopSendHello(*conn)
conn.Close()
}
func loopSendHello(conn net.UDPConn) {
timeStart := time.Now()
for i:=0; i < 200000; i++ {
sendHelloEdited(&conn)
}
timeStop := time.Now()
timeDelta := timeStop.Sub(timeStart)
fmt.Println("Took", timeDelta.Milliseconds(), "ms to send 200 000 packets.")
}
// targetAddr is target address in form of net.UDPAddr
func sendHelloEdited(conn *net.UDPConn) {
_, err := conn.WriteToUDP(buff, &targetAddr)
if err != nil {
log.Fatal("Error while writing to conn! :", err)
}
}
def main():
x = 0
data = random._urandom(1024)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
addr = (str(ip), int(port))
startTime = datetime.datetime.now()
while x < 200000:
s.sendto(data, addr)
x += 1
s.close()
endTime = datetime.datetime.now()
deltaTime = endTime - startTime
print("Took", deltaTime, "to send 200 000 packets")
main()
有趣的是,python的结果总是很快,平均输出为:需要0:00:01.831531才能发送200000个数据包
因此,Go看起来确实是最慢的,但只是稍微慢一点。这是一个毫无意义的比较,因为在普通程序中,您不会在每次发送单个数据包时都创建一个新套接字,特别是在性能受到关注的情况下,所以运行时并没有为此进行优化。如果你想提高性能,10毫秒的延迟也是相当糟糕的。在Go中,您应该使用
ListenUDP
和WriteToUDP
来获得更具可比性的内容,并且您也没有关闭python中的套接字。@JimB只创建一个连接,该连接将传递给所有创建的goroutine,使用ListenUDP/WriteToUDP会产生100毫秒的延迟。这是比原始情况更糟糕的性能。更新:性能没有更差,但与以前大致相同,我的坏。您一定有其他事情发生,但我们无法知道,如果没有。例如,我的笔记本电脑每秒可以生成25000个数据包。从同一个套接字发送多个goroutine对您也没有任何好处。该接口只能以如此快的速度写入数据包,因此增加数据包上的争用并不能提高性能。@JimB-Hmm可能是这样,但我在我的macbook上进行了测试,得到了类似的结果,其中Go的性能非常差。不管怎么说,Rust似乎解决了我的问题。这是一个毫无意义的比较,因为在一个普通的程序中,你不会每次想发送一个数据包时都创建一个新的套接字,特别是当性能是一个问题时,所以运行时并没有为此进行优化。如果你想提高性能,10毫秒的延迟也是相当糟糕的。在Go中,您应该使用ListenUDP
和WriteToUDP
来获得更具可比性的内容,并且您也没有关闭python中的套接字。@JimB只创建一个连接,该连接将传递给所有创建的goroutine,使用ListenUDP/WriteToUDP会产生100毫秒的延迟。这是比原始情况更糟糕的性能。更新:性能没有更差,但与以前大致相同,我的坏。您一定有其他事情发生,但我们无法知道,如果没有。例如,我的笔记本电脑每秒可以生成25000个数据包。从同一个套接字发送多个goroutine对您也没有任何好处。该接口只能以如此快的速度写入数据包,因此增加数据包上的争用并不能提高性能。@JimB-Hmm可能是这样,但我在我的macbook上进行了测试,得到了类似的结果,其中Go的性能非常差。不管怎样,看来生锈解决了我的问题。