単一のマシンでネットワークのシミュレーションを可能にするプログラムを開発しています。このために、非同期 I/O に Twisted を使用しています。「接続」ごとにスレッドを使用するのは少し面倒かもしれません。(NIO を使用して Java で同様のプログラムを実装したこともあります)。ただし、エミュレートされたネットワークのサイズを拡大すると、Twisted のスループットが低下します。これを Java の実装と比較すると、ネットワーク サイズが同じ場合、Java のスループットは増加し続けています。(成長率は鈍化しますが、それでも増加しています)。例 (Python 100 ノード = 58MB 合計スループット、300 ノード = 45MB、Java 100 ノード = 24 MB、300 ノード = 56MB)。
なぜこれが起こっているのかについて何か提案があるかどうか疑問に思っていますか?
私が考えることができる唯一の理由は、Java の場合、それぞれの「ピア」が独自のスレッド (ピア接続を監視する独自のセレクターを含む) で実行されていることです。Python バージョンでは、すべてがリアクター (およびその後の 1 つのセレクター) に登録されます。Python がスケールアップすると、1 つのセレクターはそれほど速く応答できなくなります。ただし、これは単なる推測に過ぎません。具体的な情報があれば、それは評価されるでしょう。
編集: Jean-Paul Calderone の提案に従っていくつかのテストを実行しました。結果はimgurに投稿されています。次の平均スループットがテストで報告されたことに疑問を持っているかもしれません。(プロファイリングは cProfile で行われ、テストは 60 秒間実行されました)
Epoll Reactor: 100 ピア: 20.34 MB、200 ピア: 18.84 MB、300 ピア: 17.4 MB
リアクターの選択: 100 ピア: 18.86 MB、200 ピア: 19.08 MB、300 ピア: 16.732 MB
報告されたスループットで上下するように見えたいくつかのことは、main.py:48(send) への呼び出しでしたが、データが送信されている場所であるため、この相関はそれほど驚くべきことではありません。
どちらのリアクターでも、スループットが低下するとソケットの送信関数に費やされる時間が増加し、スループットが低下すると送信関数の呼び出し回数が減少しました。(つまり、ソケットでの送信により多くの時間が費やされ、ソケットで送信するための呼び出しが少なくなりました。)たとえば、413600 呼び出しの 100 ピアでの epoll {'_socket.socket' オブジェクトのメソッド 'send'} で 2.5 秒、5.5 秒354300 コールの 300 ピアでの epoll の場合は 1 秒。
元の質問に答えようとすると、このデータはセレクターが制限要因であることを示しているように見えますか? セレクターで費やされる時間は、ピアの数が増えるにつれて減少するようです (セレクターがすべてを遅くしている場合、内部で費やされる時間が増えるとは思わないでしょうか?) 送信されるデータの量を遅くしている可能性のあるものは他にありますか? ? (データの送信は、reactor.calllater に何度も登録されているピアごとに 1 つの関数にすぎません。それが main.py:49 (送信) です)