简体   繁体   English

Golang 与 Python 中糟糕的 UDP 性能

[英]Bad UDP performance in Golang vs. Python

I want to send as many UDP packets as fast as possible.我想尽可能快地发送尽可能多的 UDP 数据包。 I tried different methods of sending UDP data in the net package, but ended up with the following;我尝试了在net包中发送 UDP 数据的不同方法,但最终得到了以下结果;

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()
}

THREADS is defined by runtime.NumCPU() btw. THREADS 由 runtime.NumCPU() btw 定义。 Benchmarking this using Wireshark gives these results:使用 Wireshark 对此进行基准测试可得出以下结果: Golang 基准测试 About 90ms delay (if I'm reading this right).大约 90 毫秒的延迟(如果我没看错的话)。

While this is the situation in Python (this function is running in 4 threads):虽然这是 Python 中的情况(此函数在 4 个线程中运行):

def sendHello():
    while True:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            addr = ("192.168.1.xxx", 1337)
            s.sendto(data, addr)
        except:
            print("error")

Benchmark using Wireshark:使用 Wireshark 进行基准测试: 长凳 . . This is from 1ms to about 10ms delay!这是从 1ms 到大约 10ms 的延迟! Insane differences.疯狂的差异。

How can I match python's speed in Go?如何在 Go 中匹配 python 的速度?

So I decided to very quickly create a simple benchmark of sending 200 000 UDP packets without any threads or bad programming techniques.所以我决定非常快速地创建一个简单的基准测试,发送 200 000 个 UDP 数据包,没有任何线程或糟糕的编程技术。 The benchmark is between Go and Python.基准测试介于 Go 和 Python 之间。 In addition I wanted a benchmark test to be concidered close to as fast as possible.此外,我希望尽可能快地考虑基准测试。 I concidered using C, but as I'm on Windows it seemed easiest to use Rust.我考虑过使用 C,但由于我在 Windows 上,使用 Rust 似乎最容易。

Rust code:防锈代码:

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());
}

Avg.平均result (built in --release mode): Time 1863 ms to send 200 000 packets结果(内置 --release 模式): Time 1863 ms to send 200 000 packets

For the Go benchmark, this is essentially the code:对于 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)
    }
}

Go avg.去平均。 result: Took 1959 MS to send 200 000 packets.结果: Took 1959 MS to send 200 000 packets.

Now for the Python test, this is the code:现在对于 Python 测试,这是代码:

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()

Interestingly the python result was always quick, with an avg.有趣的是,python 结果总是很快,平均。 output of: Took 0:00:01.831531 to send 200 000 packets输出: Took 0:00:01.831531 to send 200 000 packets

So it seems Go is indeed slowest, but only marginally.所以看起来 Go 确实是最慢的,但只是微不足道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM