在python中处理和保存UDP流的最快方法

时间:2014-05-14 16:51:26

标签: python performance sockets networking network-programming

我正在为通过1Gb以太网连接到PC的科学测量设备开发客户端。

测试PC CPU是i5-460M(2.53x2)+ 8Gb内存。 OS Win 7 x64(无法更改为linux)。 Python 2.7.6 x86

设备使用以下格式以UDP数据包发送数据:

  uint  meas_id;
  uint  part_id;
  ubyte data[1428];

数据速率为1Gb / s(每秒约70'000个数据包)。

我需要接收并将数据转储到磁盘上(大约10分钟)以备将来处理,但遇到两个问题:数据包丢失(在线程之间传输数据时)和HDD使用情况。

目前的结构是两个工作过程:

  1. 接收udp数据包,累积1000个数据包,在多处理中发送数据。管道/队列到另一个进程。
  2. 获取chunks prom Pipe / Queue,反序列化结构(至少前2个字段)并保存。
  3. 使用原始python套接字我可以在我的机器上接收大约110k pps而不丢包,只需

    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024*1024*256) # real buffer is less
    s.bind(("0.0.0.0", 8201))
    while is_active:
        ...
        data = s.recv(1536)
    

    但有些数据包会被丢弃。当我试图使用这样的代码将数据发送到另一个进程时:

    data_buf = []
    while 1:
        d = s.recv(1536)
        data_buf.append(d)
        if len(data_buf) == CHUNK_SIZE:
            xchg_queue.put(data_buf)
            data_buf = []
    

    管道更快,但正如我所见 - 如果管道中有某些对象,pipe.send()可能会锁定。

    是否有更快的方法在流程之间发送数据?

    我已经尝试将MySQL作为具有禁用索引的存储并启用了延迟写入,但每秒节省了大约30-35k数据包。

    使用cPickle时,每个文件保存1000 - 100000个数据包时得到40-50k pps。

    有更快的方法来保存数据吗?可能是PyTables(HDF5)或一些快速的NoSQL DB(类似redis)。

    此外,我不确定这个客户端是否可以在python中使用 - 可能需要在纯C中重写模块。

    或者可能是python套接字上有快速包装器(如gevent)?

    希望你能提供帮助。

1 个答案:

答案 0 :(得分:0)

如果您只需要保存数据以备将来处理,我就不会使用python和数据库的开销,而只需使用tshark或windump尽可能快地保存数据,并将最少的开销存入单个文件。这也是HDD最便宜的,因为你只附加在文件中。稍后你可以使用python和winpcap或其他工具来处理数据,而不会丢失任何数据,并以你需要的格式写出来。