Operations 14 min read

Master HTTP Load Testing with wrk: Install, Commands, and Lua Scripting

This guide walks you through installing the wrk load‑testing tool on Unix‑like systems, explains its core command‑line options, shows how to interpret benchmark results, and demonstrates advanced customization using Lua scripts for POST requests, dynamic parameters, authentication, and HTTP pipelining.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Master HTTP Load Testing with wrk: Install, Commands, and Lua Scripting

Having tried many load‑testing tools without finding a favorite, I tested wrk and found it useful, so I wrote this usage guide as a personal reference that may also help others.

Installation

wrk runs on most Unix‑like systems (not Windows) and requires LuaJIT and OpenSSL support, which are available on most platforms. Install it by cloning the source from GitHub and running make in the project directory.

git clone https://github.com/wg/wrk

make

After make, the executable wrk appears in the current directory. Copy it to a directory in your PATH (e.g., /usr/local/bin) to run it from anywhere.

If you prefer to use the system‑installed LuaJIT and OpenSSL, specify their locations with the WITH_LUAJIT and WITH_OPENSSL options, for example:

make WITH_LUAJIT=/usr WITH_OPENSSL=/usr

Basic Usage

Run wrk without arguments to see the help message.

Usage: wrk <options> <url>
  Options:
    -c, --connections <N>   Connections to keep open
    -d, --duration <T>      Duration of test
    -t, --threads <N>       Number of threads to use
    -s, --script <S>        Load Lua script file
    -H, --header <H>        Add header to request
        --latency           Print latency statistics
        --timeout <T>       Socket/request timeout
    -v, --version           Print version details

Numeric arguments may include SI units (1k, 1M, 1G).
Time arguments may include a time unit (2s, 2m, 2h).

In Chinese the options are:

使用方法: wrk <选项> <被测HTTP服务的URL>
Options:
  -c, --connections <N>  跟服务器建立并保持的TCP连接数量
  -d, --duration <T>    压测时间
  -t, --threads <N>      使用多少个线程进行压测
  -s, --script <S>       指定Lua脚本路径
  -H, --header <H>       为每一个HTTP请求添加HTTP头
      --latency          在压测结束后,打印延迟统计信息
      --timeout <T>      超时时间
  -v, --version          打印正在使用的wrk的详细版本信息

Check the version:

wrk -v

输出:
wrk 4.0.2 [epoll] Copyright (C) 2012 Will Glozer

The output shows wrk 4.0.2 compiled with epoll, meaning it can create many connections with few threads.

Run a simple benchmark and analyze the result:

wrk -t8 -c200 -d30s --latency "http://www.bing.com"

输出:
Running 30s test @ http://www.bing.com
  8 threads and 200 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    46.67ms  215.38ms   1.67s    95.59%
    Req/Sec     7.91k     1.15k   10.26k    70.77%
  Latency Distribution
     50%    2.93ms
     75%    3.78ms
     90%    4.73ms
     99%    1.35s
  1790465 requests in 30.01s, 684.08MB read
Requests/sec:  59658.29
Transfer/sec:     22.79MB

The benchmark used 8 threads and 200 connections for 30 seconds against Bing's homepage, printing latency statistics. Key points:

Running 30s test @ http://www.bing.com (压测时间30s)
  8 threads and 200 connections (共8个测试线程,200个连接)
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    46.67ms  215.38ms   1.67s    95.59% (延迟)
    Req/Sec     7.91k     1.15k   10.26k    70.77% (处理中的请求数)
  Latency Distribution (延迟分布)
     50%    2.93ms
     75%    3.78ms
     90%    4.73ms
     99%    1.35s (99分位的延迟)
  1790465 requests in 30.01s, 684.08MB read (30.01秒内共处理完成了1790465个请求,读取了684.08MB数据)
Requests/sec:  59658.29 (平均每秒处理完成59658.29个请求)
Transfer/sec:     22.79MB (平均每秒读取数据22.79MB)

wrk is easy to use, produces clear results, and thanks to its non‑blocking I/O can generate many connections on a modest machine.

Customizing wrk with Lua Scripts

Simple tests may not meet all scenarios. wrk allows a Lua script (specified with --script) to customize the load test, enabling POST methods, dynamic parameters, authentication, and HTTP pipelining.

Lua script support overview

wrk provides three hook phases: setup (executed once per thread before it starts), init/delay/request/response (executed during the run), and done (executed once after the test).

Setup Phase

function setup(thread)

The setup function runs after a thread is created but before it starts. It receives a thread object that can be inspected or modified.

thread.addr            -- get or set the thread's server address
thread:get(name)       -- get a global variable in the thread's env
thread:set(name, val)  -- set a global variable in the thread's env
thread:stop()          -- stop the thread

Run Phase

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

runs once per thread at the start of the run and can read command‑line arguments. delay is called before each request; returning a number inserts that many milliseconds of pause. request must return the HTTP request string and is called for every request. response is invoked for each response; omitting it skips header/body parsing for speed.

Done Phase

function done(summary, latency, requests)

Called once after the whole test, allowing custom reporting based on the provided summary objects.

Accessible Variables and Methods

The global wrk table holds request defaults:

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

Modifying this table affects all generated requests. Useful functions include wrk.format, wrk.lookup, and wrk.connect:

function wrk.format(method, path, headers, body)
    -- returns an HTTP request string merged with values from the wrk table
end

function wrk.lookup(host, service)
    -- returns a table of all known addresses for the host/service pair (POSIX getaddrinfo)
end

function wrk.connect(addr)
    -- returns true if the address can be connected, false otherwise
end

Examples

Using POST Method

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

All requests will now use POST with the specified body and header.

Randomizing a Parameter per Request

request = function()
   uid = math.random(1, 10000000)
   path = "/test?uid=" .. uid
   return wrk.format(nil, path)
end

This generates a random uid between 1 and 10,000,000 for each request.

Adding a 10 ms Delay Before Each Request

function delay()
   return 10
end

Authentication Followed by Token‑Based Requests

token = nil
path  = "/authenticate"

request = function()
   return wrk.format("GET", path)
end

response = function(status, headers, body)
   if not token and status == 200 then
      token = headers["X-Token"]
      path = "/resource"
      wrk.headers["X-Token"] = token
   end
end

The script first calls /authenticate, extracts the X-Token header, then switches to /resource with the token attached.

Testing an HTTP‑Pipeline‑Enabled Service

init = function(args)
   local r = {}
   r[1] = wrk.format(nil, "/?foo")
   r[2] = wrk.format(nil, "/?bar")
   r[3] = wrk.format(nil, "/?baz")
   req = table.concat(r)
end

request = function()
   return req
end

The init function concatenates three request strings, so each call to request sends them together, exercising HTTP pipelining.

Conclusion

The source code of wrk is concise; reading it gives a strong appreciation for its design and the author's skill.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceLoad TestingHTTPtoolwrkLua scripting
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.