python - 如何加速python网络?

标签 python performance sockets python-2.7 network-programming

我发现 python 网络

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

主机 1(客户端): cat some_big_file | nc 主机 2 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 主机 2 9999 主机 2:./gserver.py | pv >/dev/null

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

但是,当我使用我的 python 客户端时,它仍然很慢。我将客户端切换到 gevent 。我尝试了几个 greenlets。 1、10、100、1000 - 它没有太大帮助,我可以用一个 python 进程达到 20MB/s~30MB/s 2、3、 4、5 个独立的 python 进程,这是一些东西,但仍然不是很好)。还是很慢。我已经将客户端重写为愚蠢的,如下所示:

#!/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。我还尝试了将整个大 2GB 文件读取到内存并将其发送的方法,结果类似。

我还尝试将 python 脚本作为单独的进程运行(使用 tmux)。如果我使用 1 个进程,我可以达到 10MB/s,2 个进程 20MB/s,3 个进程 23MB/s, 4, 5, 6进程没有改变任何东西(使用 gevent 版本和简单版本测试)。

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

问题:

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

最佳答案

问题不在于网络速度慢——python 函数调用有很多开销。如果您多次调用 connection.send,您将在函数调用上浪费大量 CPU 时间。

在我的电脑上,您的程序平均速度约为 35 MB/s。做一个简单的修改,我得到 450 MB/s:

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

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

如果您想最大化吞吐量,您应该在一次调用 send 时发送尽可能多的数据。一种简单的方法是在发送最终结果之前连接几个字符串。如果这样做,请记住 python 字符串是不可变的,因此连续的字符串连接(大字符串)很慢。您需要改用 bytearray

关于python - 如何加速python网络?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23249222/

相关文章:

python - 如何使用冗长的 Python 打印函数的开始和结束?

python - 为什么我在使用 Dataflow 管道时遇到 "Error syncing pod"?

使用 CPU 和 GPU 添加数组的 Java 基准测试并比较性能

c++ - 在 C++ 中以高性能将 double 转换为 char*

linux - 为什么你会在 addr 和 addrlen 设置为 0 的情况下调用 accept()?

java - getLocalAddress() 返回 0.0.0.0

python - 我可以在守护进程中运行pika的connection.ioloop.start()吗?

c# - 我是否仍应在 .NET 4.0 中使用 BinaryFormatter 进行简单序列化?

c - SSL_read 无限期阻塞

python - 实现 train_test_split 时出现 ValueError