如何加速python网络?

如何加速python网络?,python,performance,sockets,python-2.7,network-programming,Python,Performance,Sockets,Python 2.7,Network Programming,我发现python的网络速度很慢 我有一个服务器(用C编写)。我用我的客户机(python)测试了它。 我可以达到2MB/s。这让我很担心,所以我检查了这个: 主机1(客户): cat some_big_file|nc host2 9999 主机2(服务器): nc-l 0.0.0.0 9999 | pv>/dev/null 我达到了大约120MB/s(1Gb) 服务器不是瓶颈,我们在生产中使用它,它可以处理更多问题。但是为了测试,我复制了简单的pythongeventserver。看起来是这样

我发现python的网络速度很慢

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

主机1(客户):
cat some_big_file|nc host2 9999

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

我达到了大约120MB/s(1Gb)

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

  #!/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()
#!/usr/bin/env python
import sys
import socket

c = socket.create_connection((sys.argv[1], sys.argv[2]))
while 1:
        c.send('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n')
下一个措施是从
nc(主机1)
发送到
gserver(主机2)

主机1:
cat some_big_文件| nc host2 9999
host2:
/gserver.py | pv>/dev/null

主机2上的输出:
[101MB/s]
。不错

但是,当我使用python客户端时,它仍然很慢。我将客户端切换到
gevent
。我已经尝试了几个greenlet。1、10、100、1000-这没有太大帮助,我可以通过一个python进程达到
20MB/s
,或者
~30MB/s
对于2、3、4、5个单独的python进程来说,这是一件好事,但仍然不太好)。还是慢。我把客户改写成了哑巴,就像这样:

  #!/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()
#!/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

问题:

  • 为什么我可以使用python服务器(gevent服务器)快速接收大量数据,但即使C程序可以,也不能以相同的速度发送数据
  • 为什么将进程加倍并不能将发送速度提高到极限,只能提高到某个值
  • 有没有任何方法可以使用套接字在python中快速发送数据

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

    在我的电脑上,你的程序平均速度约为35MB/s。通过简单的修改,我得到了450 MB/s:

    #...
    c.send('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'*10+'\n')
    
    通过一次发送更多数据,我可以达到1GB/s以上的速度


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

    “我发现python网络速度很慢”
    。不,您发现您的应用程序(碰巧是用Python编写的)很慢。@JonathonReinhart是的,您是对的。。。但我尝试了不同的方法,因此选择了这种快捷方式。即使您尝试在C(甚至汇编)中一次发送几个字节的内容,也会很慢,因为系统调用开销会严重限制您将数据传递到内核的速度。@goncalopp,感谢您的良好解释和bytearray提示。另一点是
    缓冲区大小
    ,RTL8168具有8/16KB的片上内存(如L1、L2、L3缓存),从不通过
    以太网芯片内部缓冲区大小
    发送数据包。以太网芯片使用DMA,因此不能释放整个内置内存。我认为最大大小是
    1600字节
    数据中断
    很难,需要小心设置您的通信数据模式。我达到了40毫秒(发送+接收)的数据包时间,并使用了2个转换器(光纤到CAT6A)。缓冲区大小很重要,因为所有芯片都有更多的ns(纳秒)设置时间,可能小数据包更快,但芯片在发送和接收时有更多的延迟。继续>>继续>>使用大数据包时,需要快速内存+大CPU缓存+稳定CPU+稳定桥接CPU(如下所示:低FSB对您有好处,需要将每一步时钟设置转换为总线级)。这不仅仅是python或数据模式的问题,还包括系统的所有点(硬件、软件、电缆等)。也许nagle算法就是问题所在?()启用时,它会收集缓冲区中的数据,并在缓冲区足以发送数据时激发数据。当我在python上开发tcp代理时,它是问题的根源。试试看,也许会有帮助