1
0
mirror of https://github.com/wg/wrk synced 2026-06-10 00:55:51 +08:00

5 Commits

11 changed files with 112 additions and 42 deletions
+6 -6
View File
@@ -21,7 +21,7 @@ SRC := wrk.c net.c ssl.c aprintf.c stats.c script.c units.c \
BIN := wrk BIN := wrk
ODIR := obj ODIR := obj
OBJ := $(patsubst %.c,$(ODIR)/%.o,$(SRC)) OBJ := $(patsubst %.c,$(ODIR)/%.o,$(SRC)) $(ODIR)/bytecode.o
LDIR = deps/luajit/src LDIR = deps/luajit/src
LIBS := -lluajit $(LIBS) LIBS := -lluajit $(LIBS)
@@ -34,16 +34,16 @@ clean:
$(RM) $(BIN) obj/* $(RM) $(BIN) obj/*
@$(MAKE) -C deps/luajit clean @$(MAKE) -C deps/luajit clean
$(BIN): $(OBJ) $(ODIR)/bytecode.o $(BIN): $(OBJ)
@echo LINK $(BIN) @echo LINK $(BIN)
@$(CC) $(LDFLAGS) -o $@ $^ $(LIBS) @$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
$(OBJ): config.h Makefile | $(ODIR) $(OBJ): config.h Makefile $(LDIR)/libluajit.a | $(ODIR)
$(ODIR): $(LDIR)/libluajit.a $(ODIR):
@mkdir -p $@ @mkdir -p $@
$(ODIR)/bytecode.o: scripts/wrk.lua $(ODIR)/bytecode.o: src/wrk.lua
@echo LUAJIT $< @echo LUAJIT $<
@$(SHELL) -c 'cd $(LDIR) && ./luajit -b $(CURDIR)/$< $(CURDIR)/$@' @$(SHELL) -c 'cd $(LDIR) && ./luajit -b $(CURDIR)/$< $(CURDIR)/$@'
@@ -52,7 +52,7 @@ $(ODIR)/%.o : %.c
@$(CC) $(CFLAGS) -c -o $@ $< @$(CC) $(CFLAGS) -c -o $@ $<
$(LDIR)/libluajit.a: $(LDIR)/libluajit.a:
@echo Building LuaJit... @echo Building LuaJIT...
@$(MAKE) -C $(LDIR) BUILDMODE=static @$(MAKE) -C $(LDIR) BUILDMODE=static
.PHONY: all clean .PHONY: all clean
+2 -1
View File
@@ -5,7 +5,8 @@ wrk - a HTTP benchmarking tool
design with scalable event notification systems such as epoll and kqueue. design with scalable event notification systems such as epoll and kqueue.
An optional LuaJIT script can perform HTTP request generation, response An optional LuaJIT script can perform HTTP request generation, response
processing, and custom reporting. processing, and custom reporting. Several example scripts are located in
scripts/
Basic Usage Basic Usage
+18
View File
@@ -0,0 +1,18 @@
-- example script that demonstrates response handling and
-- retrieving an authentication token to set on all future
-- 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
+14
View File
@@ -0,0 +1,14 @@
-- example dynamic request script which demonstrates changing
-- the request path and a header for each request
-------------------------------------------------------------
-- NOTE: each wrk thread has an independent Lua scripting
-- context and thus there will be one counter per thread
counter = 0
request = function()
path = "/" .. counter
wrk.headers["X-Counter"] = counter
counter = counter + 1
return wrk.format(nil, path)
end
+16
View File
@@ -0,0 +1,16 @@
-- example script demonstrating HTTP pipelining
init = function(args)
wrk.init(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
+6
View File
@@ -0,0 +1,6 @@
-- example HTTP POST script which demonstrates setting the
-- HTTP method, body, and adding a header
wrk.method = "POST"
wrk.body = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
+10
View File
@@ -0,0 +1,10 @@
-- example reporting script which demonstrates a custom
-- done() function that prints latency percentiles as CSV
done = function(summary, latency, requests)
io.write("------------------------------\n")
for _, p in pairs({ 50, 90, 99, 99.999 }) do
n = latency:percentile(p)
io.write(string.format("%g%%,%d\n", p, n))
end
end
+1 -1
View File
@@ -38,7 +38,7 @@ SSL_CTX *ssl_init() {
CRYPTO_set_locking_callback(ssl_lock); CRYPTO_set_locking_callback(ssl_lock);
CRYPTO_set_id_callback(ssl_id); CRYPTO_set_id_callback(ssl_id);
if ((ctx = SSL_CTX_new(TLSv1_client_method()))) { if ((ctx = SSL_CTX_new(SSLv23_client_method()))) {
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
SSL_CTX_set_verify_depth(ctx, 0); SSL_CTX_set_verify_depth(ctx, 0);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+37 -33
View File
@@ -9,6 +9,7 @@ static struct config {
uint64_t connections; uint64_t connections;
uint64_t duration; uint64_t duration;
uint64_t timeout; uint64_t timeout;
uint64_t pipeline;
bool latency; bool latency;
bool dynamic; bool dynamic;
char *script; char *script;
@@ -145,7 +146,7 @@ int main(int argc, char **argv) {
script_init(t->L, cfg.script, argc - optind, &argv[optind]); script_init(t->L, cfg.script, argc - optind, &argv[optind]);
if (i == 0) { if (i == 0) {
script_verify_request(t->L); cfg.pipeline = script_verify_request(t->L);
cfg.dynamic = !script_is_static(t->L); cfg.dynamic = !script_is_static(t->L);
if (script_want_response(t->L)) { if (script_want_response(t->L)) {
parser_settings.on_header_field = header_field; parser_settings.on_header_field = header_field;
@@ -330,6 +331,26 @@ static int calibrate(aeEventLoop *loop, long long id, void *data) {
return AE_NOMORE; return AE_NOMORE;
} }
static int check_timeouts(aeEventLoop *loop, long long id, void *data) {
thread *thread = data;
connection *c = thread->cs;
uint64_t now = time_us();
uint64_t maxAge = now - (cfg.timeout * 1000);
for (uint64_t i = 0; i < thread->connections; i++, c++) {
if (maxAge > c->start) {
thread->errors.timeout++;
}
}
if (stop || now >= thread->stop_at) {
aeStop(loop);
}
return TIMEOUT_INTERVAL_MS;
}
static int sample_rate(aeEventLoop *loop, long long id, void *data) { static int sample_rate(aeEventLoop *loop, long long id, void *data) {
thread *thread = data; thread *thread = data;
@@ -386,8 +407,6 @@ static int response_complete(http_parser *parser) {
thread->complete++; thread->complete++;
thread->requests++; thread->requests++;
stats_record(thread->latency, now - c->start);
if (status > 399) { if (status > 399) {
thread->errors.status++; thread->errors.status++;
} }
@@ -403,40 +422,22 @@ static int response_complete(http_parser *parser) {
goto done; goto done;
} }
if (!http_should_keep_alive(parser)) goto reconnect; if (--c->pending == 0) {
stats_record(thread->latency, now - c->start);
aeCreateFileEvent(thread->loop, c->fd, AE_WRITABLE, socket_writeable, c);
}
if (!http_should_keep_alive(parser)) {
reconnect_socket(thread, c);
goto done;
}
http_parser_init(parser, HTTP_RESPONSE); http_parser_init(parser, HTTP_RESPONSE);
aeCreateFileEvent(thread->loop, c->fd, AE_WRITABLE, socket_writeable, c);
goto done;
reconnect:
reconnect_socket(thread, c);
done: done:
return 0; return 0;
} }
static int check_timeouts(aeEventLoop *loop, long long id, void *data) {
thread *thread = data;
connection *c = thread->cs;
uint64_t now = time_us();
uint64_t maxAge = now - (cfg.timeout * 1000);
for (uint64_t i = 0; i < thread->connections; i++, c++) {
if (maxAge > c->start) {
thread->errors.timeout++;
}
}
if (stop || now >= thread->stop_at) {
aeStop(loop);
}
return TIMEOUT_INTERVAL_MS;
}
static void socket_connected(aeEventLoop *loop, int fd, void *data, int mask) { static void socket_connected(aeEventLoop *loop, int fd, void *data, int mask) {
connection *c = data; connection *c = data;
@@ -449,8 +450,8 @@ static void socket_connected(aeEventLoop *loop, int fd, void *data, int mask) {
http_parser_init(&c->parser, HTTP_RESPONSE); http_parser_init(&c->parser, HTTP_RESPONSE);
c->written = 0; c->written = 0;
aeCreateFileEvent(c->thread->loop, c->fd, AE_READABLE, socket_readable, c); aeCreateFileEvent(c->thread->loop, fd, AE_READABLE, socket_readable, c);
aeCreateFileEvent(c->thread->loop, c->fd, AE_WRITABLE, socket_writeable, c); aeCreateFileEvent(c->thread->loop, fd, AE_WRITABLE, socket_writeable, c);
return; return;
@@ -478,7 +479,10 @@ static void socket_writeable(aeEventLoop *loop, int fd, void *data, int mask) {
case RETRY: return; case RETRY: return;
} }
if (!c->written) c->start = time_us(); if (!c->written) {
c->start = time_us();
c->pending = cfg.pipeline;
}
c->written += n; c->written += n;
if (c->written == c->length) { if (c->written == c->length) {
+2 -1
View File
@@ -14,7 +14,7 @@
#include "script.h" #include "script.h"
#include "http_parser.h" #include "http_parser.h"
#define VERSION "3.0.3" #define VERSION "3.1.0"
#define RECVBUF 8192 #define RECVBUF 8192
#define SAMPLES 100000000 #define SAMPLES 100000000
@@ -53,6 +53,7 @@ typedef struct connection {
char *request; char *request;
size_t length; size_t length;
size_t written; size_t written;
uint64_t pending;
buffer headers; buffer headers;
buffer body; buffer body;
char buf[RECVBUF]; char buf[RECVBUF];
View File