Browse Source

gossipd: avoid tal overhead in listnodes

We know exactly how many there will be, so allocate an entire array up-front.

  -listnodes_sec:2.540000-2.610000(2.584+/-0.029)
  +listnodes_sec:2.100000-2.170000(2.118+/-0.026)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
htlc_accepted_hook
Rusty Russell 6 years ago
parent
commit
c7034f271a
  1. 44
      gossipd/gossipd.c

44
gossipd/gossipd.c

@ -2150,16 +2150,13 @@ static struct io_plan *getchannels_req(struct io_conn *conn,
/*~ Similarly, lightningd asks us for all nodes when it gets `listnodes` */ /*~ Similarly, lightningd asks us for all nodes when it gets `listnodes` */
/* We keep pointers into n, assuming it won't change. */ /* We keep pointers into n, assuming it won't change. */
static void append_node(struct daemon *daemon, static void add_node_entry(const tal_t *ctx,
const struct gossip_getnodes_entry ***entries, struct daemon *daemon,
const struct node *n) const struct node *n,
struct gossip_getnodes_entry *e)
{ {
struct gossip_getnodes_entry *e;
e = tal(*entries, struct gossip_getnodes_entry);
e->nodeid = n->id; e->nodeid = n->id;
if (get_node_announcement(ctx, daemon, n,
if (get_node_announcement(e, daemon, n,
e->color, e->alias, e->color, e->alias,
&e->globalfeatures, &e->globalfeatures,
&e->addresses)) { &e->addresses)) {
@ -2170,8 +2167,6 @@ static void append_node(struct daemon *daemon,
* channel_update". */ * channel_update". */
e->last_timestamp = -1; e->last_timestamp = -1;
} }
tal_arr_expand(entries, e);
} }
/* Simply routine when they ask for `listnodes` */ /* Simply routine when they ask for `listnodes` */
@ -2181,6 +2176,7 @@ static struct io_plan *getnodes(struct io_conn *conn, struct daemon *daemon,
u8 *out; u8 *out;
struct node *n; struct node *n;
const struct gossip_getnodes_entry **nodes; const struct gossip_getnodes_entry **nodes;
struct gossip_getnodes_entry *node_arr;
struct node_id *id; struct node_id *id;
if (!fromwire_gossip_getnodes_request(tmpctx, msg, &id)) if (!fromwire_gossip_getnodes_request(tmpctx, msg, &id))
@ -2188,19 +2184,33 @@ static struct io_plan *getnodes(struct io_conn *conn, struct daemon *daemon,
/* Format of reply is the same whether they ask for a specific node /* Format of reply is the same whether they ask for a specific node
* (0 or one responses) or all nodes (0 or more) */ * (0 or one responses) or all nodes (0 or more) */
nodes = tal_arr(tmpctx, const struct gossip_getnodes_entry *, 0);
if (id) { if (id) {
n = get_node(daemon->rstate, id); n = get_node(daemon->rstate, id);
if (n) if (n) {
append_node(daemon, &nodes, n); node_arr = tal_arr(tmpctx,
struct gossip_getnodes_entry,
1);
add_node_entry(node_arr, daemon, n, &node_arr[0]);
} else
nodes = NULL;
} else { } else {
struct node_map_iter i; struct node_map_iter it;
n = node_map_first(daemon->rstate->nodes, &i); size_t i = 0;
node_arr = tal_arr(tmpctx, struct gossip_getnodes_entry,
daemon->rstate->nodes->raw.elems);
n = node_map_first(daemon->rstate->nodes, &it);
while (n != NULL) { while (n != NULL) {
append_node(daemon, &nodes, n); add_node_entry(node_arr, daemon, n, &node_arr[i++]);
n = node_map_next(daemon->rstate->nodes, &i); n = node_map_next(daemon->rstate->nodes, &it);
} }
assert(i == daemon->rstate->nodes->raw.elems);
} }
/* FIXME: towire wants array of pointers. */
nodes = tal_arr(node_arr, const struct gossip_getnodes_entry *,
tal_count(node_arr));
for (size_t i = 0; i < tal_count(node_arr); i++)
nodes[i] = &node_arr[i];
out = towire_gossip_getnodes_reply(NULL, nodes); out = towire_gossip_getnodes_reply(NULL, nodes);
daemon_conn_send(daemon->master, take(out)); daemon_conn_send(daemon->master, take(out));
return daemon_conn_read_next(conn, daemon->master); return daemon_conn_read_next(conn, daemon->master);

Loading…
Cancel
Save