私のアプリケーションでは、2 つの小さなメッセージをサーバー (memcached のようなサービス) に送信します。Python ライクな擬似コードでは、次のようになります。
sock.send("add some-key 0")
ignored = sock.recv(...)
sock.send("incr some-key 1")
new_value = sock.recv(...)
サーバーはファイア アンド フォーゲット スタイルの書き込みをサポートしているため、このコードを次のように最適化できます。
sock.send("add some-key 0 noreply")
sock.send("incr some-key 1")
new_value = sock.recv(...)
ただし、これにはかなり長い時間がかかります。前者の平均 1 ミリ秒未満に対して、このバージョンでは平均 40 ミリ秒です。
TCP_NODELAY
さらに、ソケットをで作成して Nagle のアルゴリズムを無効にすると、2 番目のスニペットのタイミングが最初のスニペットと似ていることに気付きました。これは、2 つの 間で遅延が発生していることを示していますsend()
(「書き込み-書き込み-読み取り」問題)。
私は、Nagle を無効にすることが私のアプリケーションにとって正しい動きであると合理的に確信しています - 私は可能な限り少ないレイテンシーで処理しなければならないかなり小さな書き込みをかなり大量に持っています - しかしなぜそうしなかったのか分かりません。最初の例で必要です。recv()
カーネルにバッファリングされた書き込みを強制的に送信しますか? これは本当だと思いますが、その趣旨の文書をどこにも見つけることができませんでした。
(これは Linux 2.6.32 と Python 2.6.8 を使用した glibc 2.12 であることに注意してください。いずれかが答えに関係している場合に備えて)