perf: add maprintf and simpleformat printf tests
No binary (build failed)
—
(log yok)
| @@ -45,6 +45,8 @@ CURLX_C = \ | |
| TESTS_C = \ | |
| base64dec.c \ | |
| base64enc.c \ | |
| + | maprintf.c \ |
| + | simpleformat.c \ |
| snprintf.c \ | |
| urldecode.c \ | |
| urlencode.c \ | |
| @@ -45,6 +45,24 @@ call: | |
| ./perf snprintf [loops] | |
| + | ## `maprintf` |
| + | |
| + | This test repeatedly formats a request header block with `curl_maprintf()`, |
| + | which allocates the result, and measures the time per call. It exercises the |
| + | allocating output path and a `curl_off_t` conversion, which the `snprintf` |
| + | test does not: |
| + | |
| + | ./perf maprintf [loops] |
| + | |
| + | ## `simpleformat` |
| + | |
| + | This test repeatedly formats a commonly used simple message with |
| + | `curl_msnprintf()`: literal text plus `%s`, a `size_t` and a `curl_off_t`, |
| + | with no width or precision. Where `snprintf` measures an elaborate format, |
| + | this measures the common one: |
| + | |
| + | ./perf simpleformat [loops] |
| + | |
| ## `urlencode` | |
| This test URL (percent) encodes a 256-byte buffer that has every different | |
| @@ -0,0 +1,75 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "first.h" |
| + | |
| + | /* snprintf.c times curl_msnprintf() into a caller's buffer. This test times |
| + | curl_maprintf(), which allocates and returns the result. libcurl builds |
| + | request lines and headers with curlx_dyn_addf(), which formats through the |
| + | same allocating code (curl_mvaprintf), so this exercises that path and its |
| + | per-byte cost, which differs from the fixed-buffer one. The format is a |
| + | request-header-like block: literal text, %s, and a curl_off_t. The |
| + | allocation and the free are inside the timed loop on purpose, because a |
| + | caller pays them. */ |
| + | |
| + | static int test_maprintf(int argc, const char **argv) |
| + | { |
| + | struct curltime start; |
| + | struct curltime end; |
| + | timediff_t us; |
| + | long long hn; |
| + | |
| + | curl_off_t loops = 10000000, loop; |
| + | |
| + | if(argc > 1) { |
| + | const char *ptr = argv[1]; |
| + | curl_off_t num; |
| + | if(!curlx_str_number(&ptr, &num, CURL_OFF_T_MAX) && !*ptr) |
| + | loops = num; |
| + | } |
| + | |
| + | start = curlx_now(); |
| + | for(loop = 0; loop < loops; loop++) { |
| + | char *s = curl_maprintf("%s %s HTTP/1.1\r\n" |
| + | "Host: %s\r\n" |
| + | "Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", |
| + | "POST", "/path/to/resource", "example.com", |
| + | (curl_off_t)4096); |
| + | if(!s) { |
| + | curl_mfprintf(stderr, "curl_maprintf() failed\n"); |
| + | return 1; |
| + | } |
| + | curl_free(s); |
| + | } |
| + | end = curlx_now(); |
| + | us = curlx_timediff_us(end, start); /* how many microseconds */ |
| + | hn = loops ? us * 100000 / loops : 0; /* 100 times too big */ |
| + | curl_mprintf("Loops: %" CURL_FORMAT_CURL_OFF_T "\n" |
| + | "Time: %lld usecs\n" |
| + | "Time/loop: %lld.%0lld ns\n", |
| + | loops, |
| + | (long long)us, |
| + | (long long)hn / 100, |
| + | (long long)hn % 100); |
| + | return 0; |
| + | } |
| @@ -0,0 +1,70 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| + | * |
| + | * This software is licensed as described in the file COPYING, which |
| + | * you should have received as part of this distribution. The terms |
| + | * are also available at https://curl.se/docs/copyright.html. |
| + | * |
| + | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| + | * copies of the Software, and permit persons to whom the Software is |
| + | * furnished to do so, under the terms of the COPYING file. |
| + | * |
| + | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| + | * KIND, either express or implied. |
| + | * |
| + | * SPDX-License-Identifier: curl |
| + | * |
| + | ***************************************************************************/ |
| + | #include "first.h" |
| + | |
| + | /* snprintf.c times a format that uses widths and a '*' argument. This test |
| + | times a commonly used simple format instead: literal text plus %s, a size_t |
| + | and a curl_off_t, with no width or precision. It is the shape of the |
| + | messages curl builds with infof() and similar all over the library; it is |
| + | modeled on one in lib/imap.c rather than copied from it, so it measures the |
| + | common case rather than the elaborate one. The sink is a caller's buffer, |
| + | as in snprintf.c. */ |
| + | |
| + | static int test_simpleformat(int argc, const char **argv) |
| + | { |
| + | struct curltime start; |
| + | struct curltime end; |
| + | timediff_t us; |
| + | long long hn; |
| + | |
| + | curl_off_t loops = 10000000, loop; |
| + | |
| + | char buffer[256]; |
| + | |
| + | if(argc > 1) { |
| + | const char *ptr = argv[1]; |
| + | curl_off_t num; |
| + | if(!curlx_str_number(&ptr, &num, CURL_OFF_T_MAX) && !*ptr) |
| + | loops = num; |
| + | } |
| + | |
| + | start = curlx_now(); |
| + | for(loop = 0; loop < loops; loop++) { |
| + | curl_msnprintf(buffer, sizeof(buffer), |
| + | "%s: wrote %zu bytes, %" CURL_FORMAT_CURL_OFF_T |
| + | " bytes are left for transfer\n", |
| + | "upload", (size_t)4096, (curl_off_t)1048576); |
| + | } |
| + | end = curlx_now(); |
| + | us = curlx_timediff_us(end, start); /* how many microseconds */ |
| + | hn = loops ? us * 100000 / loops : 0; /* 100 times too big */ |
| + | curl_mprintf("Loops: %" CURL_FORMAT_CURL_OFF_T "\n" |
| + | "Time: %lld usecs\n" |
| + | "Time/loop: %lld.%0lld ns\n", |
| + | loops, |
| + | (long long)us, |
| + | (long long)hn / 100, |
| + | (long long)hn % 100); |
| + | return 0; |
| + | } |