From 411b9dd3263b8b4e042bfdee1d8637577beccd89 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 25 Mar 2017 21:23:31 +0100 Subject: [PATCH] replaced most occurrences of list_foreach with a traditional for loop due to performance reasons --- include/villas/list.h | 5 ++-- lib/apis/nodes.c | 4 ++- lib/kernel/if.c | 8 ++++-- lib/kernel/vfio.c | 13 +++++++-- lib/list.c | 16 +++++++---- lib/nodes/ngsi.c | 10 +++++-- lib/nodes/socket.c | 18 +++++++++--- lib/nodes/websocket.c | 21 ++++++++++---- lib/path.c | 66 ++++++++++++++++++++++++++++--------------- lib/plugin.c | 12 +++++--- lib/super_node.c | 37 +++++++++++++++--------- src/node.c | 11 ++++++-- tests/unit/list.c | 15 ++++++---- 13 files changed, 162 insertions(+), 74 deletions(-) diff --git a/include/villas/list.h b/include/villas/list.h index 07fd58e9f..00ff9ee15 100644 --- a/include/villas/list.h +++ b/include/villas/list.h @@ -30,12 +30,11 @@ } #define list_length(list) ((list)->length) -#define list_at(list, index) ((list)->length > index ? (list)->array[index] : NULL) +#define list_at_safe(list, index) ((list)->length > index ? (list)->array[index] : NULL) +#define list_at(list, index) ((list)->array[index]) #define list_first(list) list_at(list, 0) #define list_last(list) list_at(list, (list)->length-1) -#define list_foreach(ptr, list) for (int _i = 0, _p; _p = 1, _i < (list)->length; _i++) \ - for (ptr = (list)->array[_i]; _p--; ) /** Callback to destroy list elements. * diff --git a/lib/apis/nodes.c b/lib/apis/nodes.c index 6567c8b10..2487f8435 100644 --- a/lib/apis/nodes.c +++ b/lib/apis/nodes.c @@ -19,7 +19,9 @@ static int api_nodes(struct api_ressource *r, json_t *args, json_t **resp, struc { json_t *json_nodes = json_array(); - list_foreach(struct node *n, &s->api->super_node->nodes) { + for (size_t i = 0; i < list_length(&s->api->super_node->nodes); i++) { + struct node *n = list_at(&s->api->super_node->nodes, i); + json_t *json_node = json_pack("{ s: s, s: i, s: i, s: i, s: i }", "name", node_name_short(n), "state", n->state, diff --git a/lib/kernel/if.c b/lib/kernel/if.c index 765bf22aa..785596739 100644 --- a/lib/kernel/if.c +++ b/lib/kernel/if.c @@ -59,7 +59,9 @@ int if_start(struct interface *i, int affinity) /* Assign fwmark's to socket nodes which have netem options */ int ret, mark = 0; - list_foreach(struct socket *s, &i->sockets) { + for (size_t j = 0; j < list_length(&i->sockets); j++) { + struct socket *s = list_at(&i->sockets, j); + if (s->tc_qdisc) s->mark = 1 + mark++; } @@ -82,7 +84,9 @@ int if_start(struct interface *i, int affinity) error("Failed to setup priority queuing discipline: %s", nl_geterror(ret)); /* Create netem qdisks and appropriate filter per netem node */ - list_foreach(struct socket *s, &i->sockets) { + for (size_t j = 0; j < list_length(&i->sockets); j++) { + struct socket *s = list_at(&i->sockets, j); + if (s->tc_qdisc) { ret = tc_mark(i, &s->tc_classifier, TC_HANDLE(1, s->mark), s->mark); if (ret) diff --git a/lib/kernel/vfio.c b/lib/kernel/vfio.c index b6751f4cf..4d7e99d3f 100644 --- a/lib/kernel/vfio.c +++ b/lib/kernel/vfio.c @@ -247,7 +247,9 @@ int vfio_dev_attach(struct vfio_dev *d, struct vfio_container *c, const char *na struct vfio_group *g = NULL; /* Check if group already exists */ - list_foreach(struct vfio_group *h, &c->groups) { + for (size_t i = 0; i < list_length(&c->groups); i++) { + struct vfio_group *h = list_at(&c->groups, i); + if (h->index == index) g = h; } @@ -497,13 +499,18 @@ void vfio_dump(struct vfio_container *v) info("VFIO Version: %u", v->version); info("VFIO Extensions: %#x", v->extensions); - list_foreach(struct vfio_group *g, &v->groups) { + for (size_t i = 0; i < list_length(&v->groups); i++) { + struct vfio_group *g = list_at(&v->groups, i); + info("VFIO Group %u, viable=%u, container=%d", g->index, (g->status.flags & VFIO_GROUP_FLAGS_VIABLE) > 0, (g->status.flags & VFIO_GROUP_FLAGS_CONTAINER_SET) > 0 ); - list_foreach(struct vfio_dev *d, &g->devices) { INDENT + + for (size_t i = 0; i < list_length(&g->devices); i++) { INDENT + struct vfio_device *d = list_at(&g->devices, i); + info("Device %s: regions=%u, irqs=%u, flags=%#x", d->name, d->info.num_regions, d->info.num_irqs, diff --git a/lib/list.c b/lib/list.c index 0a95ed9bf..2dfd2b416 100644 --- a/lib/list.c +++ b/lib/list.c @@ -40,6 +40,7 @@ void list_init(struct list *l) l->length = 0; l->capacity = 0; l->array = NULL; + l->state = STATE_INITIALIZED; } @@ -49,7 +50,9 @@ int list_destroy(struct list *l, dtor_cb_t destructor, bool release) assert(l->state != STATE_DESTROYED); - list_foreach(void *p, l) { + for (size_t i = 0; i < list_length(l); i++) { + void *p = list_at(l, i); + if (destructor) destructor(p); if (release) @@ -97,7 +100,7 @@ void list_remove(struct list *l, void *p) assert(l->state == STATE_INITIALIZED); - for (int i = 0; i < l->length; i++) { + for (size_t i = 0; i < list_length(l); i++) { if (l->array[i] == p) removed++; else @@ -127,7 +130,9 @@ int list_count(struct list *l, cmp_cb_t cmp, void *ctx) assert(l->state == STATE_INITIALIZED); - list_foreach(void *e, l) { + for (size_t i = 0; i < list_length(l); i++) { + void *e = list_at(l, i); + if (cmp(e, ctx) == 0) c++; } @@ -145,8 +150,9 @@ void * list_search(struct list *l, cmp_cb_t cmp, void *ctx) assert(l->state == STATE_INITIALIZED); - list_foreach(e, l) { - if (!cmp(e, ctx)) + for (size_t i = 0; i < list_length(l); i++) { + e = list_at(l, i); + if (cmp(e, ctx) == 0) goto out; } diff --git a/lib/nodes/ngsi.c b/lib/nodes/ngsi.c index 2f89aa87e..9fb660c30 100644 --- a/lib/nodes/ngsi.c +++ b/lib/nodes/ngsi.c @@ -56,7 +56,10 @@ static json_t* ngsi_build_entity(struct ngsi *i, struct sample *smps[], unsigned if (flags & NGSI_ENTITY_ATTRIBUTES) { json_t *attributes = json_array(); - list_foreach(struct ngsi_attribute *map, &i->mapping) { + + for (size_t j = 0; j < list_length(&i->mapping); j++) { + struct ngsi_attribute *map = list_at(&i->mapping, j); + json_t *attribute = json_pack("{ s: s, s: s }", "name", map->name, "type", map->type @@ -77,7 +80,10 @@ static json_t* ngsi_build_entity(struct ngsi *i, struct sample *smps[], unsigned if (flags & NGSI_ENTITY_METADATA) { /* Create Metadata for attribute */ json_t *metadatas = json_array(); - list_foreach(struct ngsi_metadata *meta, &map->metadata) { + + for (size_t i = 0; i < list_length(&map->metadata); i++) { + struct ngsi_metadata *meta = list_at(&map->metadata, i); + json_array_append_new(metadatas, json_pack("{ s: s, s: s, s: s }", "name", meta->name, "type", meta->type, diff --git a/lib/nodes/socket.c b/lib/nodes/socket.c index 1b0bcbd4a..87e7464db 100644 --- a/lib/nodes/socket.c +++ b/lib/nodes/socket.c @@ -45,7 +45,8 @@ int socket_init(int argc, char *argv[], config_setting_t *cfg) list_init(&interfaces); /* Gather list of used network interfaces */ - list_foreach(struct node *n, &p.node.instances) { + for (size_t i = 0; i < list_length(&p.node.instances); i++) { + struct node *n = list_at(&p.node.instances, i); struct socket *s = n->_vd; struct rtnl_link *link; @@ -58,7 +59,10 @@ int socket_init(int argc, char *argv[], config_setting_t *cfg) /* Search of existing interface with correct ifindex */ struct interface *i; - list_foreach(i, &interfaces) { + + for (size_t k = 0; k < list_length(&interfaces); k++) { + i = list_at(&interfaces, k); + if (rtnl_link_get_ifindex(i->nl_link) == rtnl_link_get_ifindex(link)) goto found; } @@ -79,16 +83,22 @@ found: list_push(&i->sockets, s); if (!config_setting_lookup_int(cfg, "affinity", &affinity)) affinity = -1; - list_foreach(struct interface *i, &interfaces) + for (size_t j = 0; list_length(&interfaces); j++) { + struct interface *i = list_at(&interfaces, j); + if_start(i, affinity); + } return 0; } int socket_deinit() { - list_foreach(struct interface *i, &interfaces) + for (size_t j = 0; list_length(&interfaces); j++) { + struct interface *i = list_at(&interfaces, j); + if_stop(i); + } list_destroy(&interfaces, (dtor_cb_t) if_destroy, false); diff --git a/lib/nodes/websocket.c b/lib/nodes/websocket.c index ffdd96c9f..daa242ec4 100644 --- a/lib/nodes/websocket.c +++ b/lib/nodes/websocket.c @@ -288,7 +288,9 @@ int websocket_stop(struct node *n) { struct websocket *w = n->_vd; - list_foreach(struct websocket_connection *c, &w->connections) { + for (size_t i = 0; i < list_length(&w->connections); i++) { + struct websocket_connection *c = list_at(&w->connections, i); + c->state = WEBSOCKET_SHUTDOWN; lws_callback_on_writable(c->wsi); } @@ -340,11 +342,18 @@ int websocket_write(struct node *n, struct sample *smps[], unsigned cnt) { struct websocket *w = n->_vd; - list_foreach(struct websocket_connection *c, &w->connections) - websocket_connection_write(c, smps, cnt); - list_foreach(struct websocket_connection *c, &connections) + for (size_t i = 0; i < list_length(&w->connections); i++) { + struct websocket_connection *c = list_at(&w->connections, i); + websocket_connection_write(c, smps, cnt); + } + + for (size_t i = 0; i < list_length(&connections); i++) { + struct websocket_connection *c = list_at(&connections, i); + + websocket_connection_write(c, smps, cnt); + } return cnt; } @@ -399,7 +408,9 @@ char * websocket_print(struct node *n) buf = strcatf(&buf, "dests="); - list_foreach(struct lws_client_connect_info *in, &w->destinations) { + for (size_t i = 0; i < list_length(&w->destinations); i++) { + struct lws_client_connect_info *in = list_at(&w->destinations, i); + buf = strcatf(&buf, "%s://%s:%d/%s", in->ssl_connection ? "https" : "http", in->address, diff --git a/lib/path.c b/lib/path.c index 48cadb1ce..0a5408d0d 100644 --- a/lib/path.c +++ b/lib/path.c @@ -57,7 +57,9 @@ static void path_read(struct path *p) stats_update(p->stats->delta, STATS_SKIPPED, recv - enqueue); } - list_foreach(struct path_destination *pd, &p->destinations) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + enqueued = queue_push_many(&pd->queue, (void **) smps, enqueue); if (enqueue != enqueued) warn("Queue overrun for path %s", path_name(p)); @@ -71,7 +73,9 @@ static void path_read(struct path *p) static void path_write(struct path *p) { - list_foreach(struct path_destination *pd, &p->destinations) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + int cnt = pd->node->vectorize; int sent; int tosend; @@ -217,14 +221,13 @@ int path_parse(struct path *p, config_setting_t *cfg, struct list *nodes) p->source->node = source; p->source->samplelen = samplelen; - list_foreach(struct node *n, &destinations) { - if (n->_vt->write == NULL) - cerror(cfg_out, "Output node '%s' is not supported as a destination.", node_name(n)); - - struct path_destination pd; - - pd.node = n; - pd.queuelen = queuelen; + for (size_t i = 0; i < list_length(&destinations); i++) { + struct node *n = list_at(&destinations, i); + + struct path_destination pd = { + .node = n, + .queuelen = p->queuelen + }; list_push(&p->destinations, memdup(&pd, sizeof(pd))); } @@ -238,7 +241,9 @@ int path_check(struct path *p) { assert(p->state != STATE_DESTROYED); - list_foreach(struct node *n, &p->destinations) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct node *n = list_at(&p->destinations, i); + if (!n->_vt->write) error("Destiation node '%s' is not supported as a sink for path '%s'", node_name(n), path_name(p)); } @@ -256,7 +261,9 @@ int path_init2(struct path *p) assert(p->state == STATE_CHECKED); /* Add internal hooks if they are not already in the list*/ - list_foreach(struct plugin *q, &plugins) { + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *q = list_at(&plugins, i); + if (q->type == PLUGIN_TYPE_HOOK) { struct hook h; struct hook_type *vt = &q->hook; @@ -273,7 +280,9 @@ int path_init2(struct path *p) list_sort(&p->hooks, hook_cmp_priority); /* Initialize destinations */ - list_foreach(struct path_destination *pd, &p->destinations) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + ret = queue_init(&pd->queue, pd->queuelen, &memtype_hugepage); if (ret) error("Failed to initialize queue for path"); @@ -298,8 +307,9 @@ int path_start(struct path *p) info("Starting path: %s (#hooks=%zu)", path_name(p), list_length(&p->hooks)); - list_foreach(struct hook *h, &p->hooks) { - ret = hook_run(h, HOOK_PATH_START, &(struct hook_info) { .path = p }); + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); + if (ret) return ret; } @@ -324,8 +334,10 @@ int path_stop(struct path *p) pthread_cancel(p->tid); pthread_join(p->tid, NULL); - list_foreach(struct hook *h, &p->hooks) { - ret = hook_run(h, HOOK_PATH_STOP, &(struct hook_info) { .path = p }); + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); + + ret = hook_run(h, HOOK_STOP, NULL, 0); if (ret) return ret; } @@ -366,8 +378,11 @@ const char * path_name(struct path *p) else { strcatf(&p->_name, "%s " MAG("=>") " [", node_name_short(p->source->node)); - list_foreach(struct path_destination *pd, &p->destinations) + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + strcatf(&p->_name, " %s", node_name_short(pd->node)); + } strcatf(&p->_name, " ]"); } @@ -377,7 +392,9 @@ const char * path_name(struct path *p) } int path_uses_node(struct path *p, struct node *n) { - list_foreach(struct path_destination *pd, &p->destinations) { + for (size_t i = 0; i < list_length(&p->destinations); i++) { + struct path_destination *pd = list_at(&p->destinations, i); + if (pd->node == n) return 0; } @@ -412,10 +429,11 @@ int path_reverse(struct path *p, struct path *r) r->source = ps; - list_foreach(struct hook *h, &p->hooks) { + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); struct hook hc; - ret = hook_init(&hc, h->_vt, p->super_node); + ret = hook_init(&hc, h->_vt, p); if (ret) return ret; @@ -434,12 +452,14 @@ int path_run_hooks(struct path *p, int when, struct sample *smps[], size_t cnt) .count = cnt }; - list_foreach(struct hook *h, &p->hooks) { - ret = hook_run(h, when, &i); if (ret) break; if (i.count == 0) + for (size_t i = 0; i < list_length(&p->hooks); i++) { + struct hook *h = list_at(&p->hooks, i); + + ret = hook_run(h, when, smps, &cnt); break; } diff --git a/lib/plugin.c b/lib/plugin.c index e0b462ba8..4aab33115 100644 --- a/lib/plugin.c +++ b/lib/plugin.c @@ -69,9 +69,11 @@ int plugin_destroy(struct plugin *p) struct plugin * plugin_lookup(enum plugin_type type, const char *name) { - list_foreach(struct plugin *l, &plugins) { - if (l->type == type && strcmp(l->name, name) == 0) - return l; + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *p = list_at(&plugins, i); + + if (p->type == type && strcmp(p->name, name) == 0) + return p; } return NULL; @@ -79,7 +81,9 @@ struct plugin * plugin_lookup(enum plugin_type type, const char *name) void plugin_dump(enum plugin_type type) { - list_foreach(struct plugin *p, &plugins) { + for (size_t i = 0; i < list_length(&plugins); i++) { + struct plugin *p = list_at(&plugins, i); + if (p->type == type) printf(" - %-12s: %s\n", p->name, p->description); } diff --git a/lib/super_node.c b/lib/super_node.c index 5a66f8800..5e7b5b582 100644 --- a/lib/super_node.c +++ b/lib/super_node.c @@ -131,9 +131,7 @@ int super_node_parse_uri(struct super_node *sn, const char *uri) afclose(af); else fclose(f); - - - + return super_node_parse(sn, cfg_root); } else { INDENT @@ -278,13 +276,17 @@ int super_node_check(struct super_node *sn) { int ret; - list_foreach(struct node *n, &sn->nodes) { + for (size_t i = 0; i < list_length(&sn->nodes); i++) { + struct node *n = list_at(&sn->nodes, i); + ret = node_check(n); if (ret) error("Invalid configuration for node %s", node_name(n)); } - list_foreach(struct path *p, &sn->paths) { + for (size_t i = 0; i < list_length(&sn->paths); i++) { + struct path *p = list_at(&sn->paths, i); + ret = path_check(p); if (ret) error("Invalid configuration for path %s", path_name(p)); @@ -306,14 +308,16 @@ int super_node_start(struct super_node *sn) web_start(&sn->web); info("Start node types"); - list_foreach(struct node *n, &sn->nodes) { INDENT - config_setting_t *cfg = config_root_setting(&sn->cfg); + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); - node_type_start(n->_vt, sn->cli.argc, sn->cli.argv, cfg); + node_type_start(n->_vt, sn); } info("Starting nodes"); - list_foreach(struct node *n, &sn->nodes) { INDENT + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); + int refs = list_count(&sn->paths, (cmp_cb_t) path_uses_node, n); if (refs > 0) node_start(n); @@ -322,7 +326,9 @@ int super_node_start(struct super_node *sn) } info("Starting paths"); - list_foreach(struct path *p, &sn->paths) { INDENT + for (size_t i = 0; i < list_length(&sn->paths); i++) { INDENT + struct path *p = list_at(&sn->paths, i); + if (p->enabled) { path_init(p, sn); path_start(p); @@ -341,17 +347,22 @@ int super_node_stop(struct super_node *sn) assert(sn->state == STATE_STARTED); info("Stopping paths"); - list_foreach(struct path *p, &sn->paths) { INDENT + for (size_t i = 0; i < list_length(&sn->paths); i++) { INDENT + struct path *p = list_at(&sn->paths, i); + path_stop(p); } info("Stopping nodes"); - list_foreach(struct node *n, &sn->nodes) { INDENT + for (size_t i = 0; i < list_length(&sn->nodes); i++) { INDENT + struct node *n = list_at(&sn->nodes, i); + node_stop(n); } info("De-initializing node types"); - list_foreach(struct plugin *p, &plugins) { INDENT + for (size_t i = 0; i < list_length(&plugins); i++) { INDENT + struct plugin *p = list_at(&plugins, i); if (p->type == PLUGIN_TYPE_NODE) node_type_stop(&p->node); } diff --git a/src/node.c b/src/node.c index 9380cf56c..d24d3b706 100644 --- a/src/node.c +++ b/src/node.c @@ -107,9 +107,14 @@ int main(int argc, char *argv[]) while (1) { now = time_now(); if (sn.stats > 0 && time_delta(&last, &now) > sn.stats) { - list_foreach(struct path *p, &sn.paths) { - list_foreach(struct hook *h, &p->hooks) - hook_run(h, HOOK_PERIODIC, NULL); + for (size_t i = 0; i < list_length(&sn.paths); i++) { + struct path *p = list_at(&sn.paths, i); + + for (size_t j = 0; j < list_length(&p->hooks); j++) { + struct hook *h = list_at(&p->hooks, j); + + hook_run(h, HOOK_PERIODIC, NULL, 0); + } } last = time_now(); diff --git a/tests/unit/list.c b/tests/unit/list.c index 591711aaa..9a6d6b7b8 100644 --- a/tests/unit/list.c +++ b/tests/unit/list.c @@ -116,15 +116,18 @@ Test(list, basics) cr_assert_eq(list_last(&l), (void *) 99); cr_assert_eq(list_first(&l), NULL); - i = 0; - list_foreach (void *j, &l) - cr_assert_eq(j, (void *) i++); + for (size_t j = 0, i = 0; j < list_length(&l); j++) { + void *k = list_at(&l, j); + + cr_assert_eq(k, (void *) i++); + } list_sort(&l, compare); /* Reverse list */ - i = 99; - list_foreach (void *j, &l) { - cr_assert_eq(j, (void *) i, "Is %p, expected %p", i, j); + for (size_t j = 0, i = 99; j < list_length(&l); j++) { + void *k = list_at(&l, j); + + cr_assert_eq(k, (void *) i, "Is %p, expected %p", i, k); i--; }