1
0
mirror of https://github.com/wg/wrk synced 2026-06-09 16:43:42 +08:00

4 Commits

3 changed files with 53 additions and 18 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ LIBS := -lpthread -lm
TARGET := $(shell uname -s | tr [A-Z] [a-z] 2>/dev/null || echo unknown) TARGET := $(shell uname -s | tr [A-Z] [a-z] 2>/dev/null || echo unknown)
ifeq ($(TARGET), sunos) ifeq ($(TARGET), sunos)
CFLAGS += -D_PTHREADS CFLAGS += -D_PTHREADS -D_POSIX_C_SOURCE=200112L
LIBS += -lsocket LIBS += -lsocket
endif endif
+51 -16
View File
@@ -33,6 +33,7 @@ static struct config {
uint64_t connections; uint64_t connections;
uint64_t requests; uint64_t requests;
uint64_t timeout; uint64_t timeout;
uint64_t errors;
} cfg; } cfg;
static struct { static struct {
@@ -50,6 +51,12 @@ static const struct http_parser_settings parser_settings = {
.on_message_complete = request_complete .on_message_complete = request_complete
}; };
static volatile sig_atomic_t stop = 0;
static void handler(int sig) {
stop = 1;
}
static void usage() { static void usage() {
printf("Usage: wrk <options> <url> \n" printf("Usage: wrk <options> <url> \n"
" Options: \n" " Options: \n"
@@ -59,6 +66,7 @@ static void usage() {
" \n" " \n"
" -H, --header <h> Add header to request \n" " -H, --header <h> Add header to request \n"
" -v, --version Print version details \n" " -v, --version Print version details \n"
" --errors <n> Abort after N errors \n"
" \n" " \n"
" Numeric arguments may include a SI unit (2k, 2M, 2G)\n"); " Numeric arguments may include a SI unit (2k, 2M, 2G)\n");
} }
@@ -104,14 +112,9 @@ int main(int argc, char **argv) {
for (addr = addrs; addr != NULL; addr = addr->ai_next) { for (addr = addrs; addr != NULL; addr = addr->ai_next) {
int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); int fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (fd == -1) continue; if (fd == -1) continue;
if (connect(fd, addr->ai_addr, addr->ai_addrlen) == -1) { rc = connect(fd, addr->ai_addr, addr->ai_addrlen);
if (errno == EHOSTUNREACH || errno == ECONNREFUSED) {
close(fd);
continue;
}
}
close(fd); close(fd);
break; if (rc == 0) break;
} }
if (addr == NULL) { if (addr == NULL) {
@@ -121,6 +124,7 @@ int main(int argc, char **argv) {
} }
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
signal(SIGINT, SIG_IGN);
cfg.addr = *addr; cfg.addr = *addr;
request.buf = format_request(host, port, path, headers); request.buf = format_request(host, port, path, headers);
request.size = strlen(request.buf); request.size = strlen(request.buf);
@@ -145,6 +149,13 @@ int main(int argc, char **argv) {
} }
} }
struct sigaction sa = {
.sa_handler = handler,
.sa_flags = 0,
};
sigfillset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
printf("Making %"PRIu64" requests to %s\n", cfg.requests, url); printf("Making %"PRIu64" requests to %s\n", cfg.requests, url);
printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections); printf(" %"PRIu64" threads and %"PRIu64" connections\n", cfg.threads, cfg.connections);
@@ -320,6 +331,16 @@ static int check_timeouts(aeEventLoop *loop, long long id, void *data) {
} }
} }
uint64_t errors = 0;
errors += thread->errors.connect;
errors += thread->errors.read;
errors += thread->errors.write;
errors += thread->errors.timeout;
if (stop || errors >= cfg.errors) {
aeStop(loop);
}
return TIMEOUT_INTERVAL_MS; return TIMEOUT_INTERVAL_MS;
} }
@@ -382,18 +403,24 @@ 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) { static char *format_request(char *host, char *port, char *path, char **headers) {
char *req = NULL; char *req = NULL;
char *head = NULL;
aprintf(&req, "GET %s HTTP/1.1\r\n", path);
aprintf(&req, "Host: %s", host);
if (port) aprintf(&req, ":%s", port);
aprintf(&req, "\r\n");
for (char **h = headers; *h != NULL; h++) { for (char **h = headers; *h != NULL; h++) {
aprintf(&req, "%s\r\n", *h); aprintf(&head, "%s\r\n", *h);
if (!strncasecmp(*h, "Host:", 5)) {
host = NULL;
port = NULL;
}
} }
aprintf(&req, "\r\n"); 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 : "");
free(head);
return req; return req;
} }
@@ -402,6 +429,7 @@ static struct option longopts[] = {
{ "requests", required_argument, NULL, 'r' }, { "requests", required_argument, NULL, 'r' },
{ "threads", required_argument, NULL, 't' }, { "threads", required_argument, NULL, 't' },
{ "header", required_argument, NULL, 'H' }, { "header", required_argument, NULL, 'H' },
{ "errors", required_argument, NULL, 'E' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 } { NULL, 0, NULL, 0 }
@@ -416,7 +444,7 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
cfg->requests = 100; cfg->requests = 100;
cfg->timeout = SOCKET_TIMEOUT_MS; cfg->timeout = SOCKET_TIMEOUT_MS;
while ((c = getopt_long(argc, argv, "t:c:r:H:v?", longopts, NULL)) != -1) { while ((c = getopt_long(argc, argv, "t:c:r:E:H:v?", longopts, NULL)) != -1) {
switch (c) { switch (c) {
case 't': case 't':
if (scan_metric(optarg, &cfg->threads)) return -1; if (scan_metric(optarg, &cfg->threads)) return -1;
@@ -427,6 +455,9 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
case 'r': case 'r':
if (scan_metric(optarg, &cfg->requests)) return -1; if (scan_metric(optarg, &cfg->requests)) return -1;
break; break;
case 'E':
if (scan_metric(optarg, &cfg->errors)) return -1;
break;
case 'H': case 'H':
*header++ = optarg; *header++ = optarg;
break; break;
@@ -449,6 +480,10 @@ static int parse_args(struct config *cfg, char **url, char **headers, int argc,
return -1; return -1;
} }
if (cfg->errors == 0) {
cfg->errors = cfg->requests / cfg->threads / 10;
}
*url = argv[optind]; *url = argv[optind];
*header = NULL; *header = NULL;
+1 -1
View File
@@ -11,7 +11,7 @@
#include "http_parser.h" #include "http_parser.h"
#include "tinymt64.h" #include "tinymt64.h"
#define VERSION "1.1.0" #define VERSION "1.2.0"
#define RECVBUF 8192 #define RECVBUF 8192
#define SAMPLES 100000 #define SAMPLES 100000