diff options
author | Phil Sutter <phil@nwl.cc> | 2020-11-20 20:01:59 +0100 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2020-11-23 00:12:02 +0100 |
commit | 389a0e1edc89a4048a272e569d3349b1d43bc567 (patch) | |
tree | ad4c3da174bf557c898d144e3e99a2d190d9d769 | |
parent | 31f73c4c2323d2ba8634d67f37033342bc5784ed (diff) |
json: echo: Speedup seqnum_to_json()
Derek Dai reports:
"If there are a lot of command in JSON node, seqnum_to_json() will slow
down application (eg: firewalld) dramatically since it iterate whole
command list every time."
He sent a patch implementing a lookup table, but we can do better: Speed
this up by introducing a hash table to store the struct json_cmd_assoc
objects in, taking their netlink sequence number as key.
Quickly tested restoring a ruleset containing about 19k rules:
| # time ./before/nft -jeaf large_ruleset.json >/dev/null
| 4.85user 0.47system 0:05.48elapsed 97%CPU (0avgtext+0avgdata 69732maxresident)k
| 0inputs+0outputs (15major+16937minor)pagefaults 0swaps
| # time ./after/nft -jeaf large_ruleset.json >/dev/null
| 0.18user 0.44system 0:00.70elapsed 89%CPU (0avgtext+0avgdata 68484maxresident)k
| 0inputs+0outputs (15major+16645minor)pagefaults 0swaps
Bugzilla: https://bugzilla.netfilter.org/show_bug.cgi?id=1479
Reported-by: Derek Dai <daiderek@gmail.com>
Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r-- | src/parser_json.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/src/parser_json.c b/src/parser_json.c index b1de56a4..6ebbb408 100644 --- a/src/parser_json.c +++ b/src/parser_json.c @@ -3762,42 +3762,50 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root) } struct json_cmd_assoc { - struct json_cmd_assoc *next; + struct hlist_node hnode; const struct cmd *cmd; json_t *json; }; -static struct json_cmd_assoc *json_cmd_list = NULL; +#define CMD_ASSOC_HSIZE 512 +static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE]; static void json_cmd_assoc_free(void) { struct json_cmd_assoc *cur; + struct hlist_node *pos, *n; + int i; - while (json_cmd_list) { - cur = json_cmd_list; - json_cmd_list = cur->next; - free(cur); + for (i = 0; i < CMD_ASSOC_HSIZE; i++) { + hlist_for_each_entry_safe(cur, pos, n, + &json_cmd_assoc_hash[i], hnode) + free(cur); } } static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd) { struct json_cmd_assoc *new = xzalloc(sizeof *new); + int key = cmd->seqnum % CMD_ASSOC_HSIZE; - new->next = json_cmd_list; new->json = json; new->cmd = cmd; - json_cmd_list = new; + + hlist_add_head(&new->hnode, &json_cmd_assoc_hash[key]); } static json_t *seqnum_to_json(const uint32_t seqnum) { - const struct json_cmd_assoc *cur; + int key = seqnum % CMD_ASSOC_HSIZE; + struct json_cmd_assoc *cur; + struct hlist_node *n; - for (cur = json_cmd_list; cur; cur = cur->next) { + + hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) { if (cur->cmd->seqnum == seqnum) return cur->json; } + return NULL; } |