Add event_config_set_num_cpus_hint for tuning thread pools, etc.

This commit is contained in:
Christopher Davis 2010-08-28 04:07:48 -07:00
parent 499452f4c2
commit 2447fe8886
8 changed files with 39 additions and 13 deletions

View File

@ -285,6 +285,7 @@ struct event_config_entry {
struct event_config { struct event_config {
TAILQ_HEAD(event_configq, event_config_entry) entries; TAILQ_HEAD(event_configq, event_config_entry) entries;
int n_cpus_hint;
enum event_method_feature require_features; enum event_method_feature require_features;
enum event_base_config_flag flags; enum event_base_config_flag flags;
}; };

15
event.c
View File

@ -615,19 +615,19 @@ event_base_new_with_config(const struct event_config *cfg)
#ifdef WIN32 #ifdef WIN32
if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP)) if (cfg && (cfg->flags & EVENT_BASE_FLAG_STARTUP_IOCP))
event_base_start_iocp(base); event_base_start_iocp(base, cfg->n_cpus_hint);
#endif #endif
return (base); return (base);
} }
int int
event_base_start_iocp(struct event_base *base) event_base_start_iocp(struct event_base *base, int n_cpus)
{ {
#ifdef WIN32 #ifdef WIN32
if (base->iocp) if (base->iocp)
return 0; return 0;
base->iocp = event_iocp_port_launch(); base->iocp = event_iocp_port_launch(n_cpus);
if (!base->iocp) { if (!base->iocp) {
event_warnx("%s: Couldn't launch IOCP", __func__); event_warnx("%s: Couldn't launch IOCP", __func__);
return -1; return -1;
@ -918,6 +918,15 @@ event_config_require_features(struct event_config *cfg,
return (0); 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 int
event_priority_init(int npriorities) event_priority_init(int npriorities)
{ {

View File

@ -162,8 +162,10 @@ event_get_win32_extension_fns(void)
return &the_extension_fns; return &the_extension_fns;
} }
#define N_CPUS_DEFAULT 2
struct event_iocp_port * struct event_iocp_port *
event_iocp_port_launch(void) event_iocp_port_launch(int n_cpus)
{ {
struct event_iocp_port *port; struct event_iocp_port *port;
int i; int i;
@ -173,12 +175,16 @@ event_iocp_port_launch(void)
if (!(port = mm_calloc(1, sizeof(struct event_iocp_port)))) if (!(port = mm_calloc(1, sizeof(struct event_iocp_port))))
return NULL; 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)); port->threads = calloc(port->n_threads, sizeof(HANDLE));
if (!port->threads) if (!port->threads)
goto err; 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; port->ms = -1;
if (!port->port) if (!port->port)
goto err; goto err;

View File

@ -226,6 +226,16 @@ int event_config_require_features(struct event_config *cfg, int feature);
* will be initialized, and how they'll work. */ * will be initialized, and how they'll work. */
int event_config_set_flag(struct event_config *cfg, int flag); 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. Initialize the event API.

View File

@ -155,7 +155,7 @@ void evbuffer_commit_write(struct evbuffer *, ev_ssize_t);
This interface is unstable, and will change. 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 /** Associate a file descriptor with an iocp, such that overlapped IO on the
fd will happen on one of the iocp's worker threads. 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); struct event_iocp_port *event_base_get_iocp(struct event_base *base);
/* FIXME document. */ /* 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); void event_base_stop_iocp(struct event_base *base);
/* FIXME document. */ /* FIXME document. */

View File

@ -133,7 +133,7 @@ main(int argc, char **argv)
case 'i': case 'i':
use_iocp = 1; use_iocp = 1;
evthread_use_windows_threads(); evthread_use_windows_threads();
event_base_start_iocp(base); event_base_start_iocp(base, 0);
break; break;
#endif #endif
default: default:

View File

@ -170,7 +170,7 @@ test_iocp_port(void *ptr)
event_overlapped_init(&o1.eo, dummy_cb); event_overlapped_init(&o1.eo, dummy_cb);
event_overlapped_init(&o2.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(port);
tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 10, 100)); 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(rbuf, NULL);
evbuffer_enable_locking(wbuf, NULL); evbuffer_enable_locking(wbuf, NULL);
port = event_iocp_port_launch(); port = event_iocp_port_launch(0);
tt_assert(port); tt_assert(port);
tt_assert(rbuf); tt_assert(rbuf);
tt_assert(wbuf); tt_assert(wbuf);
@ -310,7 +310,7 @@ test_iocp_bufferevent_async(void *ptr)
char buf[128]; char buf[128];
size_t n; size_t n;
event_base_start_iocp(data->base); event_base_start_iocp(data->base, 0);
port = event_base_get_iocp(data->base); port = event_base_get_iocp(data->base);
tt_assert(port); tt_assert(port);

View File

@ -209,7 +209,7 @@ basic_test_setup(const struct testcase_t *testcase)
exit(1); exit(1);
} }
if (testcase->flags & TT_ENABLE_IOCP_FLAG) { 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); event_base_free(base);
return (void*)TT_SKIP; return (void*)TT_SKIP;
} }