1
0
mirror of https://github.com/wg/wrk synced 2025-01-06 21: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
* 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 init -- called when the thread is starting
global delay -- called to get the request delay
global request -- called to generate the HTTP request
global response -- called with HTTP response data
global done -- called with results of run
@ -64,6 +65,7 @@ Setup
Running
function init(args)
function delay()
function request()
function response(status, headers, body)
@ -73,6 +75,9 @@ Running
The init() function receives any extra command line arguments for the
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 each time is expensive, when testing a high performance server
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);
}
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) {
int pop = 1;
lua_getglobal(L, "request");
@ -189,6 +197,10 @@ bool script_want_response(lua_State *L) {
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) {
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_init(lua_State *, thread *, int, char **);
uint64_t script_delay(lua_State *);
void script_request(lua_State *, char **, size_t *);
void script_response(lua_State *, int, buffer *, buffer *);
size_t script_verify_request(lua_State *L);
bool script_is_static(lua_State *);
bool script_want_response(lua_State *L);
bool script_has_delay(lua_State *L);
bool script_has_done(lua_State *L);
void script_summary(lua_State *, uint64_t, uint64_t, uint64_t);
void script_errors(lua_State *, errors *);

View File

@ -5,13 +5,14 @@
#include "main.h"
static struct config {
uint64_t threads;
uint64_t connections;
uint64_t duration;
uint64_t threads;
uint64_t timeout;
uint64_t pipeline;
bool latency;
bool delay;
bool dynamic;
bool latency;
char *script;
SSL_CTX *ctx;
} cfg;
@ -107,7 +108,8 @@ int main(int argc, char **argv) {
if (i == 0) {
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)) {
parser_settings.on_header_field = header_field;
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->request = request;
c->length = length;
c->delayed = cfg.delay;
connect_socket(thread, c);
}
@ -282,6 +285,13 @@ static int record_rate(aeEventLoop *loop, long long id, void *data) {
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) {
connection *c = parser->data;
if (c->state == VALUE) {
@ -331,6 +341,7 @@ static int response_complete(http_parser *parser) {
if (!stats_record(statistics.latency, now - c->start)) {
thread->errors.timeout++;
}
c->delayed = cfg.delay;
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;
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 (cfg.dynamic) {
script_request(thread->L, &c->request, &c->length);

View File

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