我正在开发一个允许在一台机器上模拟网络的程序。为此,我使用Twisted进行异步I / O,因为每个'连接'都有一个线程可能有点多。 (我还使用他们的NIO在Java中实现了类似的程序)。但是,随着我对模拟网络规模的扩展,Twisted上的吞吐量会降低。将其与Java实现进行比较时,对于相同的网络大小,Java吞吐量会继续增长。 (增长率放缓,但仍然是增长)。 例如。 (Python 100个节点= 58MB总吞吐量,300个节点= 45MB,Java 100个节点= 24 MB,300个节点= 56MB)。
我想知道是否有人对为什么会发生这种情况有任何建议?
我能想到的唯一原因是Java的每个'peer'都在自己的线程中运行(它包含自己的监视对等连接的选择器)。在python版本中,所有内容都在reactor(以及随后的一个选择器)中注册。随着python的扩展,一个选择器无法快速响应。然而,这只是一个猜测,如果任何人有任何更多的具体信息,它将被appriciated。
编辑: 我按照Jean-Paul Calderone的建议进行了一些测试,结果发布在imgur。对于那些可能想知道测试报告以下Avg吞吐量的人。 (使用cProfile完成分析,测试运行60秒)
Epoll反应器: 100个对等方:20.34 MB,200个对等方:18.84 MB,300个对等方:17.4 MB选择Reactor: 100对等人:18.86 MB,200对等人:19.08 MB,300对等人:16.732 MB
对于报告的吞吐量而言似乎上下的一些事情是对main.py:48(send)的调用,但这种腐蚀并不是一个惊喜,因为这是发送数据的地方。 / p>
对于两个反应器,套接字上的send函数花费的时间随着吞吐量的减少而增加,并且随着吞吐量的减少,对send函数的调用次数也减少。 (即:在套接字上发送的时间更长,在套接字上发送的呼叫次数更少。)例如对于413600个呼叫,100个对等体上的epoll {方法'发送''_socket.socket'对象}为2.5秒,对于300个对等体上的epoll为5.5秒,对于354300个呼叫。
为了尝试回答原始问题,这些数据是否似乎指向选择器是一个限制因素?在Selector中花费的时间似乎随着对等体数量的增加而减少(如果选择器减慢了一切,那么人们不会期望内部花费的时间会增加吗?)还有什么可能会减慢发送的数据量? (数据的发送只是一次又一次向reactor.calllater注册的每个对等体的一个函数。那就是main.py:49(发送))
答案 0 :(得分:1)
尝试在不同的并发级别上分析应用程序,并在添加更多连接时查看哪些内容变慢。
select
可能是候选人;如果您发现添加连接的时间越来越多,请尝试使用using the poll
or epoll
reactor。