From 11721fb29b88d633c7b26e62ceb17a68ff4a870d Mon Sep 17 00:00:00 2001 From: "Peter (Stig) Edwards" Date: Thu, 11 Jan 2024 13:52:18 +0000 Subject: [PATCH 1/2] Increase connection.wbuf size from 64k to 1m This is to support setting keys with value_size 1047552 (1023k) as done in conf/set_big_values. https://github.com/memcached/mc-crusher/issues/10 --- mc-crusher.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mc-crusher.c b/mc-crusher.c index b4a13d0..d6cdd43 100644 --- a/mc-crusher.c +++ b/mc-crusher.c @@ -53,6 +53,8 @@ #define SHARED_RBUF_SIZE 1024 * 64 #define SHARED_VALUE_SIZE 1024 * 1024 +// Big enough for conf/set_big_values and below valgrind max-stackframe +#define WBUF_SIZE 1024 * 1024 // avoiding some hacks for finding member size. #define SOCK_MAX 100 @@ -152,7 +154,7 @@ struct connection { int (*ascii_format)(struct connection *c); int (*bin_format)(struct connection *c); int (*bin_prep_cmd)(struct connection *c); - unsigned char wbuf[65536]; // putting this at the end to get more of the above into fewer cachelines. + unsigned char wbuf[WBUF_SIZE]; // putting this at the end to get more of the above into fewer cachelines. }; static void client_handler(const int fd, const short which, void *arg); @@ -915,6 +917,13 @@ static void parse_config_line(mc_thread *main_thread, char *line, bool use_sock) break; case VALUE_SIZE: template.value_size = atoi(value); + if(template.value_size > WBUF_SIZE){ + fprintf(stderr, "Error, value_size (%i) too large, WBUF_SIZE is %i\n", template.value_size, WBUF_SIZE); + exit(-1); + } + if( (template.value_size + 1024) > WBUF_SIZE){ // allow 1024 bytes for command, key and metadata + fprintf(stderr, "Warning, value_size (%i + 1024) may be too large, WBUF_SIZE is %i\n", template.value_size, WBUF_SIZE); + } break; case VALUE: strcpy(template.s->value, value); From 616d999e56d7b80b6e9c8dc88c3a1b1fc2a1febf Mon Sep 17 00:00:00 2001 From: "Peter (Stig) Edwards" Date: Fri, 12 Jan 2024 12:26:19 +0000 Subject: [PATCH 2/2] Support value_size > 64k connection.wbuf is changed from a static sized array on the stack to a pointer to a dynamically sized heap allocation. So that configs with many connections do not over allocate memory for wbuf, while also now supporting value_size > 64k --- mc-crusher.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/mc-crusher.c b/mc-crusher.c index d6cdd43..5214e6d 100644 --- a/mc-crusher.c +++ b/mc-crusher.c @@ -53,8 +53,7 @@ #define SHARED_RBUF_SIZE 1024 * 64 #define SHARED_VALUE_SIZE 1024 * 1024 -// Big enough for conf/set_big_values and below valgrind max-stackframe -#define WBUF_SIZE 1024 * 1024 +#define MIN_WBUF_SIZE 65536 // avoiding some hacks for finding member size. #define SOCK_MAX 100 @@ -154,7 +153,7 @@ struct connection { int (*ascii_format)(struct connection *c); int (*bin_format)(struct connection *c); int (*bin_prep_cmd)(struct connection *c); - unsigned char wbuf[WBUF_SIZE]; // putting this at the end to get more of the above into fewer cachelines. + unsigned char *wbuf; }; static void client_handler(const int fd, const short which, void *arg); @@ -546,7 +545,7 @@ static inline void run_write(struct connection *c) { } { // not using iovecs, save some libc/kernel looping. - c->wbuf_towrite = c->wbuf_pos - (unsigned char *)&c->wbuf; + c->wbuf_towrite = c->wbuf_pos - c->wbuf; c->wbuf_written = 0; //fprintf(stderr, "WBUF towrite: %d\n", c->wbuf_towrite); write_flat(c, c->next_state); @@ -917,13 +916,6 @@ static void parse_config_line(mc_thread *main_thread, char *line, bool use_sock) break; case VALUE_SIZE: template.value_size = atoi(value); - if(template.value_size > WBUF_SIZE){ - fprintf(stderr, "Error, value_size (%i) too large, WBUF_SIZE is %i\n", template.value_size, WBUF_SIZE); - exit(-1); - } - if( (template.value_size + 1024) > WBUF_SIZE){ // allow 1024 bytes for command, key and metadata - fprintf(stderr, "Warning, value_size (%i + 1024) may be too large, WBUF_SIZE is %i\n", template.value_size, WBUF_SIZE); - } break; case VALUE: strcpy(template.s->value, value); @@ -1049,6 +1041,13 @@ static void start_template(struct connection *template, int conns_tomake, bool u *template->cur_key = 0; *template->write_count = 0; + size_t wbuf_size = template->value_size + 1024; // space for op, key and metadata + if( wbuf_size < MIN_WBUF_SIZE ){ + wbuf_size = MIN_WBUF_SIZE; + } + template->wbuf = (unsigned char*)malloc(wbuf_size); + memset(template->wbuf, 0, wbuf_size); + int i, newsock; for (i = 0; i < conns_tomake; i++) { if (use_sock) {