Whenever I use 'ab' to benchmark a web server, it will freeze for a while after having sent lots of requests, only to continue after 20 seconds or so.
Consider the following HTTP server simulator, written in Ruby:
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
I then run ab as follows:
ab -n 45000 -c 10 http://127.0.0.1:3000/
During the first few seconds, ab does its job as it's supposed to and uses 100% CPU:
Benchmarking 127.0.0.1 (be patient)
Completed 4500 requests
Completed 9000 requests
Completed 13500 requests
After about 13500 requests, system CPU usage drops to 0%. ab seems to be frozen on something. The problem is not in the server because at this moment, the server is calling accept(). After about 20 seconds ab continues as if nothing happened, and will use 100% CPU again, only to freeze again after several seconds.
I suspect something in the kernel is throttling connections, but what and why? I'm using OS X Leopard. I've seen similar behavior on Linux as well, though the freeze happens at a much larger number of requests and doesn't happen so often.
This problem prevents me from running large HTTP benchmarks.