From: Noah Goldstein <goldstein.w.n@gmail.com>
To: libc-alpha@sourceware.org
Cc: hjl.tools@gmail.com, carlos@systemhalted.org
Subject: Re: [PATCH v1] Benchtest: Add benchtests for {wcs,str}lcpy and {wcs,str}lcat
Date: Fri, 21 Apr 2023 19:24:32 -0500 [thread overview]
Message-ID: <CAFUsyfKfQ6Wh4N853UCvZpCLV=XqjapTHzrf3tmiuos6R4VaTQ@mail.gmail.com> (raw)
In-Reply-To: <20230422002319.2592882-1-goldstein.w.n@gmail.com>
On Fri, Apr 21, 2023 at 7:23 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> Mostly reuses the existing code for strncpy/strncat respectively.
> ---
> benchtests/Makefile | 4 +++
> benchtests/bench-stpncpy.c | 2 +-
> benchtests/bench-string.h | 24 +++++++------
> benchtests/bench-strlcat.c | 65 +++++++++++++++++++++++++++++++++++
> benchtests/bench-strlcpy.c | 63 ++++++++++++++++++++++++++++++++++
> benchtests/bench-strncat.c | 69 +++++++++++++++++++++++---------------
> benchtests/bench-strncpy.c | 22 +++++++++---
> benchtests/bench-wcslcat.c | 20 +++++++++++
> benchtests/bench-wcslcpy.c | 20 +++++++++++
> 9 files changed, 246 insertions(+), 43 deletions(-)
> create mode 100644 benchtests/bench-strlcat.c
> create mode 100644 benchtests/bench-strlcpy.c
> create mode 100644 benchtests/bench-wcslcat.c
> create mode 100644 benchtests/bench-wcslcpy.c
>
> diff --git a/benchtests/Makefile b/benchtests/Makefile
> index 5bd763a19d..336a3555f9 100644
> --- a/benchtests/Makefile
> +++ b/benchtests/Makefile
> @@ -162,6 +162,8 @@ string-benchset := \
> strcpy \
> strcpy_chk \
> strcspn \
> + strlcat \
> + strlcpy \
> strlen \
> strncasecmp \
> strncat \
> @@ -188,6 +190,8 @@ wcsmbs-benchset := \
> wcscmp \
> wcscpy \
> wcscspn \
> + wcslcat \
> + wcslcpy \
> wcslen \
> wcsncat \
> wcsncmp \
> diff --git a/benchtests/bench-stpncpy.c b/benchtests/bench-stpncpy.c
> index adc81a58ba..e824a2d3c1 100644
> --- a/benchtests/bench-stpncpy.c
> +++ b/benchtests/bench-stpncpy.c
> @@ -16,7 +16,7 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#define STRNCPY_RESULT(dst, len, n) ((dst) + ((len) > (n) ? (n) : (len)))
> +#define STRNCPY_RESULT(dst, src, len, n) ((dst) + ((len) > (n) ? (n) : (len)))
> #define TEST_MAIN
> #ifndef WIDE
> # define TEST_NAME "stpncpy"
> diff --git a/benchtests/bench-string.h b/benchtests/bench-string.h
> index dbe7084e60..44d6042142 100644
> --- a/benchtests/bench-string.h
> +++ b/benchtests/bench-string.h
> @@ -75,21 +75,23 @@ extern impl_t __start_impls[], __stop_impls[];
> # define MEMCMP memcmp
> # define MEMCPY memcpy
> # define MEMSET memset
> +# define STPCPY stpcpy
> +# define STPNCPY stpncpy
> # define STRCAT strcat
> -# define STRLEN strlen
> -# define STRCMP strcmp
> # define STRCHR strchr
> +# define STRCMP strcmp
> # define STRCPY strcpy
> -# define STRNLEN strnlen
> # define STRCSPN strcspn
> +# define STRLCPY strlcpy
> +# define STRLEN strlen
> # define STRNCAT strncat
> # define STRNCMP strncmp
> # define STRNCPY strncpy
> +# define STRNLEN strnlen
> # define STRPBRK strpbrk
> # define STRRCHR strrchr
> # define STRSPN strspn
> -# define STPCPY stpcpy
> -# define STPNCPY stpncpy
> +# define STRLCAT strlcat
> # else
> # include <wchar.h>
> # define CHAR wchar_t
> @@ -100,21 +102,23 @@ extern impl_t __start_impls[], __stop_impls[];
> # define MEMCMP wmemcmp
> # define MEMCPY wmemcpy
> # define MEMSET wmemset
> +# define STPCPY wcpcpy
> +# define STPNCPY wcpncpy
> # define STRCAT wcscat
> -# define STRLEN wcslen
> -# define STRCMP wcscmp
> # define STRCHR wcschr
> +# define STRCMP wcscmp
> # define STRCPY wcscpy
> -# define STRNLEN wcsnlen
> # define STRCSPN wcscspn
> +# define STRLCAT wcslcat
> +# define STRLCPY wcslcpy
> +# define STRLEN wcslen
> # define STRNCAT wcsncat
> # define STRNCMP wcsncmp
> # define STRNCPY wcsncpy
> +# define STRNLEN wcsnlen
> # define STRPBRK wcspbrk
> # define STRRCHR wcsrchr
> # define STRSPN wcsspn
> -# define STPCPY wcpcpy
> -# define STPNCPY wcpncpy
> # endif /* WIDE */
>
> # define TEST_FUNCTION test_main
> diff --git a/benchtests/bench-strlcat.c b/benchtests/bench-strlcat.c
> new file mode 100644
> index 0000000000..cb97c60aa0
> --- /dev/null
> +++ b/benchtests/bench-strlcat.c
> @@ -0,0 +1,65 @@
> +/* Measure stplcpy functions.
> + Copyright (C) 2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +#define DSTLEN(dst, n) STRNLEN (dst, n)
> +#define STRNCAT_RESULT(dst, src, slen, n, dlen) ((dlen) + STRLEN (src))
> +#define CMP(dst, src, slen, n, dlen) \
> + ({ \
> + size_t tmp_n_ = (n); \
> + tmp_n_ -= (dlen); \
> + size_t tmp_len_ \
> + = (tmp_n_) ? ((slen) < (tmp_n_) ? (slen) : ((tmp_n_) -1)) : 0; \
> + (((tmp_n_) != 0) && ((dst)[(dlen) + tmp_len_] != 0)) \
> + || memcmp ((dst) + (dlen), src, tmp_len_ * sizeof (CHAR)); \
> + })
> +
> +#define CHECK_NULL_TERM 0
> +#define TEST_MAIN
> +#ifndef WIDE
> +# define TEST_NAME "strlcat"
> +#else
> +# define generic_strlcat generic_wcslcat
> +# define TEST_NAME "wcslcat"
> +#endif /* WIDE */
> +#include "bench-string.h"
> +
> +#define PROTO typedef size_t (*proto_t) (CHAR *, const CHAR *, size_t)
> +
> +size_t
> +generic_strlcat (CHAR *dst, const CHAR *src, size_t n)
> +{
> + size_t src_len, dst_len;
> + src_len = STRLEN (src);
> + dst_len = STRNLEN (dst, n);
> + if (dst_len < n)
> + {
> + n -= dst_len;
> + if (src_len < n)
> + {
> + n = src_len + 1;
> + }
> + MEMCPY (dst + dst_len, src, n - 1);
> + dst[dst_len + n - 1] = 0;
> + }
> +
> + return dst_len + src_len;
> +}
> +
> +IMPL (STRLCAT, 1)
> +IMPL (generic_strlcat, 0)
> +
> +#include "bench-strncat.c"
> diff --git a/benchtests/bench-strlcpy.c b/benchtests/bench-strlcpy.c
> new file mode 100644
> index 0000000000..d87e0f5bc5
> --- /dev/null
> +++ b/benchtests/bench-strlcpy.c
> @@ -0,0 +1,63 @@
> +/* Measure stplcpy functions.
> + Copyright (C) 2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#define STRNCPY_RESULT(dst, src, len, n) STRLEN (src)
> +#define CMP(dst, src, len, n) \
> + ({ \
> + size_t tmp_len_ = (n) ? ((len) < (n) ? (len) : ((n) -1)) : 0; \
> + (((n) != 0) && ((dst)[tmp_len_] != 0)) \
> + || memcmp (dst, src, tmp_len_ * sizeof (CHAR)); \
> + })
> +#define NEED_ZFILL 0
> +#define TEST_MAIN
> +#ifndef WIDE
> +# define STRLEN strlen
> +# define MEMCPY memcpy
> +# define TEST_NAME "strlcpy"
> +#else
> +# define STRLEN wcslen
> +# define MEMCPY wmemcpy
> +# define generic_strlcpy generic_wcslcpy
> +# define TEST_NAME "wcslcpy"
> +#endif /* WIDE */
> +#include "bench-string.h"
> +
> +#define PROTO typedef size_t (*proto_t) (CHAR *, const CHAR *, size_t)
> +
> +size_t
> +generic_strlcpy (CHAR *dst, const CHAR *src, size_t n)
> +{
> + size_t src_len;
> + src_len = STRLEN (src);
> + if (n)
> + {
> + if (src_len < n)
> + {
> + n = src_len + 1;
> + }
> +
> + MEMCPY (dst, src, n - 1);
> + dst[n - 1] = 0;
> + }
> + return src_len;
> +}
> +
> +IMPL (STRLCPY, 1)
> +IMPL (generic_strlcpy, 0)
> +
> +#include "bench-strncpy.c"
> diff --git a/benchtests/bench-strncat.c b/benchtests/bench-strncat.c
> index e4792a9c3d..5dfab339a5 100644
> --- a/benchtests/bench-strncat.c
> +++ b/benchtests/bench-strncat.c
> @@ -16,26 +16,21 @@
> License along with the GNU C Library; if not, see
> <https://www.gnu.org/licenses/>. */
>
> -#define TEST_MAIN
> -#ifndef WIDE
> -# define TEST_NAME "strncat"
> -#else
> -# define TEST_NAME "wcsncat"
> -# define generic_strncat generic_wcsncat
> -#endif /* WIDE */
> -#include "bench-string.h"
> -
> -#define BIG_CHAR MAX_CHAR
> -
> -#ifndef WIDE
> -# define SMALL_CHAR 127
> -#else
> -# define SMALL_CHAR 1273
> -#endif /* WIDE */
> +#ifndef STRNCAT_RESULT
> +#define CHECK_NULL_TERM 1
> +#define STRNCAT_RESULT(dst, src, slen, n, dlen) dst
> +# define CMP(dst, src, slen, n, dlen) \
> + MEMCMP ((dst) + (dlen), src, (slen) + 1 > (n) ? (n) : (slen) + 1)
> +# define DSTLEN(dst, n) STRLEN(dst)
> +# define TEST_MAIN
> +# ifndef WIDE
> +# define TEST_NAME "strncat"
> +# else
> +# define TEST_NAME "wcsncat"
> +# define generic_strncat generic_wcsncat
> +# endif /* WIDE */
>
> -#include "json-lib.h"
> -
> -typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
> +#include "bench-string.h"
>
> CHAR *
> generic_strncat (CHAR *dst, const CHAR *src, size_t n)
> @@ -50,29 +45,49 @@ generic_strncat (CHAR *dst, const CHAR *src, size_t n)
> IMPL (STRNCAT, 2)
> IMPL (generic_strncat, 0)
>
> +#endif
> +
> +
> +#define BIG_CHAR MAX_CHAR
> +
> +#ifndef WIDE
> +# define SMALL_CHAR 127
> +#else
> +# define SMALL_CHAR 1273
> +#endif /* WIDE */
> +
> +#include "json-lib.h"
> +
> +#ifndef PROTO
> +typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
> +#else
> +PROTO;
> +#endif
> +
> +
> static void
> do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *dst, const CHAR *src,
> - size_t n)
> + size_t slen, size_t n)
> {
> - size_t k = STRLEN (dst), i, iters = INNER_LOOP_ITERS8;
> + size_t k = DSTLEN (dst, n), i, iters = INNER_LOOP_ITERS8;
> timing_t start, stop, cur;
>
> - if (CALL (impl, dst, src, n) != dst)
> + if (CALL (impl, dst, src, n) != STRNCAT_RESULT (dst, src, slen, n, k))
> {
> error (0, 0, "Wrong result in function %s %p != %p", impl->name,
> - CALL (impl, dst, src, n), dst);
> + (void *) CALL (impl, dst, src, n),
> + (void *) STRNCAT_RESULT (dst, src, slen, n, k));
> ret = 1;
> return;
> }
>
> - size_t len = STRLEN (src);
> - if (MEMCMP (dst + k, src, len + 1 > n ? n : len + 1) != 0)
> + if (CMP(dst, src, slen, n, k) != 0)
> {
> error (0, 0, "Incorrect concatenation in function %s", impl->name);
> ret = 1;
> return;
> }
> - if (n < len && dst[k + n] != '\0')
> + if (CHECK_NULL_TERM && n < slen && dst[k + n] != '\0')
> {
> error (0, 0, "There is no zero in the end of output string in %s",
> impl->name);
> @@ -133,7 +148,7 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len1,
> FOR_EACH_IMPL (impl, 0)
> {
> s2[len2] = '\0';
> - do_one_test (json_ctx, impl, s2, s1, n);
> + do_one_test (json_ctx, impl, s2, s1, len1, n);
> }
>
> json_array_end (json_ctx);
> diff --git a/benchtests/bench-strncpy.c b/benchtests/bench-strncpy.c
> index d90e3c55e2..bd762803b0 100644
> --- a/benchtests/bench-strncpy.c
> +++ b/benchtests/bench-strncpy.c
> @@ -26,8 +26,16 @@
>
> #include "json-lib.h"
>
> +#ifndef CMP
> +# define CMP(dst, src, len, n) \
> + memcmp (dst, src, ((len) > (n) ? (n) : (len)) * sizeof (CHAR))
> +#endif
> +#ifndef NEED_ZFILL
> +# define NEED_ZFILL 1
> +#endif
> +
> #ifndef STRNCPY_RESULT
> -# define STRNCPY_RESULT(dst, len, n) dst
> +# define STRNCPY_RESULT(dst, src, len, n) dst
> # define TEST_MAIN
> # ifndef WIDE
> # define TEST_NAME "strncpy"
> @@ -51,7 +59,11 @@ IMPL (generic_strncpy, 0)
>
> #endif /* !STRNCPY_RESULT */
>
> +#ifndef PROTO
> typedef CHAR *(*proto_t) (CHAR *, const CHAR *, size_t);
> +#else
> +PROTO;
> +#endif
>
> static void
> do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *dst, const CHAR *src,
> @@ -60,22 +72,22 @@ do_one_test (json_ctx_t *json_ctx, impl_t *impl, CHAR *dst, const CHAR *src,
> size_t i, iters = INNER_LOOP_ITERS_LARGE / CHARBYTES;
> timing_t start, stop, cur;
>
> - if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, len, n))
> + if (CALL (impl, dst, src, n) != STRNCPY_RESULT (dst, src, len, n))
> {
> error (0, 0, "Wrong result in function %s %p %p", impl->name,
> - CALL (impl, dst, src, n), dst);
> + (void *) CALL (impl, dst, src, n), dst);
> ret = 1;
> return;
> }
>
> - if (memcmp (dst, src, (len > n ? n : len) * sizeof (CHAR)) != 0)
> + if (CMP(dst, src, len, n) != 0)
> {
> error (0, 0, "Wrong result in function %s", impl->name);
> ret = 1;
> return;
> }
>
> - if (n > len)
> + if (NEED_ZFILL && n > len)
> {
> size_t i;
>
> diff --git a/benchtests/bench-wcslcat.c b/benchtests/bench-wcslcat.c
> new file mode 100644
> index 0000000000..02f1331579
> --- /dev/null
> +++ b/benchtests/bench-wcslcat.c
> @@ -0,0 +1,20 @@
> +/* Measure wcslcat functions.
> + Copyright (C) 2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#define WIDE 1
> +#include "bench-strlcat.c"
> diff --git a/benchtests/bench-wcslcpy.c b/benchtests/bench-wcslcpy.c
> new file mode 100644
> index 0000000000..9389b531a5
> --- /dev/null
> +++ b/benchtests/bench-wcslcpy.c
> @@ -0,0 +1,20 @@
> +/* Measure wcslcpy functions.
> + Copyright (C) 2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#define WIDE 1
> +#include "bench-strlcpy.c"
> --
> 2.34.1
>
NB: Based on "Implement strlcpy and strlcat [BZ #178]" by Florian.
prev parent reply other threads:[~2023-04-22 0:24 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-22 0:23 Noah Goldstein
2023-04-22 0:24 ` Noah Goldstein [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAFUsyfKfQ6Wh4N853UCvZpCLV=XqjapTHzrf3tmiuos6R4VaTQ@mail.gmail.com' \
--to=goldstein.w.n@gmail.com \
--cc=carlos@systemhalted.org \
--cc=hjl.tools@gmail.com \
--cc=libc-alpha@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).