From 1c184e718f5745cf3a53a3c389814a792e73aa51 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 29 Feb 2020 18:35:55 -0500 Subject: passwd: Cache the user/group tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a significant optimization for conditions that need these tables: Benchmark #1: ./bfs ~/code/linux -nouser >/dev/null Time (mean ± σ): 232.0 ms ± 2.5 ms [User: 44.3 ms, System: 185.0 ms] Range (min … max): 228.7 ms … 238.7 ms 12 runs Benchmark #2: ./bfs-1.6 ~/code/linux -nouser >/dev/null Time (mean ± σ): 1.050 s ± 0.012 s [User: 544.2 ms, System: 500.0 ms] Range (min … max): 1.025 s … 1.063 s 10 runs Benchmark #3: find ~/code/linux -nouser >/dev/null Time (mean ± σ): 1.040 s ± 0.012 s [User: 533.6 ms, System: 500.6 ms] Range (min … max): 1.017 s … 1.054 s 10 runs Summary './bfs ~/code/linux -nouser >/dev/null' ran 4.48 ± 0.07 times faster than 'find ~/code/linux -nouser >/dev/null' 4.52 ± 0.07 times faster than './bfs-1.6 ~/code/linux -nouser >/dev/null' --- parse.c | 50 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'parse.c') diff --git a/parse.c b/parse.c index 1de065b..891e6e1 100644 --- a/parse.c +++ b/parse.c @@ -31,6 +31,7 @@ #include "expr.h" #include "fsade.h" #include "mtab.h" +#include "passwd.h" #include "printf.h" #include "spawn.h" #include "stat.h" @@ -267,6 +268,9 @@ int free_cmdline(struct cmdline *cmdline) { free_bfs_mtab(cmdline->mtab); + bfs_free_groups(cmdline->groups); + bfs_free_users(cmdline->users); + struct trie_leaf *leaf; while ((leaf = trie_first_leaf(&cmdline->open_files))) { struct open_file *ofile = leaf->value; @@ -1299,7 +1303,6 @@ static struct expr *parse_fls(struct parser_state *state, int arg1, int arg2) { if (expr) { expr_set_always_true(expr); expr->cost = PRINT_COST; - expr->ephemeral_fds = 1; if (expr_open(state, expr, expr->sdata) != 0) { goto fail; } @@ -1414,6 +1417,12 @@ static struct expr *parse_fstype(struct parser_state *state, int arg1, int arg2) * Parse -gid/-group. */ static struct expr *parse_group(struct parser_state *state, int arg1, int arg2) { + struct cmdline *cmdline = state->cmdline; + if (!cmdline->groups) { + parse_error(state, "Couldn't parse the group table: %s.\n", strerror(cmdline->groups_error)); + return NULL; + } + const char *arg = state->argv[0]; struct expr *expr = parse_unary_test(state, eval_gid); @@ -1421,7 +1430,7 @@ static struct expr *parse_group(struct parser_state *state, int arg1, int arg2) return NULL; } - struct group *grp = getgrnam(expr->sdata); + const struct group *grp = bfs_getgrnam(cmdline->groups, expr->sdata); if (grp) { expr->idata = grp->gr_gid; expr->cmp_flag = CMP_EXACT; @@ -1466,6 +1475,12 @@ static struct expr *parse_used(struct parser_state *state, int arg1, int arg2) { * Parse -uid/-user. */ static struct expr *parse_user(struct parser_state *state, int arg1, int arg2) { + struct cmdline *cmdline = state->cmdline; + if (!cmdline->users) { + parse_error(state, "Couldn't parse the user table: %s.\n", strerror(cmdline->users_error)); + return NULL; + } + const char *arg = state->argv[0]; struct expr *expr = parse_unary_test(state, eval_uid); @@ -1473,7 +1488,7 @@ static struct expr *parse_user(struct parser_state *state, int arg1, int arg2) { return NULL; } - struct passwd *pwd = getpwnam(expr->sdata); + const struct passwd *pwd = bfs_getpwnam(cmdline->users, expr->sdata); if (pwd) { expr->idata = pwd->pw_uid; expr->cmp_flag = CMP_EXACT; @@ -1545,7 +1560,6 @@ static struct expr *parse_ls(struct parser_state *state, int arg1, int arg2) { struct expr *expr = parse_nullary_action(state, eval_fls); if (expr) { init_print_expr(state, expr); - expr->ephemeral_fds = 1; expr->reftime = state->now; } return expr; @@ -1743,11 +1757,16 @@ fail: * Parse -nogroup. */ static struct expr *parse_nogroup(struct parser_state *state, int arg1, int arg2) { + struct cmdline *cmdline = state->cmdline; + if (!cmdline->groups) { + parse_error(state, "Couldn't parse the group table: %s.\n", strerror(cmdline->groups_error)); + return NULL; + } + struct expr *expr = parse_nullary_test(state, eval_nogroup); if (expr) { expr->cost = 9000.0; expr->probability = 0.01; - expr->ephemeral_fds = 1; } return expr; } @@ -1775,11 +1794,16 @@ static struct expr *parse_noleaf(struct parser_state *state, int arg1, int arg2) * Parse -nouser. */ static struct expr *parse_nouser(struct parser_state *state, int arg1, int arg2) { + struct cmdline *cmdline = state->cmdline; + if (!cmdline->users) { + parse_error(state, "Couldn't parse the user table: %s.\n", strerror(cmdline->users_error)); + return NULL; + } + struct expr *expr = parse_nullary_test(state, eval_nouser); if (expr) { expr->cost = 9000.0; expr->probability = 0.01; - expr->ephemeral_fds = 1; } return expr; } @@ -3452,6 +3476,10 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { cmdline->colors = NULL; cmdline->cout = NULL; cmdline->cerr = NULL; + cmdline->users = NULL; + cmdline->users_error = 0; + cmdline->groups = NULL; + cmdline->groups_error = 0; cmdline->mtab = NULL; cmdline->mtab_error = 0; cmdline->mindepth = 0; @@ -3497,6 +3525,16 @@ struct cmdline *parse_cmdline(int argc, char *argv[]) { goto fail; } + cmdline->users = bfs_parse_users(); + if (!cmdline->users) { + cmdline->users_error = errno; + } + + cmdline->groups = bfs_parse_groups(); + if (!cmdline->groups) { + cmdline->groups_error = errno; + } + cmdline->mtab = parse_bfs_mtab(); if (!cmdline->mtab) { cmdline->mtab_error = errno; -- cgit v1.2.3