Skip to content

Commit

Permalink
add script setup() and thread methods
Browse files Browse the repository at this point in the history
  • Loading branch information
wg committed Feb 21, 2015
1 parent 6f0aa32 commit 9b84d3e
Show file tree
Hide file tree
Showing 14 changed files with 385 additions and 152 deletions.
6 changes: 5 additions & 1 deletion CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
master
wrk next

* The wrk global variable is the only global defined by default.
* wrk.init() calls the global init(), remove calls to wrk.init().
* Add wrk.lookup(host, port) and wrk.connect(addr) functions.
* Add setup phase that calls the global setup() for each thread.
* Allow assignment to thread.addr to specify the server address.
* Add thread:set(key, value), thread:get(key), and thread:stop().
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ifeq ($(TARGET), sunos)
else ifeq ($(TARGET), darwin)
LDFLAGS += -pagezero_size 10000 -image_base 100000000
else ifeq ($(TARGET), linux)
CFLAGS += -D_POSIX_C_SOURCE=200112L -D_BSD_SOURCE
LIBS += -ldl
LDFLAGS += -Wl,-E
else ifeq ($(TARGET), freebsd)
Expand Down
71 changes: 5 additions & 66 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ wrk - a HTTP benchmarking tool
design with scalable event notification systems such as epoll and kqueue.

An optional LuaJIT script can perform HTTP request generation, response
processing, and custom reporting. Several example scripts are located in
scripts/
processing, and custom reporting. Details are available in SCRIPTING and
several examples are located in scripts/

Basic Usage

Expand All @@ -26,65 +26,6 @@ Basic Usage
Requests/sec: 748868.53
Transfer/sec: 606.33MB

Scripting

wrk's public Lua API is:

init = function(args)
request = function()
response = function(status, headers, body)
done = function(summary, latency, requests)

wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil
}

function wrk.format(method, path, headers, body)

wrk.format returns a HTTP request string containing the passed
parameters merged with values from the wrk table.

The following globals are optional, and if defined must be functions:

global init -- called when the thread is initialized
global request -- returning the HTTP message for each request
global response -- called with HTTP response data
global done -- called with results of run

The init() function receives any extra command line arguments for the
script which must be separated from wrk arguments with "--".

The done() function receives a table containing result data, and two
statistics objects representing the sampled per-request latency and
per-thread request rate. Duration and latency are microsecond values
and rate is measured in requests per second.

latency.min -- minimum value seen
latency.max -- maximum value seen
latency.mean -- average value seen
latency.stdev -- standard deviation
latency:percentile(99.0) -- 99th percentile value
latency[i] -- raw sample value

summary = {
duration = N, -- run duration in microseconds
requests = N, -- total completed requests
bytes = N, -- total bytes received
errors = {
connect = N, -- total socket connection errors
read = N, -- total socket read errors
write = N, -- total socket write errors
status = N, -- total HTTP status codes > 399
timeout = N -- total request timeouts
}
}

Benchmarking Tips

The machine running wrk must have a sufficient number of ephemeral ports
Expand All @@ -93,11 +34,9 @@ Benchmarking Tips
than the number of concurrent connections being tested.

A user script that only changes the HTTP method, path, adds headers or
a body, will have no performance impact. If multiple HTTP requests are
necessary they should be pre-generated and returned via a quick lookup in
the request() call. Per-request actions, particularly building a new HTTP
request, and use of response() will necessarily reduce the amount of load
that can be generated.
a body, will have no performance impact. Per-request actions, particularly
building a new HTTP request, and use of response() will necessarily reduce
the amount of load that can be generated.

Acknowledgements

Expand Down
112 changes: 112 additions & 0 deletions SCRIPTING
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
Overview

wrk supports executing a LuaJIT script during three distinct phases: setup,
running, and done. Each wrk thread has an independent scripting environment
and the setup & done phases execute in a separate environment which does
not participate in the running phase.

The public Lua API consists of a global table and a number of global
functions:

wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = <userdata>,
}

function wrk.format(method, path, headers, body)

wrk.format returns a HTTP request string containing the passed parameters
merged with values from the wrk table.

function wrk.lookup(host, service)

wrk.lookup returns a table containing all known addresses for the host
and service pair. This corresponds to the POSIX getaddrinfo() function.

function wrk.connect(addr)

wrk.connect returns true if the address can be connected to, otherwise
it returns false. The address must be one returned from wrk.lookup().

The following globals are optional, and if defined must be functions:

global setup -- called during thread setup
global init -- called when the thread is starting
global request -- called to generate the HTTP request
global response -- called with HTTP response data
global done -- called with results of run

Setup

function setup(thread)

The setup phase begins after the target IP address has been resolved and all
threads have been initialized but not yet started.

setup() is called once for each thread and receives a userdata object
representing the thread.

thread.addr - get or set the thread's server address
thread:get(key) - get the value of a global in the thread's env
thread:set(key, value) - set the value of a global in the thread's env
thread:stop() - stop the thread

Only boolean, nil, number, and string values or tables of the same may be
transfered via get()/set() and thread:stop() can only be called while the
thread is running.

Running

function init(args)
function request()
function response(status, headers, body)

The running phase begins with a single call to init(), followed by
a call to request() and response() for each request cycle.

The init() function receives any extra command line arguments for the
script which must be separated from wrk arguments with "--".

request() returns a string containing the HTTP request. Building a new
request each time is expensive, when testing a high performance server
one solution is to pre-generate all requests in init() and do a quick
lookup in request().

response() is called with the HTTP response status, headers, and body.
Parsing the headers and body is expensive, so if the response global is
nil after the call to init() wrk will ignore the headers and body.

Done

function done(summary, latency, requests)

The done() function receives a table containing result data, and two
statistics objects representing the sampled per-request latency and
per-thread request rate. Duration and latency are microsecond values
and rate is measured in requests per second.

latency.min -- minimum value seen
latency.max -- maximum value seen
latency.mean -- average value seen
latency.stdev -- standard deviation
latency:percentile(99.0) -- 99th percentile value
latency[i] -- raw sample value

summary = {
duration = N, -- run duration in microseconds
requests = N, -- total completed requests
bytes = N, -- total bytes received
errors = {
connect = N, -- total socket connection errors
read = N, -- total socket read errors
write = N, -- total socket write errors
status = N, -- total HTTP status codes > 399
timeout = N -- total request timeouts
}
}
22 changes: 22 additions & 0 deletions scripts/addr.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- example script that demonstrates use of setup() to pass
-- a random server address to each thread

local addrs = nil

function setup(thread)
if not addrs then
addrs = wrk.lookup(wrk.host, wrk.port or "http")
for i = #addrs, 1, -1 do
if not wrk.connect(addrs[i]) then
table.remove(addrs, i)
end
end
end

thread.addr = addrs[math.random(#addrs)]
end

function init(args)
local msg = "thread addr: %s"
print(msg:format(wrk.thread.addr))
end
38 changes: 38 additions & 0 deletions scripts/setup.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
-- example script that demonstrates use of setup() to pass
-- data to and from the threads

local counter = 1
local threads = {}

function setup(thread)
thread:set("id", counter)
table.insert(threads, thread)
counter = counter + 1
end

function init(args)
requests = 0
responses = 0

local msg = "thread %d created"
print(msg:format(id))
end

function request()
requests = requests + 1
return wrk.request()
end

function response(status, headers, body)
responses = responses + 1
end

function done(summary, latency, requests)
for index, thread in ipairs(threads) do
local id = thread:get("id")
local requests = thread:get("requests")
local responses = thread:get("responses")
local msg = "thread %d made %d requests and got %d responses"
print(msg:format(id, requests, responses))
end
end
10 changes: 10 additions & 0 deletions scripts/stop.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- example script that demonstrates use of thread:stop()

local counter = 1

function response()
if counter == 100 then
wrk.thread:stop()
end
counter = counter + 1
end
1 change: 0 additions & 1 deletion src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#define HAVE_KQUEUE
#elif defined(__linux__)
#define HAVE_EPOLL
#define _POSIX_C_SOURCE 200809L
#elif defined (__sun)
#define HAVE_EVPORT
#endif
Expand Down
1 change: 0 additions & 1 deletion src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>

Expand Down
Loading

0 comments on commit 9b84d3e

Please sign in to comment.