Currently we are spending a lot of time in the new buffer manager code as well as allocating and freeing memory. Let's look into why these are called so much and figure out how we can reduce them. 6 out of the top 13
calls are malloc
related.
After
90,182,405 /build/buildd/glibc-2.21/malloc/malloc.c:_int_malloc [/lib/x86_64-linux-gnu/libc-2.21.so]
84,397,847 /build/buildd/glibc-2.21/malloc/malloc.c:_int_free [/lib/x86_64-linux-gnu/libc-2.21.so]
71,316,659 src/haywire/http_request_buffers.c:http_request_buffer_pin [/root/tmp18/haywire/build/hello_world]
63,189,481 src/haywire/http_parser.c:http_parser_execute [/root/tmp18/haywire/build/hello_world]
60,456,718 src/haywire/http_request_buffers.c:http_request_buffer_reassign_pin [/root/tmp18/haywire/build/hello_world]
47,094,829 src/haywire/http_request_buffers.c:http_request_buffer_locate [/root/tmp18/haywire/build/hello_world]
33,124,183 /build/buildd/glibc-2.21/malloc/malloc.c:malloc [/lib/x86_64-linux-gnu/libc-2.21.so]
30,457,235 /build/buildd/glibc-2.21/malloc/malloc.c:free [/lib/x86_64-linux-gnu/libc-2.21.so]
26,760,452 /build/buildd/glibc-2.21/malloc/malloc.c:calloc [/lib/x86_64-linux-gnu/libc-2.21.so]
15,346,372 src/haywire/http_request.c:set_header [/root/tmp18/haywire/build/hello_world]
13,911,569 /build/buildd/glibc-2.21/malloc/malloc.c:malloc_consolidate [/lib/x86_64-linux-gnu/libc-2.21.so]
12,304,079 /build/buildd/glibc-2.21/string/../sysdeps/x86_64/multiarch/memcpy-sse2-unaligned.S:__memcpy_sse2_unaligned [/lib/x86_64-linux-gnu/libc-2.21.so]
11,545,632 src/haywire/route_compare_method.c:hw_route_compare_method [/root/tmp18/haywire/build/hello_world]
A couple thoughts:
- Every request has a response struct. Could we combine mallocs for both into one malloc call? We do something similar here.
- Do we need to malloc requests and responses? Can we create a pool and reuse? Would this save CPU time? This struct for example.
Some code snippets of where instructions are going.
. void http_server_cleanup_write(char* response_string, hw_write_context* write_context, uv_write_t* write_req)
. {
215,136 free(response_string);
9,676,581 => /build/buildd/glibc-2.21/malloc/malloc.c:free (71712x)
215,136 free(write_context);
7,668,152 => /build/buildd/glibc-2.21/malloc/malloc.c:free (71712x)
215,136 free(write_req);
10,410,438 => /build/buildd/glibc-2.21/malloc/malloc.c:free (71712x)
. }
. int http_server_write_response_single(hw_write_context* write_context, hw_string* response)
358,560 {
71,712 http_connection* connection = write_context->connection;
.
215,136 if (connection->state == OPEN) {
286,848 uv_write_t *write_req = (uv_write_t *) malloc(sizeof(*write_req) + sizeof(uv_buf_t));
12,872,398 => /build/buildd/glibc-2.21/malloc/malloc.c:malloc (71712x)
71,712 uv_buf_t *resbuf = (uv_buf_t *) (write_req + 1);
.
143,424 resbuf->base = response->value;
143,424 resbuf->len = response->length;
.
71,712 write_req->data = write_context;
.
. uv_stream_t *stream = (uv_stream_t *) &write_context->connection->stream;
.
286,848 if (uv_is_writable(stream)) {
286,848 => /root/tmp18/haywire/lib/libuv/src/unix/stream.c:uv_is_writable (71712x)
. /* Ensuring that the the response can still be written. */
358,560 uv_write(write_req, stream, resbuf, 1, http_server_after_write);
19,563,750 => /root/tmp18/haywire/lib/libuv/src/unix/stream.c:uv_write (71712x)
. /* TODO: Use the return values from uv_write() */
. } else {
. /* The connection was closed, so we can write the response back, but we still need to free up things */
. http_server_cleanup_write(resbuf->base, write_context, write_req);
. }
. }
.
. return 0;
645,408 }
This malloc really hurts?
. hw_http_response hw_create_http_response(http_connection* connection)
143,424 {
215,136 http_response* response = malloc(sizeof(http_response));
27,539,899 => /build/buildd/glibc-2.21/malloc/malloc.c:malloc (71712x)
71,712 response->connection = connection;
143,424 response->request = connection->request;
143,424 response->http_major = 1;
143,424 response->http_minor = 1;
71,712 response->body.value = NULL;
71,712 response->body.length = 0;
71,712 response->number_of_headers = 0;
. return response;
143,424 }
. void hw_free_http_response(hw_http_response* response)
. {
. http_response* resp = (http_response*)response;
215,136 free(resp);
9,593,776 => /build/buildd/glibc-2.21/malloc/malloc.c:free (71712x)
. }
2 more painfull mallocs.
. hw_string* create_response_buffer(hw_http_response* response)
788,832 {
. http_response* resp = (http_response*)response;
286,848 hw_string* response_string = malloc(sizeof(hw_string));
7,956,650 => /build/buildd/glibc-2.21/malloc/malloc.c:malloc (71712x)
215,136 hw_string* cached_entry = get_cached_request(resp->status_code.value);
22,212,229 => /root/tmp18/haywire/src/haywire/http_response_cache.c:get_cached_request (71712x)
. hw_string content_length;
.
. int i = 0;
.
358,560 char length_header[] = "Content-Length: ";
. int line_sep_size = sizeof(CRLF);
.
. int header_buffer_incr = 512;
143,424 int body_size = resp->body.length;
. int header_size_remaining = header_buffer_incr;
215,136 int response_size = header_size_remaining + sizeof(length_header) + num_chars(resp->body.length) + 2 * line_sep_size + body_size + line_sep_si$
.
286,848 response_string->value = malloc(response_size);
16,125,993 => /build/buildd/glibc-2.21/malloc/malloc.c:malloc (71712x)
.
71,712 response_string->length = 0;
215,136 append_string(response_string, cached_entry);
3,513,888 => /root/tmp18/haywire/src/haywire/hw_string.c:append_string (71712x)
.
1,003,968 for (i=0; i< resp->number_of_headers; i++)
. {
1,434,240 http_header header = resp->headers[i];
.
. header_size_remaining -= header.name.length + 2 + header.value.length + line_sep_size;
286,848 if (header_size_remaining < 0) {
. header_size_remaining += header_buffer_incr * ((-header_size_remaining/header_buffer_incr) + 1);
. response_size += header_size_remaining;
. response_string->value = realloc(response_string->value, response_size);
. }
.
430,272 append_string(response_string, &header.name);
4,876,416 => /root/tmp18/haywire/src/haywire/hw_string.c:append_string (143424x)
430,272 APPENDSTRING(response_string, ": ");
573,696 append_string(response_string, &header.value);
4,876,416 => /root/tmp18/haywire/src/haywire/hw_string.c:append_string (143424x)
717,120 APPENDSTRING(response_string, CRLF);
. }
.
. /* Add the body */
143,424 APPENDSTRING(response_string, length_header);
.
358,560 string_from_int(&content_length, body_size, 10);
2,796,768 => /root/tmp18/haywire/src/haywire/hw_string.c:string_from_int (71712x)
.
143,424 if (body_size > 0) {
215,136 append_string(response_string, &content_length);
2,868,480 => /root/tmp18/haywire/src/haywire/hw_string.c:append_string (71712x)
. }
. else {
. hw_string zero_content;
. zero_content.value = "0";
. zero_content.length = 1;
. append_string(response_string, &zero_content);
. }
.
215,136 APPENDSTRING(response_string, CRLF CRLF);
.
. if (body_size > 0)
. {
215,136 append_string(response_string, &resp->body);
2,438,208 => /root/tmp18/haywire/src/haywire/hw_string.c:append_string (71712x)
. }
. return response_string;
860,544 }