1
0
mirror of https://github.com/wg/wrk synced 2025-01-08 23:32:54 +08:00

add optional delay() script function

This commit is contained in:
Will 2015-05-08 14:54:10 +09:00
parent a20969192f
commit 0f8016c907
7 changed files with 49 additions and 3 deletions

View File

@ -1,3 +1,5 @@
* delay() can return milliseconds to delay sending next request.
wrk 4.0.0 wrk 4.0.0
* The wrk global variable is the only global defined by default. * The wrk global variable is the only global defined by default.

View File

@ -38,6 +38,7 @@ Overview
global setup -- called during thread setup global setup -- called during thread setup
global init -- called when the thread is starting global init -- called when the thread is starting
global delay -- called to get the request delay
global request -- called to generate the HTTP request global request -- called to generate the HTTP request
global response -- called with HTTP response data global response -- called with HTTP response data
global done -- called with results of run global done -- called with results of run
@ -64,6 +65,7 @@ Setup
Running Running
function init(args) function init(args)
function delay()
function request() function request()
function response(status, headers, body) function response(status, headers, body)
@ -73,6 +75,9 @@ Running
The init() function receives any extra command line arguments for the The init() function receives any extra command line arguments for the
script which must be separated from wrk arguments with "--". script which must be separated from wrk arguments with "--".
delay() returns the number of milliseconds to delay sending the next
request.
request() returns a string containing the HTTP request. Building a new request() returns a string containing the HTTP request. Building a new
request each time is expensive, when testing a high performance server 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 one solution is to pre-generate all requests in init() and do a quick

6
scripts/delay.lua Normal file
View File

@ -0,0 +1,6 @@
-- example script that demonstrates adding a random
-- 10-50ms delay before each request
function delay()
return math.random(10, 50)
end

View File

@ -141,6 +141,14 @@ void script_init(lua_State *L, thread *t, int argc, char **argv) {
lua_pop(t->L, 1); lua_pop(t->L, 1);
} }
uint64_t script_delay(lua_State *L) {
lua_getglobal(L, "delay");
lua_call(L, 0, 1);
uint64_t delay = lua_tonumber(L, -1);
lua_pop(L, 1);
return delay;
}
void script_request(lua_State *L, char **buf, size_t *len) { void script_request(lua_State *L, char **buf, size_t *len) {
int pop = 1; int pop = 1;
lua_getglobal(L, "request"); lua_getglobal(L, "request");
@ -189,6 +197,10 @@ bool script_want_response(lua_State *L) {
return script_is_function(L, "response"); return script_is_function(L, "response");
} }
bool script_has_delay(lua_State *L) {
return script_is_function(L, "delay");
}
bool script_has_done(lua_State *L) { bool script_has_done(lua_State *L) {
return script_is_function(L, "done"); return script_is_function(L, "done");
} }

View File

@ -16,12 +16,14 @@ void script_setup(lua_State *, thread *);
void script_done(lua_State *, stats *, stats *); void script_done(lua_State *, stats *, stats *);
void script_init(lua_State *, thread *, int, char **); void script_init(lua_State *, thread *, int, char **);
uint64_t script_delay(lua_State *);
void script_request(lua_State *, char **, size_t *); void script_request(lua_State *, char **, size_t *);
void script_response(lua_State *, int, buffer *, buffer *); void script_response(lua_State *, int, buffer *, buffer *);
size_t script_verify_request(lua_State *L); size_t script_verify_request(lua_State *L);
bool script_is_static(lua_State *); bool script_is_static(lua_State *);
bool script_want_response(lua_State *L); bool script_want_response(lua_State *L);
bool script_has_delay(lua_State *L);
bool script_has_done(lua_State *L); bool script_has_done(lua_State *L);
void script_summary(lua_State *, uint64_t, uint64_t, uint64_t); void script_summary(lua_State *, uint64_t, uint64_t, uint64_t);
void script_errors(lua_State *, errors *); void script_errors(lua_State *, errors *);

View File

@ -5,13 +5,14 @@
#include "main.h" #include "main.h"
static struct config { static struct config {
uint64_t threads;
uint64_t connections; uint64_t connections;
uint64_t duration; uint64_t duration;
uint64_t threads;
uint64_t timeout; uint64_t timeout;
uint64_t pipeline; uint64_t pipeline;
bool latency; bool delay;
bool dynamic; bool dynamic;
bool latency;
char *script; char *script;
SSL_CTX *ctx; SSL_CTX *ctx;
} cfg; } cfg;
@ -108,6 +109,7 @@ int main(int argc, char **argv) {
if (i == 0) { if (i == 0) {
cfg.pipeline = 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);
cfg.delay = script_has_delay(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;
parser_settings.on_header_value = header_value; parser_settings.on_header_value = header_value;
@ -212,6 +214,7 @@ void *thread_main(void *arg) {
c->ssl = cfg.ctx ? SSL_new(cfg.ctx) : NULL; c->ssl = cfg.ctx ? SSL_new(cfg.ctx) : NULL;
c->request = request; c->request = request;
c->length = length; c->length = length;
c->delayed = cfg.delay;
connect_socket(thread, c); connect_socket(thread, c);
} }
@ -282,6 +285,13 @@ static int record_rate(aeEventLoop *loop, long long id, void *data) {
return RECORD_INTERVAL_MS; return RECORD_INTERVAL_MS;
} }
static int delay_request(aeEventLoop *loop, long long id, void *data) {
connection *c = data;
c->delayed = false;
aeCreateFileEvent(loop, c->fd, AE_WRITABLE, socket_writeable, c);
return AE_NOMORE;
}
static int header_field(http_parser *parser, const char *at, size_t len) { static int header_field(http_parser *parser, const char *at, size_t len) {
connection *c = parser->data; connection *c = parser->data;
if (c->state == VALUE) { if (c->state == VALUE) {
@ -331,6 +341,7 @@ static int response_complete(http_parser *parser) {
if (!stats_record(statistics.latency, now - c->start)) { if (!stats_record(statistics.latency, now - c->start)) {
thread->errors.timeout++; thread->errors.timeout++;
} }
c->delayed = cfg.delay;
aeCreateFileEvent(thread->loop, c->fd, AE_WRITABLE, socket_writeable, c); aeCreateFileEvent(thread->loop, c->fd, AE_WRITABLE, socket_writeable, c);
} }
@ -371,6 +382,13 @@ static void socket_writeable(aeEventLoop *loop, int fd, void *data, int mask) {
connection *c = data; connection *c = data;
thread *thread = c->thread; thread *thread = c->thread;
if (c->delayed) {
uint64_t delay = script_delay(thread->L);
aeDeleteFileEvent(loop, fd, AE_WRITABLE);
aeCreateTimeEvent(loop, delay, delay_request, c, NULL);
return;
}
if (!c->written) { if (!c->written) {
if (cfg.dynamic) { if (cfg.dynamic) {
script_request(thread->L, &c->request, &c->length); script_request(thread->L, &c->request, &c->length);

View File

@ -51,6 +51,7 @@ typedef struct connection {
} state; } state;
int fd; int fd;
SSL *ssl; SSL *ssl;
bool delayed;
uint64_t start; uint64_t start;
char *request; char *request;
size_t length; size_t length;