summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2017-09-27 19:22:59 +0300
committerIgor Sysoev <igor@sysoev.ru>2017-09-27 19:22:59 +0300
commitbfa808d68997d74bfe0d54196bbbb649646787c1 (patch)
tree16751ca3da7dfd1c3c7830b3203fffdaea55b0cf
parent752038eea857988045ce72252e0d1c19509981b3 (diff)
downloadunit-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.
-rw-r--r--src/nxt_conn.h1
-rw-r--r--src/nxt_conn_accept.c22
-rw-r--r--src/nxt_controller.c10
-rw-r--r--src/nxt_event_engine.c108
-rw-r--r--src/nxt_event_engine.h6
-rw-r--r--src/nxt_router.c13
-rw-r--r--src/nxt_sockaddr.c41
-rw-r--r--src/nxt_sockaddr.h4
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;