poundjs

node.js load testing client and server

#pound

Pound is a load testing client which generates N requests to specified urls. Pound also provides a light-weight server setup so you can determine the processing power of node.

Client: Macbook Pro Mid 2012 10.7.5. 8GB RAM, SATA HD, 2.3 GHz Intel Core i7

Server: Hackintosh 10.6.8. 16GB RAM, SSD Hard drive, 3.31 GHz Intel Core i5

Node --version : v0.10.15

Network: Local wifi. Wireless N.

high amount of requests and throughput.

(result is when hitting pound server with clusterServer=true)

ulimit -n 10240
pound url=192.168.0.130 port=9090 numberOfRequests=150000 burstIntervalMs=90
requestsPerBurst=12000 sendRequestsInBursts=true useAgents=true agentMaxSockets=12000 
agentEveryNrequests=12000 connectionHeader='keep-alive'

Results in:

pound completed 150000 requests in 28588 ms. 
received responses: 150000. 
highest number of open connections was: 240. 
request errors: 0
requests per second: 5246.956765076256. 
responses per second: 5246.956765076256

Sending N requests as fast as possible every X milliseconds.

Each connection is closed.

ulimit -n 10240
pound url=192.168.0.130 port=9090 numberOfRequests=10000 burstIntervalMs=90
 requestsPerBurst=120 useAgents=true sendRequestsInBursts=true

Results in:

pound completed 10000 requests in 8339 ms. 
received responses: 10000. 
highest number of open connections was: 1. 
request errors: 0
requests per second: 1199.328376109379. 
responses per second: 1199.328376109379

Using command

ulimit -n 10240
pound url=192.168.0.130 port=9090 numberOfRequests=10000 requestsPerSecond=1000 useAgents=true

Results in:

pound completed 10000 requests in 13075 ms.
received responses: 10000.
highest number of open connections was: 1.
request errors: 0
requests per second: 764.81835556405354.
responses per second: 764.81835556405354

NOTE: Performance does seem to degrade over time. with 20000 requests, requests per second got up to ~765, but usually ends up around ~525.

NOTE: this option will start getting ECONNRESET on requests when numberOfRequests is over 150.

ulimit -n 10240
pound url=192.168.0.130 port=9090 numberOfRequests=150

Results in:

pound completed 150 requests in 98 ms. 
received responses: 150. 
highest number of open connections was: 1. 
request errors: 0
requests per second: 1530.612244897959. 
responses per second: 1530.612244897959
sudo npm install -g poundjs

You can use pound from the terminal to generate requests to a given url. For example, we can generate 200 requests to www.google.com by running the following:

pound url=www.google.com numberOfRequests=200

should result in a message like:

pound completed 200 requests in 25186 ms. highest number of open connections was 191. request errors: 14

If you want more than 256 simultaneous requests to be open at a time, you'll need to first run this command in the terminal you're running pound in:

ulimit -n 257
pound url=www.google.com numberOfRequests=257

ulimit will allow up to 10240 open sockets/requests at a time. If you need more than that, you can run the following:

$ sysctl kern.maxfiles
kern.maxfiles: 12288
$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240
$ sudo sysctl -w kern.maxfiles=1048600
kern.maxfiles: 12288 -> 1048600
$ sudo sysctl -w kern.maxfilesperproc=1048576
kern.maxfilesperproc: 10240 -> 1048576
 
### IN A NEW TERMINAL ########
$ ulimit -S -n
256
$ ulimit -S -n 1048576
$ ulimit -S -n
1048576

If you don't wish to wait for all the responses to finish, you can ctrl+c to exit and still get the status message.

All options via the terminal should be space separated, in a name=value format.

e.g.

pound url=www.google.com port=80 numberOfRequests=10

The url to the resource you wish the client to request.

Do not prepend 'http://' as it is not needed and will cause an error.

Paths and query string params are fine.

If you do not supply a url, a random url from a predefined array of urls will be used.

pound url=www.example.com/someFile.js?q=true

default: predefined array of urls

not supported from the command line yet.

default: 80

the port to use when connecting to a server/url.

default: GET

the request method you wish to use. should be in upper case.

default: 200

The number of requests you wish to be immediately created, as quickly as possible, to the provided url or set of urls.

default: disabled

If set, an interval will be created to send N requests per second instead of sending them all at once.

Requests will be created evenly over the course of a second. ie. 1 request every N ms.

Note: you may not be able to get down to sub-milliseconds with this option.

Note: not valid when sending requests in bursts. see sendRequestsInBursts

default: disabled

Instead of evenly distributing requests evenly over the course of a second (see requestsPerSecond), this option will send requestsPerBurst requests all at once, every burstIntervalMs.

default: 200 (only used when sendRequestsInBursts is true)

This amount of requests will be sent all at once every burstIntervalMs.

Useful for tweaking to find the max requests that you can send as fast as possible.

default: 200 (only used when sendRequestsInBursts is true)

Bursts of requests will be sent every N milliseconds.

Useful for tweaking to find the max requests that you can send as fast as possible.

default: 'close'

The connection request header value. setting to 'keep-alive' will allow more throughput.

default: false

If set to true, an http agent will be created and used for a set of requests, instead of using the default global agent.

default: 20 (only used when useAgents=true)

a new agent will be created and used every N requests.

default: 20 (only used when useAgents=true)

max sockets set for each new agent created.

default: 10,000

the value which should be assigned to http.globalAgent.maxSockets.

default: 5

prints out total requests, responses received, etc. every N seconds. Useful when you need visibility into what's going on for high number of requests.

NOTE: these are running totals, and not just the totals for the status update interval.

see https://github.com/jasonmcaffee/pound/issues/2

see https://github.com/jasonmcaffee/pound/issues/1

To start the pound server, pass 'server=true' to pound:

pound server=true

By default the server will listen on port 9090

The server will simply respond with a text/plain body which will tell you the request number

pound server received request number: 48

NOTE: 2 requests are issued when you load the server url in your browser. The extra one is for the favicon.

NOTE: see the MAC OS Limits section above if you wish to process more than 256 requests at a time.

default: false

set to true if you wish to start the server

default: 9090

the port you wish the server to listen on.

default: false

uses the experimental cluster api to fork the server across all cpus on the box.

default: 10,000

the value which should be assigned to http.globalAgent.maxSockets.

default: false

when true, console logs won't be written for each request received. (the terminal can eat up 99% cpu when logging lots of requests)

you can process several hundreds more requests per second when silent=true

  • websocket support
  • configuration file for pounding multiple urls. e.g. pound config=/Users/me/poundConfig.js
  • use clustering or workers for client to allow for higher requests per second.