[spare-pipes] move variables / config knobs to core

This commit is contained in:
Kazuho Oku 2025-04-23 16:03:35 +09:00
parent b62082eedf
commit dd2ea453e4
5 changed files with 50 additions and 47 deletions

View File

@ -400,6 +400,10 @@ struct st_h2o_globalconf_t {
* SSL handshake timeout
*/
uint64_t handshake_timeout;
/**
* maximum number of pipes to retain for reuse
*/
size_t max_spare_pipes;
struct {
/**
@ -534,10 +538,6 @@ struct st_h2o_globalconf_t {
* maximum size to buffer for the response
*/
size_t max_buffer_size;
/**
* maximum number of pipes to retain for reuse
*/
size_t max_spare_pipes;
/**
* a boolean flag if set to true, instructs to use zero copy (i.e., splice to pipe then splice to socket) if possible
*/
@ -685,6 +685,13 @@ struct st_h2o_context_t {
* open file cache
*/
h2o_filecache_t *filecache;
/**
* the list of spare pipes currently retained for reuse
*/
struct {
int (*pipes)[2];
size_t count;
} spare_pipes;
/**
* context scope storage for general use
*/
@ -787,13 +794,6 @@ struct st_h2o_context_t {
* the default connection pool for proxy
*/
h2o_httpclient_connection_pool_t connpool;
/**
* the list of spare pipes currently retained for reuse
*/
struct {
int (*pipes)[2];
size_t count;
} spare_pipes;
} proxy;
struct {

View File

@ -413,6 +413,14 @@ static int on_config_handshake_timeout(h2o_configurator_command_t *cmd, h2o_conf
return config_timeout(cmd, node, &ctx->globalconf->handshake_timeout);
}
static int on_config_max_spare_pipes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
if (h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->max_spare_pipes) != 0)
return -1;
return 0;
}
static int on_config_http1_request_timeout(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
return config_timeout(cmd, node, &ctx->globalconf->http1.req_timeout);
@ -1042,6 +1050,12 @@ void h2o_configurator__init_core(h2o_globalconf_t *conf)
h2o_configurator_define_command(&c->super, "handshake-timeout",
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_handshake_timeout);
h2o_configurator_define_command(&c->super, "max-spare-pipes",
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_max_spare_pipes);
h2o_configurator_define_command(&c->super, "proxy.max-spare-pipes" /* for compatibility, retain old name as an alias */,
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_max_spare_pipes);
h2o_configurator_define_command(&c->super, "http1-request-timeout",
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_http1_request_timeout);

View File

@ -94,6 +94,18 @@ void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *co
h2o_multithread_register_receiver(ctx->queue, &ctx->receivers.hostinfo_getaddr, h2o_hostinfo_getaddr_receiver);
ctx->filecache = h2o_filecache_create(config->filecache.capacity);
ctx->spare_pipes.pipes = h2o_mem_alloc(sizeof(ctx->spare_pipes.pipes[0]) * config->max_spare_pipes);
#ifdef __linux__
/* pre-fill the pipe cache at context init */
for (i = 0; i < config->max_spare_pipes; ++i) {
if (pipe2(ctx->spare_pipes.pipes[i], O_NONBLOCK | O_CLOEXEC) != 0) {
char errbuf[256];
h2o_fatal("pipe2(2) failed:%s", h2o_strerror_r(errno, errbuf, sizeof(errbuf)));
}
ctx->spare_pipes.count++;
}
#endif
h2o_linklist_init_anchor(&ctx->_conns.active);
h2o_linklist_init_anchor(&ctx->_conns.idle);
h2o_linklist_init_anchor(&ctx->_conns.shutdown);
@ -109,20 +121,8 @@ void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *co
ctx->proxy.client_ctx.protocol_selector.ratio.http2 = ctx->globalconf->proxy.protocol_ratio.http2;
ctx->proxy.client_ctx.protocol_selector.ratio.http3 = ctx->globalconf->proxy.protocol_ratio.http3;
ctx->proxy.connpool.socketpool = &ctx->globalconf->proxy.global_socketpool;
ctx->proxy.spare_pipes.pipes = h2o_mem_alloc(sizeof(ctx->proxy.spare_pipes.pipes[0]) * config->proxy.max_spare_pipes);
h2o_linklist_init_anchor(&ctx->proxy.connpool.http2.conns);
#ifdef __linux__
/* pre-fill the pipe cache at context init */
for (i = 0; i < config->proxy.max_spare_pipes; ++i) {
if (pipe2(ctx->proxy.spare_pipes.pipes[i], O_NONBLOCK | O_CLOEXEC) != 0) {
char errbuf[256];
h2o_fatal("pipe2(2) failed:%s", h2o_strerror_r(errno, errbuf, sizeof(errbuf)));
}
ctx->proxy.spare_pipes.count++;
}
#endif
ctx->_module_configs = h2o_mem_alloc(sizeof(*ctx->_module_configs) * config->_num_config_slots);
memset(ctx->_module_configs, 0, sizeof(*ctx->_module_configs) * config->_num_config_slots);
@ -146,19 +146,12 @@ void h2o_context_init(h2o_context_t *ctx, h2o_loop_t *loop, h2o_globalconf_t *co
void h2o_context_dispose(h2o_context_t *ctx)
{
h2o_globalconf_t *config = ctx->globalconf;
size_t i, j;
for (size_t i = 0; i < ctx->proxy.spare_pipes.count; ++i) {
close(ctx->proxy.spare_pipes.pipes[i][0]);
close(ctx->proxy.spare_pipes.pipes[i][1]);
}
free(ctx->proxy.spare_pipes.pipes);
h2o_socketpool_unregister_loop(&ctx->globalconf->proxy.global_socketpool, ctx->loop);
for (i = 0; config->hosts[i] != NULL; ++i) {
for (size_t i = 0; config->hosts[i] != NULL; ++i) {
h2o_hostconf_t *hostconf = config->hosts[i];
for (j = 0; j != hostconf->paths.size; ++j) {
for (size_t j = 0; j != hostconf->paths.size; ++j) {
h2o_pathconf_t *pathconf = hostconf->paths.entries[j];
h2o_context_dispose_pathconf_context(ctx, pathconf);
}
@ -168,11 +161,17 @@ void h2o_context_dispose(h2o_context_t *ctx)
free(ctx->_module_configs);
/* what should we do here? assert(!h2o_linklist_is_empty(&ctx->http2._conns); */
for (size_t i = 0; i < ctx->spare_pipes.count; ++i) {
close(ctx->spare_pipes.pipes[i][0]);
close(ctx->spare_pipes.pipes[i][1]);
}
free(ctx->spare_pipes.pipes);
h2o_filecache_destroy(ctx->filecache);
ctx->filecache = NULL;
/* clear storage */
for (i = 0; i != ctx->storage.size; ++i) {
for (size_t i = 0; i != ctx->storage.size; ++i) {
h2o_context_storage_item_t *item = ctx->storage.entries + i;
if (item->dispose != NULL) {
item->dispose(item->data);

View File

@ -347,8 +347,8 @@ static void do_close(struct rp_generator_t *self)
h2o_timer_unlink(&self->send_headers_timeout);
if (self->pipe_reader.fds[0] != -1) {
h2o_context_t *ctx = self->src_req->conn->ctx;
if (ctx->proxy.spare_pipes.count < ctx->globalconf->proxy.max_spare_pipes && empty_pipe(self->pipe_reader.fds[0])) {
int *dst = ctx->proxy.spare_pipes.pipes[ctx->proxy.spare_pipes.count++];
if (ctx->spare_pipes.count < ctx->globalconf->max_spare_pipes && empty_pipe(self->pipe_reader.fds[0])) {
int *dst = ctx->spare_pipes.pipes[ctx->spare_pipes.count++];
dst[0] = self->pipe_reader.fds[0];
dst[1] = self->pipe_reader.fds[1];
} else {
@ -674,8 +674,8 @@ static h2o_httpclient_body_cb on_head(h2o_httpclient_t *client, const char *errs
/* switch to using pipe reader, if the opportunity is provided */
if (args->pipe_reader != NULL) {
#ifdef __linux__
if (req->conn->ctx->proxy.spare_pipes.count > 0) {
int *src = req->conn->ctx->proxy.spare_pipes.pipes[--req->conn->ctx->proxy.spare_pipes.count];
if (req->conn->ctx->spare_pipes.count > 0) {
int *src = req->conn->ctx->spare_pipes.pipes[--req->conn->ctx->spare_pipes.count];
self->pipe_reader.fds[0] = src[0];
self->pipe_reader.fds[1] = src[1];
} else {

View File

@ -523,14 +523,6 @@ static int on_config_emit_missing_date_header(h2o_configurator_command_t *cmd, h
return 0;
}
static int on_config_max_spare_pipes(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
if (h2o_configurator_scanf(cmd, node, "%zu", &ctx->globalconf->proxy.max_spare_pipes) != 0)
return -1;
return 0;
}
static int on_config_zerocopy(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node)
{
ssize_t ret = h2o_configurator_get_one_of(cmd, node, "OFF,ON,ALWAYS");
@ -805,8 +797,6 @@ void h2o_proxy_register_configurator(h2o_globalconf_t *conf)
on_config_emit_missing_date_header);
h2o_configurator_define_command(&c->super, "proxy.zerocopy", H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,
on_config_zerocopy);
h2o_configurator_define_command(&c->super, "proxy.max-spare-pipes",
H2O_CONFIGURATOR_FLAG_GLOBAL | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, on_config_max_spare_pipes);
h2o_configurator_define_headers_commands(conf, &c->super, "proxy.header", get_headers_commands);
h2o_configurator_define_command(&c->super, "proxy.max-buffer-size",
H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR,