mirror of
https://github.com/wg/wrk
synced 2025-02-09 11:32:52 +08:00
support setting request method & body
This commit is contained in:
parent
acb9a78925
commit
1b7161cf0e
18
README
18
README
@ -6,21 +6,21 @@ wrk - a HTTP benchmarking tool
|
||||
|
||||
Basic Usage
|
||||
|
||||
wrk -t8 -c400 -d30 http://localhost:8080/index.html
|
||||
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html
|
||||
|
||||
This runs a benchmark for 30 seconds, using 8 threads, and keeping
|
||||
This runs a benchmark for 30 seconds, using 12 threads, and keeping
|
||||
400 HTTP connections open.
|
||||
|
||||
Output:
|
||||
|
||||
Running 30s test @ http://localhost:8080/index.html
|
||||
8 threads and 400 connections
|
||||
Running 30s test @ http://127.0.0.1:8080/index.html
|
||||
12 threads and 400 connections
|
||||
Thread Stats Avg Stdev Max +/- Stdev
|
||||
Latency 439.75us 350.49us 7.60ms 92.88%
|
||||
Req/Sec 61.13k 8.26k 72.00k 87.54%
|
||||
10000088 requests in 19.87s, 3.42GB read
|
||||
Requests/sec: 503396.23
|
||||
Transfer/sec: 176.16MB
|
||||
Latency 635.91us 0.89ms 12.92ms 93.69%
|
||||
Req/Sec 56.20k 8.07k 62.00k 86.54%
|
||||
22464657 requests in 30.00s, 17.76GB read
|
||||
Requests/sec: 748868.53
|
||||
Transfer/sec: 606.33MB
|
||||
|
||||
Benchmarking Tips
|
||||
|
||||
|
46
src/wrk.c
46
src/wrk.c
@ -38,9 +38,11 @@ static struct config {
|
||||
} cfg;
|
||||
|
||||
static struct {
|
||||
char *method;
|
||||
char *body;
|
||||
size_t size;
|
||||
char *buf;
|
||||
} request;
|
||||
} req;
|
||||
|
||||
static struct {
|
||||
stats *latency;
|
||||
@ -66,6 +68,8 @@ static void usage() {
|
||||
" -t, --threads <N> Number of threads to use \n"
|
||||
" \n"
|
||||
" -H, --header <H> Add header to request \n"
|
||||
" -M, --method <M> HTTP method \n"
|
||||
" --body <B> Request body \n"
|
||||
" --latency Print latency statistics \n"
|
||||
" --timeout <T> Socket/request timeout \n"
|
||||
" -v, --version Print version details \n"
|
||||
@ -128,9 +132,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
cfg.addr = *addr;
|
||||
request.buf = format_request(host, port, path, headers);
|
||||
request.size = strlen(request.buf);
|
||||
cfg.addr = *addr;
|
||||
req.buf = format_request(host, port, path, headers);
|
||||
req.size = strlen(req.buf);
|
||||
|
||||
pthread_mutex_init(&statistics.mutex, NULL);
|
||||
statistics.latency = stats_alloc(SAMPLES);
|
||||
@ -351,7 +355,7 @@ static int check_timeouts(aeEventLoop *loop, long long id, void *data) {
|
||||
static void socket_writeable(aeEventLoop *loop, int fd, void *data, int mask) {
|
||||
connection *c = data;
|
||||
|
||||
if (write(fd, request.buf, request.size) < request.size) goto error;
|
||||
if (write(fd, req.buf, req.size) < req.size) goto error;
|
||||
c->start = time_us();
|
||||
aeDeleteFileEvent(loop, fd, AE_WRITABLE);
|
||||
|
||||
@ -406,7 +410,7 @@ static char *extract_url_part(char *url, struct http_parser_url *parser_url, enu
|
||||
}
|
||||
|
||||
static char *format_request(char *host, char *port, char *path, char **headers) {
|
||||
char *req = NULL;
|
||||
char *buf = NULL;
|
||||
char *head = NULL;
|
||||
|
||||
for (char **h = headers; *h != NULL; h++) {
|
||||
@ -417,14 +421,21 @@ static char *format_request(char *host, char *port, char *path, char **headers)
|
||||
}
|
||||
}
|
||||
|
||||
aprintf(&req, "GET %s HTTP/1.1\r\n", path);
|
||||
if (host) aprintf(&req, "Host: %s", host);
|
||||
if (port) aprintf(&req, ":%s", port);
|
||||
if (host) aprintf(&req, "\r\n");
|
||||
aprintf(&req, "%s\r\n", head ? head : "");
|
||||
if (req.body) {
|
||||
size_t len = strlen(req.body);
|
||||
aprintf(&head, "Content-Length: %zd\r\n", len);
|
||||
}
|
||||
|
||||
aprintf(&buf, "%s %s HTTP/1.1\r\n", req.method, path);
|
||||
if (host) aprintf(&buf, "Host: %s", host);
|
||||
if (port) aprintf(&buf, ":%s", port);
|
||||
if (host) aprintf(&buf, "\r\n");
|
||||
|
||||
aprintf(&buf, "%s\r\n", head ? head : "");
|
||||
aprintf(&buf, "%s", req.body ? req.body : "");
|
||||
|
||||
free(head);
|
||||
return req;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static struct option longopts[] = {
|
||||
@ -432,6 +443,8 @@ static struct option longopts[] = {
|
||||
{ "duration", required_argument, NULL, 'd' },
|
||||
{ "threads", required_argument, NULL, 't' },
|
||||
{ "header", required_argument, NULL, 'H' },
|
||||
{ "method", required_argument, NULL, 'M' },
|
||||
{ "body", required_argument, NULL, 'B' },
|
||||
{ "latency", no_argument, NULL, 'L' },
|
||||
{ "timeout", required_argument, NULL, 'T' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
@ -447,8 +460,9 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
|
||||
cfg->connections = 10;
|
||||
cfg->duration = 10;
|
||||
cfg->timeout = SOCKET_TIMEOUT_MS;
|
||||
req.method = "GET";
|
||||
|
||||
while ((c = getopt_long(argc, argv, "t:c:d:H:T:Lrv?", longopts, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "t:c:d:H:M:B:T:Lrv?", longopts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 't':
|
||||
if (scan_metric(optarg, &cfg->threads)) return -1;
|
||||
@ -462,6 +476,12 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
|
||||
case 'H':
|
||||
*header++ = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
req.method = optarg;
|
||||
break;
|
||||
case 'B':
|
||||
req.body = optarg;
|
||||
break;
|
||||
case 'L':
|
||||
cfg->latency = true;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user