diff options
author | Igor Sysoev <igor@sysoev.ru> | 2017-09-27 19:22:59 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2017-09-27 19:22:59 +0300 |
commit | bfa808d68997d74bfe0d54196bbbb649646787c1 (patch) | |
tree | 16751ca3da7dfd1c3c7830b3203fffdaea55b0cf /src | |
parent | 752038eea857988045ce72252e0d1c19509981b3 (diff) | |
download | unit-bfa808d68997d74bfe0d54196bbbb649646787c1.tar.gz unit-bfa808d68997d74bfe0d54196bbbb649646787c1.tar.bz2 |
Event engine memory cache for nxt_sockaddr_t.
Introducing event engine memory cache and using the cache for
nxt_sockaddr_t structures.
Diffstat (limited to '')
-rw-r--r-- | src/nxt_conn.h | 1 | ||||
-rw-r--r-- | src/nxt_conn_accept.c | 22 | ||||
-rw-r--r-- | src/nxt_controller.c | 10 | ||||
-rw-r--r-- | src/nxt_event_engine.c | 108 | ||||
-rw-r--r-- | src/nxt_event_engine.h | 6 | ||||
-rw-r--r-- | src/nxt_router.c | 13 | ||||
-rw-r--r-- | src/nxt_sockaddr.c | 41 | ||||
-rw-r--r-- | src/nxt_sockaddr.h | 4 |
8 files changed, 185 insertions, 20 deletions
diff --git a/src/nxt_conn.h b/src/nxt_conn.h index 32cad432..c4cabd05 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -103,6 +103,7 @@ typedef struct { uint32_t ready; uint32_t batch; + uint32_t mem_cache; /* 8 bits */ /* An accept() interface is cached to minimize memory accesses. */ nxt_work_handler_t accept; diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c index 660b41ff..38b36270 100644 --- a/src/nxt_conn_accept.c +++ b/src/nxt_conn_accept.c @@ -46,6 +46,8 @@ nxt_listen_event(nxt_task_t *task, nxt_listen_socket_t *ls) engine = task->thread->engine; lev->batch = engine->batch; + lev->mem_cache = (uint32_t) -1; + lev->socket.read_work_queue = &engine->accept_work_queue; lev->socket.read_handler = nxt_conn_listen_handler; lev->socket.error_handler = nxt_conn_listen_event_error; @@ -84,7 +86,6 @@ nxt_conn_accept_alloc(nxt_task_t *task, nxt_listen_event_t *lev) { nxt_mp_t *mp; nxt_conn_t *c; - nxt_sockaddr_t *sa, *remote; nxt_event_engine_t *engine; nxt_listen_socket_t *ls; @@ -107,23 +108,10 @@ nxt_conn_accept_alloc(nxt_task_t *task, nxt_listen_event_t *lev) ls = lev->listen; - remote = nxt_sockaddr_alloc(mp, ls->socklen, ls->address_length); - if (nxt_slow_path(remote == NULL)) { - goto fail; + c->remote = nxt_sockaddr_cache_alloc(engine, lev); + if (nxt_fast_path(c->remote != NULL)) { + return c; } - - c->remote = remote; - - sa = ls->sockaddr; - remote->type = sa->type; - /* - * Set address family for unspecified Unix domain socket, - * because these sockaddr's are not updated by old BSD systems, - * see comment in nxt_conn_io_accept(). - */ - remote->u.sockaddr.sa_family = sa->u.sockaddr.sa_family; - - return c; } fail: diff --git a/src/nxt_controller.c b/src/nxt_controller.c index c8bfbad6..d7a3d1a7 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -118,10 +118,18 @@ nxt_controller_start(nxt_task_t *task, void *data) nxt_str_t *json; nxt_runtime_t *rt; nxt_conf_value_t *conf; + nxt_event_engine_t *engine; nxt_http_fields_hash_t *hash; rt = task->thread->runtime; + engine = task->thread->engine; + + engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); + if (nxt_slow_path(engine->mem_pool == NULL)) { + return NXT_ERROR; + } + hash = nxt_http_fields_hash_create(nxt_controller_request_fields, rt->mem_pool); if (nxt_slow_path(hash == NULL)) { @@ -686,6 +694,8 @@ nxt_controller_conn_free(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "controller conn free"); + nxt_sockaddr_cache_free(task->thread->engine, c); + nxt_mp_destroy(c->mem_pool); //nxt_free(c); diff --git a/src/nxt_event_engine.c b/src/nxt_event_engine.c index 7f20c4c8..e275571c 100644 --- a/src/nxt_event_engine.c +++ b/src/nxt_event_engine.c @@ -7,6 +7,20 @@ #include <nxt_main.h> +typedef struct nxt_mem_cache_block_s nxt_mem_cache_block_t; + +struct nxt_mem_cache_block_s { + nxt_mem_cache_block_t *next; +}; + + +typedef struct { + nxt_mem_cache_block_t *free; + uint32_t size; + uint32_t count; +} nxt_mem_cache_t; + + static nxt_int_t nxt_event_engine_post_init(nxt_event_engine_t *engine); static nxt_int_t nxt_event_engine_signal_pipe_create( nxt_event_engine_t *engine); @@ -541,6 +555,100 @@ nxt_event_engine_start(nxt_event_engine_t *engine) } +void * +nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint32_t *slot, + size_t size) +{ + uint32_t n; + nxt_uint_t items; + nxt_array_t *mem_cache; + nxt_mem_cache_t *cache; + nxt_mem_cache_block_t *block; + + mem_cache = engine->mem_cache; + n = *slot; + + if (n == (uint32_t) -1) { + + if (mem_cache == NULL) { + /* IPv4 nxt_sockaddr_t and HTTP/1 and HTTP/2 buffers. */ + items = 3; +#if (NXT_INET6) + items++; +#endif +#if (NXT_HAVE_UNIX_DOMAIN) + items++; +#endif + + mem_cache = nxt_array_create(engine->mem_pool, items, + sizeof(nxt_mem_cache_t)); + if (nxt_slow_path(mem_cache == NULL)) { + return mem_cache; + } + + engine->mem_cache = mem_cache; + } + + cache = mem_cache->elts; + for (n = 0; n < mem_cache->nelts; n++) { + if (cache[n].size == size) { + goto found; + } + } + + cache = nxt_array_add(mem_cache); + if (nxt_slow_path(cache == NULL)) { + return cache; + } + + cache->free = NULL; + cache->size = size; + cache->count = 0; + + found: + + *slot = n; + } + + cache = mem_cache->elts; + cache = cache + n; + + block = cache->free; + + if (block != NULL) { + cache->free = block->next; + cache->count--; + + return block; + } + + return nxt_mp_alloc(engine->mem_pool, size); +} + + +void +nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint32_t *slot, void *p) +{ + nxt_mem_cache_t *cache; + nxt_mem_cache_block_t *block; + + block = p; + + cache = engine->mem_cache->elts; + cache = cache + *slot; + + if (cache->count < 16) { + cache->count++; + block->next = cache->free; + cache->free = block; + + return; + } + + nxt_mp_free(engine->mem_pool, p); +} + + #if (NXT_DEBUG) void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine) diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 57776a06..329a5a64 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -491,6 +491,7 @@ struct nxt_event_engine_s { nxt_queue_t joints; nxt_queue_t listen_connections; nxt_queue_t idle_connections; + nxt_array_t *mem_cache; nxt_queue_link_t link; // STUB: router link @@ -511,6 +512,11 @@ NXT_EXPORT void nxt_event_engine_post(nxt_event_engine_t *engine, NXT_EXPORT void nxt_event_engine_signal(nxt_event_engine_t *engine, nxt_uint_t signo); +void *nxt_event_engine_mem_alloc(nxt_event_engine_t *engine, uint32_t *slot, + size_t size); +void nxt_event_engine_mem_free(nxt_event_engine_t *engine, uint32_t *slot, + void *p); + nxt_inline nxt_event_engine_t * nxt_thread_event_engine(void) diff --git a/src/nxt_router.c b/src/nxt_router.c index d3c60a94..285c19b6 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -1819,6 +1819,9 @@ nxt_router_thread_start(void *data) #endif engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64); + if (nxt_slow_path(engine->mem_pool == NULL)) { + return; + } port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid, NXT_PROCESS_ROUTER); @@ -3433,6 +3436,7 @@ static void nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) { nxt_conn_t *c; + nxt_event_engine_t *engine; nxt_req_conn_link_t *rc; nxt_app_parse_ctx_t *ap; nxt_socket_conf_joint_t *joint; @@ -3466,11 +3470,14 @@ nxt_router_conn_free(nxt_task_t *task, void *obj, void *data) nxt_queue_remove(&c->link); - joint = c->listen->socket.data; + engine = task->thread->engine; - task = &task->thread->engine->task; + nxt_sockaddr_cache_free(engine, c); + + joint = c->listen->socket.data; - nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup, task, joint, NULL); + nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup, + &engine->task, joint, NULL); nxt_mp_release(c->mem_pool, c); } diff --git a/src/nxt_sockaddr.c b/src/nxt_sockaddr.c index 74de0984..38e2189e 100644 --- a/src/nxt_sockaddr.c +++ b/src/nxt_sockaddr.c @@ -21,6 +21,47 @@ static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs); nxt_sockaddr_t * +nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, nxt_listen_event_t *lev) +{ + size_t size; + nxt_sockaddr_t *sa; + nxt_listen_socket_t *ls; + + ls = lev->listen; + + size = offsetof(nxt_sockaddr_t, u) + ls->socklen + ls->address_length; + + sa = nxt_event_engine_mem_alloc(engine, &lev->mem_cache, size); + + if (nxt_fast_path(sa != NULL)) { + /* Zero only beginning of structure up to sockaddr_un.sun_path[1]. */ + nxt_memzero(sa, offsetof(nxt_sockaddr_t, u.sockaddr.sa_data[1])); + + sa->sockaddr_size = size; + sa->socklen = ls->socklen; + sa->length = ls->address_length; + + sa->type = ls->sockaddr->type; + /* + * Set address family for unspecified Unix domain socket, + * because these sockaddr's are not updated by old BSD systems, + * see comment in nxt_conn_io_accept(). + */ + sa->u.sockaddr.sa_family = ls->sockaddr->u.sockaddr.sa_family; + } + + return sa; +} + + +void +nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c) +{ + nxt_event_engine_mem_free(engine, &c->listen->mem_cache, c->remote); +} + + +nxt_sockaddr_t * nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length) { size_t size; diff --git a/src/nxt_sockaddr.h b/src/nxt_sockaddr.h index 1119ee2e..6f2c4a77 100644 --- a/src/nxt_sockaddr.h +++ b/src/nxt_sockaddr.h @@ -69,6 +69,10 @@ typedef struct { } nxt_job_sockaddr_parse_t; +nxt_sockaddr_t *nxt_sockaddr_cache_alloc(nxt_event_engine_t *engine, + nxt_listen_event_t *lev); +void nxt_sockaddr_cache_free(nxt_event_engine_t *engine, nxt_conn_t *c); + NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length) NXT_MALLOC_LIKE; |