Event engine memory cache for nxt_sockaddr_t.
Introducing event engine memory cache and using the cache for nxt_sockaddr_t structures.
This commit is contained in:
@@ -103,6 +103,7 @@ typedef struct {
|
|||||||
|
|
||||||
uint32_t ready;
|
uint32_t ready;
|
||||||
uint32_t batch;
|
uint32_t batch;
|
||||||
|
uint32_t mem_cache; /* 8 bits */
|
||||||
|
|
||||||
/* An accept() interface is cached to minimize memory accesses. */
|
/* An accept() interface is cached to minimize memory accesses. */
|
||||||
nxt_work_handler_t accept;
|
nxt_work_handler_t accept;
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ nxt_listen_event(nxt_task_t *task, nxt_listen_socket_t *ls)
|
|||||||
engine = task->thread->engine;
|
engine = task->thread->engine;
|
||||||
lev->batch = engine->batch;
|
lev->batch = engine->batch;
|
||||||
|
|
||||||
|
lev->mem_cache = (uint32_t) -1;
|
||||||
|
|
||||||
lev->socket.read_work_queue = &engine->accept_work_queue;
|
lev->socket.read_work_queue = &engine->accept_work_queue;
|
||||||
lev->socket.read_handler = nxt_conn_listen_handler;
|
lev->socket.read_handler = nxt_conn_listen_handler;
|
||||||
lev->socket.error_handler = nxt_conn_listen_event_error;
|
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_mp_t *mp;
|
||||||
nxt_conn_t *c;
|
nxt_conn_t *c;
|
||||||
nxt_sockaddr_t *sa, *remote;
|
|
||||||
nxt_event_engine_t *engine;
|
nxt_event_engine_t *engine;
|
||||||
nxt_listen_socket_t *ls;
|
nxt_listen_socket_t *ls;
|
||||||
|
|
||||||
@@ -107,24 +108,11 @@ nxt_conn_accept_alloc(nxt_task_t *task, nxt_listen_event_t *lev)
|
|||||||
|
|
||||||
ls = lev->listen;
|
ls = lev->listen;
|
||||||
|
|
||||||
remote = nxt_sockaddr_alloc(mp, ls->socklen, ls->address_length);
|
c->remote = nxt_sockaddr_cache_alloc(engine, lev);
|
||||||
if (nxt_slow_path(remote == NULL)) {
|
if (nxt_fast_path(c->remote != NULL)) {
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return c;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
|
|||||||
@@ -118,10 +118,18 @@ nxt_controller_start(nxt_task_t *task, void *data)
|
|||||||
nxt_str_t *json;
|
nxt_str_t *json;
|
||||||
nxt_runtime_t *rt;
|
nxt_runtime_t *rt;
|
||||||
nxt_conf_value_t *conf;
|
nxt_conf_value_t *conf;
|
||||||
|
nxt_event_engine_t *engine;
|
||||||
nxt_http_fields_hash_t *hash;
|
nxt_http_fields_hash_t *hash;
|
||||||
|
|
||||||
rt = task->thread->runtime;
|
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,
|
hash = nxt_http_fields_hash_create(nxt_controller_request_fields,
|
||||||
rt->mem_pool);
|
rt->mem_pool);
|
||||||
if (nxt_slow_path(hash == NULL)) {
|
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_debug(task, "controller conn free");
|
||||||
|
|
||||||
|
nxt_sockaddr_cache_free(task->thread->engine, c);
|
||||||
|
|
||||||
nxt_mp_destroy(c->mem_pool);
|
nxt_mp_destroy(c->mem_pool);
|
||||||
|
|
||||||
//nxt_free(c);
|
//nxt_free(c);
|
||||||
|
|||||||
@@ -7,6 +7,20 @@
|
|||||||
#include <nxt_main.h>
|
#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_post_init(nxt_event_engine_t *engine);
|
||||||
static nxt_int_t nxt_event_engine_signal_pipe_create(
|
static nxt_int_t nxt_event_engine_signal_pipe_create(
|
||||||
nxt_event_engine_t *engine);
|
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)
|
#if (NXT_DEBUG)
|
||||||
|
|
||||||
void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine)
|
void nxt_event_engine_thread_adopt(nxt_event_engine_t *engine)
|
||||||
|
|||||||
@@ -491,6 +491,7 @@ struct nxt_event_engine_s {
|
|||||||
nxt_queue_t joints;
|
nxt_queue_t joints;
|
||||||
nxt_queue_t listen_connections;
|
nxt_queue_t listen_connections;
|
||||||
nxt_queue_t idle_connections;
|
nxt_queue_t idle_connections;
|
||||||
|
nxt_array_t *mem_cache;
|
||||||
|
|
||||||
nxt_queue_link_t link;
|
nxt_queue_link_t link;
|
||||||
// STUB: router 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_EXPORT void nxt_event_engine_signal(nxt_event_engine_t *engine,
|
||||||
nxt_uint_t signo);
|
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_inline nxt_event_engine_t *
|
||||||
nxt_thread_event_engine(void)
|
nxt_thread_event_engine(void)
|
||||||
|
|||||||
@@ -1819,6 +1819,9 @@ nxt_router_thread_start(void *data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
engine->mem_pool = nxt_mp_create(4096, 128, 1024, 64);
|
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,
|
port = nxt_port_new(task, nxt_port_get_next_id(), nxt_pid,
|
||||||
NXT_PROCESS_ROUTER);
|
NXT_PROCESS_ROUTER);
|
||||||
@@ -3433,6 +3436,7 @@ static void
|
|||||||
nxt_router_conn_free(nxt_task_t *task, void *obj, void *data)
|
nxt_router_conn_free(nxt_task_t *task, void *obj, void *data)
|
||||||
{
|
{
|
||||||
nxt_conn_t *c;
|
nxt_conn_t *c;
|
||||||
|
nxt_event_engine_t *engine;
|
||||||
nxt_req_conn_link_t *rc;
|
nxt_req_conn_link_t *rc;
|
||||||
nxt_app_parse_ctx_t *ap;
|
nxt_app_parse_ctx_t *ap;
|
||||||
nxt_socket_conf_joint_t *joint;
|
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);
|
nxt_queue_remove(&c->link);
|
||||||
|
|
||||||
|
engine = task->thread->engine;
|
||||||
|
|
||||||
|
nxt_sockaddr_cache_free(engine, c);
|
||||||
|
|
||||||
joint = c->listen->socket.data;
|
joint = c->listen->socket.data;
|
||||||
|
|
||||||
task = &task->thread->engine->task;
|
nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup,
|
||||||
|
&engine->task, joint, NULL);
|
||||||
nxt_mp_cleanup(c->mem_pool, nxt_router_conn_mp_cleanup, task, joint, NULL);
|
|
||||||
|
|
||||||
nxt_mp_release(c->mem_pool, c);
|
nxt_mp_release(c->mem_pool, c);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,47 @@ static nxt_int_t nxt_job_sockaddr_inet6_parse(nxt_job_sockaddr_parse_t *jbs);
|
|||||||
static nxt_int_t nxt_job_sockaddr_inet_parse(nxt_job_sockaddr_parse_t *jbs);
|
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_t *
|
||||||
nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length)
|
nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen, size_t address_length)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ typedef struct {
|
|||||||
} nxt_job_sockaddr_parse_t;
|
} 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,
|
NXT_EXPORT nxt_sockaddr_t *nxt_sockaddr_alloc(nxt_mp_t *mp, socklen_t socklen,
|
||||||
size_t address_length)
|
size_t address_length)
|
||||||
NXT_MALLOC_LIKE;
|
NXT_MALLOC_LIKE;
|
||||||
|
|||||||
Reference in New Issue
Block a user