Add event_config_set_num_cpus_hint for tuning thread pools, etc.
authorChristopher Davis <chrisd@torproject.org>
Sat, 28 Aug 2010 11:07:48 +0000 (04:07 -0700)
committerChristopher Davis <chrisd@torproject.org>
Wed, 8 Sep 2010 08:22:22 +0000 (01:22 -0700)
event-internal.h
event.c
event_iocp.c
include/event2/event.h
iocp-internal.h
test/bench_http.c
test/regress_iocp.c
test/regress_main.c

index 7d97d98e3f27bf56a9b8e321cba1b76cfb978a75..256f308642764e5881e454f4ed702808a8fbe2b0 100644 (file)
@@ -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 aaf8f28b03f95d7bfe0c485bdf7f442e3cb49fe8..8e8c324b02efd14e0813be8109265ebba8eb2d01 100644 (file)
--- 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)
 {
index 19c7bffc65edf7ea71285660ed86671d58d6b48a..254ed90dcfe4feadb954d889c659b17e9a9291ec 100644 (file)
@@ -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;
index e9d0048fbeff31b85225651de7f000418352bf3e..fa0f625d3e30e354786694cc9e9026d67ccdbf48 100644 (file)
@@ -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.
 
index 2b740bccefd03dd183f84d63108e1848afabc631..eb2eae49c20cf1e61f71554298d48f5ec99e9769 100644 (file)
@@ -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. */
index fdcf49dd60ded8dafa3ae863d042245152c0e826..4b2eb3cd3a79f23ff07ef18c3046ecbb41e5d9d8 100644 (file)
@@ -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:
index 96d8eb3edf58a733c33eefafff657deeb37d7776..920da2a71711a606510f6ba173178fa4b9c8a490 100644 (file)
@@ -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);
 
index 7d18938b0b2cb4604a2dcd4507b891d54c278cb4..3732f09898dad6cde50a7bd1ab1005757bbfb45f 100644 (file)
@@ -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;
                }