The find utility uses a hardcoded value of 32 * 1024 as the limit of
the command-line length when calling 'find -exec ... {} +'. This results
in over 4 times more execve() calls than in coreutils' find.This patch proposes to use the limit defined in system headers. function old new delta bb_sc_arg_max - 16 +16 find_main 480 492 +12 func_exec 152 156 +4 xargs_main 923 909 -14 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 2/1 up/down: 32/-14) Total: 18 bytes text data bss dec hex filename 815849 4123 9504 829476 ca824 busybox_old 815867 4123 9504 829494 ca836 busybox_unstripped Signed-off-by: Bartosz Golaszewski <[email protected]> --- findutils/find.c | 4 +++- findutils/xargs.c | 23 ++++++++--------------- include/libbb.h | 3 +++ libbb/Kbuild.src | 1 + libbb/sysconf.c | 30 ++++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 libbb/sysconf.c diff --git a/findutils/find.c b/findutils/find.c index 8ac3da7..6ffcbab 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -419,6 +419,7 @@ struct globals { smallint need_print; smallint xdev_on; recurse_flags_t recurse_flags; + IF_FEATURE_FIND_EXEC_PLUS(long max_argv_len;) } FIX_ALIASING; #define G (*(struct globals*)&bb_common_bufsiz1) #define INIT_G() do { \ @@ -428,6 +429,7 @@ struct globals { /* we have to zero it out because of NOEXEC */ \ memset(&G, 0, sizeof(G)); \ IF_FEATURE_FIND_MAXDEPTH(G.minmaxdepth[1] = INT_MAX;) \ + IF_FEATURE_FIND_EXEC_PLUS(G.max_argv_len = bb_sc_arg_max();) \ G.need_print = 1; \ G.recurse_flags = ACTION_RECURSE; \ } while (0) @@ -672,7 +674,7 @@ ACTF(exec) int rc = 0; /* If we have lots of files already, exec the command */ - if (ap->file_len >= 32*1024) + if (ap->file_len >= G.max_argv_len) rc = do_exec(ap, NULL); ap->file_len += strlen(fileName) + sizeof(char*) + 1; diff --git a/findutils/xargs.c b/findutils/xargs.c index 0ba5b56..67e7a66 100644 --- a/findutils/xargs.c +++ b/findutils/xargs.c @@ -523,11 +523,7 @@ int xargs_main(int argc, char **argv) argc++; } - /* -s NUM default. fileutils-4.4.2 uses 128k, but I heasitate - * to use such a big value - first need to change code to use - * growable buffer instead of fixed one. - */ - n_max_chars = 32 * 1024; + n_max_chars = bb_sc_arg_max(); /* previously hardcoded to 32 * 1024 */ /* Make smaller if system does not allow our default value. * The Open Group Base Specifications Issue 6: * "The xargs utility shall limit the command line length such that @@ -536,16 +532,13 @@ int xargs_main(int argc, char **argv) * in the System Interfaces volume of IEEE Std 1003.1-2001) * shall not exceed {ARG_MAX}-2048 bytes". */ - { - long arg_max = 0; -#if defined _SC_ARG_MAX - arg_max = sysconf(_SC_ARG_MAX) - 2048; -#elif defined ARG_MAX - arg_max = ARG_MAX - 2048; -#endif - if (arg_max > 0 && n_max_chars > arg_max) - n_max_chars = arg_max; - } + + /* TODO Introduce a growable buffer and use bb_sc_arg_max() to + * determine a safe value for n_max_chars. Remove this check afterwards. + */ + if (n_max_chars > (32 * 1024)) + n_max_chars = 32 * 1024; + if (opt & OPT_UPTO_SIZE) { n_max_chars = xatou_range(max_chars, 1, INT_MAX); } diff --git a/include/libbb.h b/include/libbb.h index a1a0dc1..3e645d6 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -731,6 +731,9 @@ extern void *xmalloc_open_read_close(const char *filename, size_t *maxsz_p) FAST /* Never returns NULL */ extern void *xmalloc_xopen_read_close(const char *filename, size_t *maxsz_p) FAST_FUNC RETURNS_MALLOC; +/* sysconf() wrappers */ +long bb_sc_arg_max(void) FAST_FUNC; + #define SEAMLESS_COMPRESSION (0 \ || ENABLE_FEATURE_SEAMLESS_XZ \ || ENABLE_FEATURE_SEAMLESS_LZMA \ diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 6578d11..62680bd 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -92,6 +92,7 @@ lib-y += skip_whitespace.o lib-y += speed_table.o lib-y += str_tolower.o lib-y += strrstr.o +lib-y += sysconf.o lib-y += time.o lib-y += trim.o lib-y += u_signal_names.o diff --git a/libbb/sysconf.c b/libbb/sysconf.c new file mode 100644 index 0000000..3635c43 --- /dev/null +++ b/libbb/sysconf.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various system configuration helpers. + * + * Copyright (C) 2014 Bartosz Golaszewski <[email protected]> + * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. + */ + +#include "libbb.h" + +/* + * Return the maximum command line length. + * + * In case neither _SC_ARG_MAX nor ARG_MAX macros are defined + * we resort to using a small (ie. safe) default of 32 * 1024. + * + * POSIX suggests to substract 2048 bytes from sysconf(_SC_ARG_MAX) + * so that the process may safely modify its environment. + */ +long FAST_FUNC bb_sc_arg_max(void) +{ +#if defined _SC_ARG_MAX + return sysconf(_SC_ARG_MAX) - 2048; +#elif defined ARG_MAX + return ARG_MAX - 2048; +#else + return 32 * 1024; +#endif +} -- 1.9.1 _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
