]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
autotools: reduce brute-force when detecting recv/send arg list
authorViktor Szakats <commit@vsz.me>
Sun, 25 Sep 2022 21:58:21 +0000 (21:58 +0000)
committerViktor Szakats <commit@vsz.me>
Sun, 25 Sep 2022 21:58:21 +0000 (21:58 +0000)
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

acinclude.m4

index cd26f43068c9e87dfc93abd4f5707d32b35fcbba..7902cfe7bd84962ec24ac30aefd046322fd8bc44 100644 (file)
@@ -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