【问题标题】:Best way to improve UDP transfer speeds with Python?使用 Python 提高 UDP 传输速度的最佳方法?
【发布时间】:2022-01-15 01:43:29
【问题描述】:

我编写了一个 Python 程序,用于通过 UDP 发送和接收大文件。现在,通过 10 Gigabit 以太网电缆在两台计算机之间传输时,我可以达到大约 0.01GB/s 的速度。我希望显着提高该速度,但我不确定最好的方法是什么。

为了它的价值,我必须使用 UDP 进行传输。我写的程序只是一个更大的项目的测试,为那个项目发送数据的设备不能使用 TCP 流。此外,我主要关注快速接收数据报的最佳方式,或者至少是确保接收端不会出现任何瓶颈的最佳方式。

现在,我的程序通过将一个大文件分成几个部分来工作,这些部分将成为要发送的数据报。这些数据报被发送,然后接收者做一些事情来确保它得到正确的数据并相应地对其进行排序。

发送代码(精简到基础)

buf = 32000  #Size of each chunk/packet
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
host ="127.0.0.1"
port = 5005
addr = (host,port)    

def read_in_chunks(infile, chunk_size=buf):
"""Chunk the file before we send it.
Arguments:
infile -- the file to chunk
chunk_size -- the size of the chunk in bytes (default 32KB)
"""
    while True:
        chunk = infile.read(chunk_size)
        if chunk:
            yield chunk
        else:
            # The chunk was empty, which means we're at the end of the file
            return

def run():
    for chunk in read_in_chunks(f):
        if(s.sendto(chunk,addr) and s.sendto(id,addr)):
            #Some acknowledgment stuff - removed for clarity (also noted to not impact performance)
            local_ID += 1

接收代码:

UDP_IP = "127.0.0.1"
UDP_PORT = 5005
buf = 32000  # Buffer size in bytes for each chunk
sock = socket.socket(socket.AF_INET,  # Internet
                 socket.SOCK_DGRAM)  # UDP
sock.bind((UDP_IP, UDP_PORT))

try:
    while(dataChunk):
        actualNumChunks += 1
        f.write(dataChunk)
        sock.settimeout(2)
        dataChunk, addr = sock.recvfrom(buf)
        packID, junkAddr = sock.recvfrom(buf)
        packIDString = str(packID)
except socket.timeout:
    f.close()
    sock.close()
    print "File received!"  # --KEEP
    print "A total of " + str(actualNumChunks) +" chunks were received"            --KEEP

我不确定优化我的代码是否是问题(尚待测试),或者是否有另一种(更好的?)方法可以提高文件传输速度。如果此处的详细信息很少,我深表歉意,但如果您需要更多信息,请告诉我。

谢谢!

【问题讨论】:

  • 使用 mmap(python 库)获得更快的 I/O。计算最大值MTU 发送更多字节/数据包。

标签: python performance sockets udp


【解决方案1】:

一些尝试的方法:

  1. 不同的数据包大小(取决于MTU,可能会导致块被分成几个数据包,或者可能太小而无法以最佳方式使用管道)
  2. 将文件读取到内存(网络速度可能为 10gbps,但磁盘要慢得多,尤其是如果它不是 SSD 时 - 通常要慢一个数量级或更慢),在全部缓存后开始发送.您可以尝试多次发送相同的数据块来检查这是否是瓶颈。
  3. 压缩可能会有所帮助。 ZLIB 非常非常非常快,这意味着您可以在更短的时间内传输更多数据,

其他要点:

  • 数据包丢失和排序可能会使正确的传输出现问题,即使在简单的一对一链接中也是如此。您需要错误检测/重试功能才能使其正常工作。
  • 内核/用户模式更改可能会减慢您的速度(怀疑,这是超级微优化)

【讨论】:

  • 谢谢。一个新的注释:我已经修改了数据包大小并更改了 MTU,它们似乎可以工作,但是当我使用 10GigE 连接实际测试程序时,我不得不使用大大减小的数据包大小(~14000 vs 原来的 32000在本地 127 IP 上工作)。我们拥有的 NIC 的 MTU 最大值约为 9000 左右。另外,对于第 2 点,您的意思是我应该在发送之前完全读入文件吗?另外,您能否再描述一下您提到的测试方法?对于第 3 点,您是建议将压缩文件作为一个整体发送还是制作压缩块?
  • 1.您可以修改源 NIC 和目标 NIC 的 MTU。 2. 尝试通过构建一个数据块并将其以多个数据包的形式发送来测试这是否是瓶颈,就好像该文件由该数据块的无限重复组成。这意味着您从 RAM 而不是从磁盘读取数据,并且应该告诉您这是否是瓶颈,或者是否位于其他地方。 3. 压缩的块可能几乎和完整的文件一样有效,这意味着您可以立即开始发送 - 所以我会说压缩块。
  • 请告诉我们您的结果是什么,如果您认为自己得到了答案,请将此问题标记为已回答。
  • 在原始测试期间更改了两个系统上的 MTU,但似乎没有达到预期的效果。我今天将测试其他更改,但我认为到目前为止,您为我提供了更好的方向感。谢谢!
  • 虽然您提出的建议有效且有帮助,但我可以从接收端做些什么来提高传输速度?您的建议更倾向于发送方(这有助于测试目的)。本质上,我希望能够确保接收端不会成为瓶颈。
【解决方案2】:

对于您的接收器,您执行文件写入,这可能是一个瓶颈。可以尝试的几件事是将所有“dataChunk”写入队列。然后有一个单独的线程或进程(多处理)从这个队列中读取并写入文件。这将从您的 while 循环中卸载文件写入 IO,并可能允许您处理更多数据包。

【讨论】:

    猜你喜欢
    • 2012-11-19
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 2021-12-14
    • 2019-04-28
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多