「ab」を使用して Web サーバーのベンチマークを実行すると、大量のリクエストを送信した後、しばらくの間フリーズし、20 秒ほど後に続行します。
Ruby で記述された次の HTTP サーバー シミュレーターを考えてみましょう。
require 'socket'
RESPONSE = "HTTP/1.1 200 OK\r\n" +
"Connection: close\r\n" +
"\r\n" +
"\r\n"
buffer = ""
server = TCPServer.new("127.0.0.1", 3000) # Create TCP server at port 3000.
server.listen(1024) # Set backlog to 1024.
while true
client = server.accept # Accept new client.
client.write(RESPONSE) # Write a stock "HTTP" response.
client.close_write # Shutdown write part of the socket.
client.read(nil, buffer) # Read all data from the socket.
client.close # Close it.
end
次に、次のように ab を実行します。
ab -n 45000 -c 10 http://127.0.0.1:3000/
最初の数秒間、ab は想定どおりにジョブを実行し、CPU を 100% 使用します。
Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests
約 13500 のリクエストの後、システムの CPU 使用率は 0% に低下します。ab は何かに固まっているようです。この時点で、サーバーは accept() を呼び出しているため、問題はサーバーにはありません。約 20 秒後、ab は何も起こらなかったかのように続行し、再び 100% の CPU を使用しますが、数秒後に再びフリーズするだけです。
カーネル内の何かが接続を調整していると思われますが、何が原因でしょうか? OS X Leopard を使用しています。Linux でも同様の動作が見られましたが、フリーズははるかに多くのリクエストで発生し、それほど頻繁には発生しません。
この問題により、大規模な HTTP ベンチマークを実行できません。