From 2447fe88860c40e968261ad8ea059166cb84a280 Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Sat, 28 Aug 2010 04:07:48 -0700 Subject: [PATCH] Add event_config_set_num_cpus_hint for tuning thread pools, etc. --- event-internal.h | 1 + event.c | 15 ++++++++++++--- event_iocp.c | 12 +++++++++--- include/event2/event.h | 10 ++++++++++ iocp-internal.h | 4 ++-- test/bench_http.c | 2 +- test/regress_iocp.c | 6 +++--- test/regress_main.c | 2 +- 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/event-internal.h b/event-internal.h index 7d97d98e..256f3086 100644 --- a/event-internal.h +++ b/event-internal.h @@ -285,6 +285,7 @@ struct event_config_entry { struct event_config { TAILQ_HEAD(event_configq, event_config_entry) entries; + int n_cpus_hint; enum event_method_feature require_features; enum event_base_config_flag flags; }; diff --git a/event.c b/event.c index aaf8f28b..8e8c324b 100644 --- a/event.c +++ b/event.c @@ -615,19 +615,19 @@ event_base_new_with_config(const struct event_config *cfg) #ifdef WIN32 if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP)) - event_base_start_iocp(base); + event_base_start_iocp(base, cfg->n_cpus_hint); #endif return (base); } int -event_base_start_iocp(struct event_base *base) +event_base_start_iocp(struct event_base *base, int n_cpus) { #ifdef WIN32 if (base->iocp) return 0; - base->iocp = event_iocp_port_launch(); + base->iocp = event_iocp_port_launch(n_cpus); if (!base->iocp) { event_warnx("%s: Couldn't launch IOCP", __func__); return -1; @@ -918,6 +918,15 @@ event_config_require_features(struct event_config *cfg, return (0); } +int +event_config_set_num_cpus_hint(struct event_config *cfg, int cpus) +{ + if (!cfg) + return (-1); + cfg->n_cpus_hint = cpus; + return (0); +} + int event_priority_init(int npriorities) { diff --git a/event_iocp.c b/event_iocp.c index 19c7bffc..254ed90d 100644 --- a/event_iocp.c +++ b/event_iocp.c @@ -162,8 +162,10 @@ event_get_win32_extension_fns(void) return &the_extension_fns; } +#define N_CPUS_DEFAULT 2 + struct event_iocp_port * -event_iocp_port_launch(void) +event_iocp_port_launch(int n_cpus) { struct event_iocp_port *port; int i; @@ -173,12 +175,16 @@ event_iocp_port_launch(void) if (!(port = mm_calloc(1, sizeof(struct event_iocp_port)))) return NULL; - port->n_threads = 2; + + if (n_cpus <= 0) + n_cpus = N_CPUS_DEFAULT; + port->n_threads = n_cpus * 2; port->threads = calloc(port->n_threads, sizeof(HANDLE)); if (!port->threads) goto err; - port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, port->n_threads); + port->port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, + n_cpus); port->ms = -1; if (!port->port) goto err; diff --git a/include/event2/event.h b/include/event2/event.h index e9d0048f..fa0f625d 100644 --- a/include/event2/event.h +++ b/include/event2/event.h @@ -226,6 +226,16 @@ int event_config_require_features(struct event_config *cfg, int feature); * will be initialized, and how they'll work. */ int event_config_set_flag(struct event_config *cfg, int flag); +/** + * Records a hint for the number of CPUs in the system. This is used for + * tuning thread pools, etc, for optimal performance. + * + * @param cfg the event configuration object + * @param cpus the number of cpus + * @return 0 on success, -1 on failure. + */ +int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus); + /** Initialize the event API. diff --git a/iocp-internal.h b/iocp-internal.h index 2b740bcc..eb2eae49 100644 --- a/iocp-internal.h +++ b/iocp-internal.h @@ -155,7 +155,7 @@ void evbuffer_commit_write(struct evbuffer *, ev_ssize_t); This interface is unstable, and will change. */ -struct event_iocp_port *event_iocp_port_launch(void); +struct event_iocp_port *event_iocp_port_launch(int n_cpus); /** Associate a file descriptor with an iocp, such that overlapped IO on the fd will happen on one of the iocp's worker threads. @@ -181,7 +181,7 @@ struct event_base; struct event_iocp_port *event_base_get_iocp(struct event_base *base); /* FIXME document. */ -int event_base_start_iocp(struct event_base *base); +int event_base_start_iocp(struct event_base *base, int n_cpus); void event_base_stop_iocp(struct event_base *base); /* FIXME document. */ diff --git a/test/bench_http.c b/test/bench_http.c index fdcf49dd..4b2eb3cd 100644 --- a/test/bench_http.c +++ b/test/bench_http.c @@ -133,7 +133,7 @@ main(int argc, char **argv) case 'i': use_iocp = 1; evthread_use_windows_threads(); - event_base_start_iocp(base); + event_base_start_iocp(base, 0); break; #endif default: diff --git a/test/regress_iocp.c b/test/regress_iocp.c index 96d8eb3e..920da2a7 100644 --- a/test/regress_iocp.c +++ b/test/regress_iocp.c @@ -170,7 +170,7 @@ test_iocp_port(void *ptr) event_overlapped_init(&o1.eo, dummy_cb); event_overlapped_init(&o2.eo, dummy_cb); - port = event_iocp_port_launch(); + port = event_iocp_port_launch(0); tt_assert(port); tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 10, 100)); @@ -255,7 +255,7 @@ test_iocp_evbuffer(void *ptr) evbuffer_enable_locking(rbuf, NULL); evbuffer_enable_locking(wbuf, NULL); - port = event_iocp_port_launch(); + port = event_iocp_port_launch(0); tt_assert(port); tt_assert(rbuf); tt_assert(wbuf); @@ -310,7 +310,7 @@ test_iocp_bufferevent_async(void *ptr) char buf[128]; size_t n; - event_base_start_iocp(data->base); + event_base_start_iocp(data->base, 0); port = event_base_get_iocp(data->base); tt_assert(port); diff --git a/test/regress_main.c b/test/regress_main.c index 7d18938b..3732f098 100644 --- a/test/regress_main.c +++ b/test/regress_main.c @@ -209,7 +209,7 @@ basic_test_setup(const struct testcase_t *testcase) exit(1); } if (testcase->flags & TT_ENABLE_IOCP_FLAG) { - if (event_base_start_iocp(base)<0) { + if (event_base_start_iocp(base, 0)<0) { event_base_free(base); return (void*)TT_SKIP; } -- 2.40.0