如何加速python网络?

时间:2014-04-23 15:41:44

标签: python performance sockets python-2.7 network-programming

我发现python网络

我有一台服务器(用C语言编写)。我用我的客户端(python)测试了它。 我可以到达2MB/s。它让我很担心,所以我查了一遍:

host1(客户端): cat some_big_file | nc host2 9999

host2(服务器): nc -l 0.0.0.0 9999 | pv > /dev/null

我的速度达到了120MB / s(1Gb)左右。

服务器不是瓶颈,我们在生产中使用它,它可以处理更多。但是要确保我复制了简单的python gevent服务器进行测试。它看起来像这样:

  #!/usr/bin/env python
  from gevent.server import StreamServer
  from gevent.pool import Pool

  def handle(socket, address):
       while True:
           print socket.recv(1024)

  pool = Pool(20000)
  server = StreamServer(('0.0.0.0', 9999), handle, spawn=pool)
  server.serve_forever()

下一项措施是从nc (host1)发送到gserver (host2)

host1:cat some_big_file | nc host2 9999 host2:./gserver.py | pv > /dev/null

host2上的输出:[ 101MB/s]。还不错。

但是,当我使用我的python客户端时,它的速度很慢。我将客户端切换到gevent。我已经尝试了几个greenlets。 1,10,100,1000 - 它没有太大帮助,我可以通过一个python进程到达20MB/s或者用{2,3}进行2,3,4,5个单独的python进程,它&# 39; s s something,但仍然不那么好)。仍然很慢。我把客户改写成笨蛋,就像这样:

~30MB/s

通过这种方法,我可以达到#!/usr/bin/env python import sys import socket c = socket.create_connection((sys.argv[1], sys.argv[2])) while 1: c.send('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n') 。我也尝试了将整个大10MB/s文件读取到内存并发送它的方法,类似的结果。

我还尝试将python脚本作为单独的进程运行(使用2GB)。如果我使用了1个进程,我可以访问tmux,2个进程10MB/s,3个进程20MB/s,4,5,6个进程没有更改任何内容(使用{{1}进行测试版本和简单的一个)。

详细说明: Python的2.7.3 Debian 7 - 标准安装 计算机是AWS实例,客户端是c1.medium,服务器是c3.xlarge。 nc和iperf在机器之间测得1Gb / s。

问题:

  1. 为什么我可以使用python服务器(gevent服务器)快速接收大量数据,但即使C程序可以,也无法以相同的速度发送。
  2. 为什么加倍进程不会将发送速度提高到极限,只会达到某个值。
  3. 有没有办法使用套接字在python中快速发送数据?

1 个答案:

答案 0 :(得分:7)

问题不在于网络速度慢 - python函数调用有很多开销。如果你多次拨打connection.send,那么你在函数调用上会浪费大量的CPU时间。

在我的计算机上,您的程序平均大约35 MB / s。做一个简单的修改,我得到450 MB / s:

#...
c.send('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'*10+'\n')

我可以通过一次发送更多数据来达到超过1GB / s的速度。

如果您想最大限度地提高吞吐量,您应该通过一次调用send发送尽可能多的数据。一种简单的方法是在发送最终结果之前连接几个字符串。如果你这样做,请记住python字符串是不可变的,因此连续的字符串连接(使用大字符串)很慢。您希望改为使用bytearray