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:
parent
a20969192f
commit
0f8016c907
2
CHANGES
2
CHANGES
@ -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.
|
||||
|
@ -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
6
scripts/delay.lua
Normal 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
|
12
src/script.c
12
src/script.c
@ -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");
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
24
src/wrk.c
24
src/wrk.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user