[v1] Benchtest: Add benchtests for {wcs, str}lcpy and {wcs, str}lcat

Message ID 20230422002319.2592882-1-goldstein.w.n@gmail.com
State New
Headers
Series [v1] Benchtest: Add benchtests for {wcs, str}lcpy and {wcs, str}lcat |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Noah Goldstein April 22, 2023, 12:23 a.m. UTC
  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
  

Comments

Noah Goldstein April 22, 2023, 12:24 a.m. UTC | #1
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.
  

Patch

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"