From: Viktor Szakats Date: Sun, 25 Sep 2022 21:58:21 +0000 (+0000) Subject: autotools: reduce brute-force when detecting recv/send arg list X-Git-Tag: curl-7_86_0~165 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6adcff68b8e4875c5efd7ed30b043e508ad538ee;p=thirdparty%2Fcurl.git autotools: reduce brute-force when detecting recv/send arg list autotools uses brute-force to detect `recv`/`send`/`select` argument lists, by interating through _all_ argument type combinations on each `./configure` run. This logic exists since 01fa02d0b545e1433dced2430561f8c0c72b74a9 (from 2006) and was a bit later extended with Windows support. This results in a worst-case number of compile + link cycles as below: - `recv`: 96 - `send`: 192 - `select`: 60 Total: 348 (the number of curl C source files is 195, for comparison) Notice that e.g. curl-for-win autotools builds require two `./configure` invocations, doubling these numbers. `recv` on Windows was especially unlucky because `SOCKET` (the correct choice there) was listed _last_ in one of the outer trial loops. This resulted in lengthy waits while autotools was trying all invalid combinations first, wasting cycles, disk writes and slowing down iteration. This patch reduces the amount of idle work by reordering the tests in a way to succeed first on a well-known platform such as Windows, and also on non-Windows by testing for POSIX prototypes first, on the assumption that these are the most likely candidates these days. (We do not touch `select`, where the order was already optimal for these platforms.) For non-Windows, this means to try a return value of `ssize_t` first, then `int`, reordering the buffer argument type to try `void *` first, then `byte *`, and prefer the `const` flavor with `send`. If we are here, also stop testing for `SOCKET` type in non-Windows builds. After the patch, detection on Windows is instantaneous. It should also be faster on popular platforms such as Linux and BSD-based ones. If there are known-good variations for other platforms, they can also be fast-tracked like above, given a way to check for that platform inside the autotools logic. Reviewed-by: Daniel Stenberg Closes #9591 --- diff --git a/acinclude.m4 b/acinclude.m4 index cd26f43068..7902cfe7bd 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -851,11 +851,21 @@ $curl_includes_bsdsocket if test "$curl_cv_recv" = "yes"; then AC_CACHE_CHECK([types of args and return type for recv], [curl_cv_func_recv_args], [ + if test "$curl_cv_native_windows" = "yes"; then + # Win32: int (SOCKET, char *, int, int) + retv_test1='int' ; arg1_test1='SOCKET' ; arg2_test1='char *'; arg3_test1='int' + retv_test2='ssize_t'; arg1_test2='int' ; arg2_test2='void *'; arg3_test2='size_t' + else + # POSIX: ssize_t (int, void *, size_t, int) + retv_test1='ssize_t'; arg1_test1='int' ; arg2_test1='void *'; arg3_test1='size_t' + retv_test2='int' ; arg1_test2='ssize_t'; arg2_test2='char *'; arg3_test2='int' + fi curl_cv_func_recv_args="unknown" - for recv_retv in 'int' 'ssize_t'; do - for recv_arg1 in 'int' 'ssize_t' 'SOCKET'; do - for recv_arg2 in 'char *' 'void *'; do - for recv_arg3 in 'size_t' 'int' 'socklen_t' 'unsigned int'; do + # Brute-force tests: 2 * 3 * 2 * 4 * 2 -> 96 runs max + for recv_retv in "${retv_test1}" "${retv_test2}"; do + for recv_arg1 in "${arg1_test1}" "${arg1_test2}"; do + for recv_arg2 in "${arg2_test1}" "${arg2_test2}"; do + for recv_arg3 in "${arg3_test1}" "${arg3_test2}" 'socklen_t' 'unsigned int'; do for recv_arg4 in 'int' 'unsigned int'; do if test "$curl_cv_func_recv_args" = "unknown"; then AC_COMPILE_IFELSE([ @@ -981,11 +991,21 @@ $curl_includes_bsdsocket if test "$curl_cv_send" = "yes"; then AC_CACHE_CHECK([types of args and return type for send], [curl_cv_func_send_args], [ + if test "$curl_cv_native_windows" = "yes"; then + # Win32: int (SOCKET, const char *, int, int) + retv_test1='int' ; arg1_test1='SOCKET' ; arg2_test1='const char *'; arg3_test1='int' + retv_test2='ssize_t'; arg1_test2='int' ; arg2_test2='const void *'; arg3_test2='size_t' + else + # POSIX: ssize_t (int, const void *, size_t, int) + retv_test1='ssize_t'; arg1_test1='int' ; arg2_test1='const void *'; arg3_test1='size_t' + retv_test2='int' ; arg1_test2='ssize_t'; arg2_test2='const char *'; arg3_test2='int' + fi curl_cv_func_send_args="unknown" - for send_retv in 'int' 'ssize_t'; do - for send_arg1 in 'int' 'ssize_t' 'SOCKET'; do - for send_arg2 in 'char *' 'void *' 'const char *' 'const void *'; do - for send_arg3 in 'size_t' 'int' 'socklen_t' 'unsigned int'; do + # Brute-force tests: 2 * 3 * 4 * 4 * 2 -> 192 runs max + for send_retv in "${retv_test1}" "${retv_test2}"; do + for send_arg1 in "${arg1_test1}" "${arg1_test2}"; do + for send_arg2 in "${arg2_test1}" "${arg2_test2}" 'void *' 'char *'; do + for send_arg3 in "${arg3_test1}" "${arg3_test2}" 'socklen_t' 'unsigned int'; do for send_arg4 in 'int' 'unsigned int'; do if test "$curl_cv_func_send_args" = "unknown"; then AC_COMPILE_IFELSE([ @@ -1579,6 +1599,8 @@ $curl_includes_bsdsocket AC_CACHE_CHECK([types of args and return type for select], [curl_cv_func_select_args], [ curl_cv_func_select_args="unknown" + # POSIX/Win32: int (int, fd_set *, fd_set *, fd_set *, struct timeval *) + # Brute-force tests: 2 * 5 * 3 * 2 -> 60 runs max for sel_retv in 'int' 'ssize_t'; do for sel_arg1 in 'int' 'ssize_t' 'size_t' 'unsigned long int' 'unsigned int'; do for sel_arg234 in 'fd_set *' 'int *' 'void *'; do