From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) by sourceware.org (Postfix) with ESMTPS id E7B63385843E for ; Fri, 27 May 2022 21:46:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E7B63385843E Received: by mail-yb1-xb35.google.com with SMTP id h75so3958791ybg.4 for ; Fri, 27 May 2022 14:46:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=qKNmrD0USOcxCJsZMsXTnx7EqZY4kp7yetKChkBxVNw=; b=pNiBJCMspIlk73ACXseQSF/aOjOqPv6PEd3yTRjiEGVEEc4VmGUFzQh0QzQD3GX4SQ 5kf6qz6+BC+CS8TNDeGLklAxL1qCzLbAig5PE/KRbrmnGS9dPToWxhBVbUcYGnnjocUD thUrgMYRbmD3viYUxCUk+HpNyK3h3H/mMMen8wxqZPNVz9gpY6exwvRNZB+jwlq/DYeA aZGlbNjhXpo5VxH8uJP615wm3DLRaRnUCdPFGDWwjOH/LN9AaFkFuzsyxzBgHmVowrcv KD3FmVSUMMNVe8Pz+s8EdI95bBOEtVAaZw5U07GQ+d7s2NxbAwHz7Z9V/o7QjiPGCWqN GBIA== X-Gm-Message-State: AOAM532d9aieLj+iWR5zMHCXBtNmroPbImF69ukMg+BbA9ZEz6zaEd57 +yZm415Ckk/VzhmxVucDpVjhKPEepkMyeOyxTtU= X-Google-Smtp-Source: ABdhPJzicgD0kz0TrT83p+h2CRYorwUGGsHrUCZrTl6cZMZvET9FLfDblGChbZrSUcL1GqJxL5OCc2oMhVzJzDVfXlc= X-Received: by 2002:a25:8711:0:b0:64f:7484:c07a with SMTP id a17-20020a258711000000b0064f7484c07amr33800982ybl.76.1653687988099; Fri, 27 May 2022 14:46:28 -0700 (PDT) MIME-Version: 1.0 References: <20220527210458.1376451-1-goldstein.w.n@gmail.com> In-Reply-To: From: Noah Goldstein Date: Fri, 27 May 2022 16:46:17 -0500 Message-ID: Subject: Re: [PATCH v1] benchtests: Improve benchtests for strstr, memmem, and memchr To: "H.J. Lu" Cc: GNU C Library , "Carlos O'Donell" Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-8.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 27 May 2022 21:46:32 -0000 On Fri, May 27, 2022 at 4:35 PM H.J. Lu wrote: > > On Fri, May 27, 2022 at 2:05 PM Noah Goldstein wrote: > > > > 1. Use json_ctx for output to help standardize format across all > > benchtests. > > > > 2. Add some additional tests to strstr and memchr expanding alignments > > and adding more small values. > > --- > > benchtests/bench-memchr.c | 108 ++++++++++++++------- > > benchtests/bench-memmem.c | 82 ++++++++++++---- > > benchtests/bench-strstr.c | 191 +++++++++++++++++++++++++++++++------- > > 3 files changed, 289 insertions(+), 92 deletions(-) > > > > diff --git a/benchtests/bench-memchr.c b/benchtests/bench-memchr.c > > index fb0284f523..4d7212332f 100644 > > --- a/benchtests/bench-memchr.c > > +++ b/benchtests/bench-memchr.c > > @@ -53,8 +53,11 @@ SIMPLE_MEMCHR (const CHAR *s, int c, size_t n) > > } > > #endif /* !USE_AS_MEMRCHR */ > > > > +#include "json-lib.h" > > + > > static void > > -do_one_test (impl_t *impl, const CHAR *s, int c, size_t n) > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, > > + size_t n) > > { > > size_t i, iters = INNER_LOOP_ITERS_LARGE; > > timing_t start, stop, cur; > > @@ -68,15 +71,16 @@ do_one_test (impl_t *impl, const CHAR *s, int c, size_t n) > > > > TIMING_DIFF (cur, start, stop); > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > + json_element_double (json_ctx, (double) cur / (double) iters); > > } > > > > static void > > -do_test (size_t align, size_t pos, size_t len, int seek_char) > > +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, > > + int seek_char) > > { > > size_t i; > > > > - align &= 7; > > + align &= getpagesize () - 1; > > if ((align + len) * sizeof (CHAR) >= page_size) > > return; > > > > @@ -100,67 +104,99 @@ do_test (size_t align, size_t pos, size_t len, int seek_char) > > buf[align + len] = seek_char; > > } > > > > - printf ("Length %4zd, position %4zd, alignment %2zd:", > > - len, pos, align); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "align", align); > > + json_attr_uint (json_ctx, "pos", pos); > > + json_attr_uint (json_ctx, "len", len); > > + json_attr_uint (json_ctx, "seek_char", seek_char); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, (CHAR *) (buf + align), seek_char, len); > > + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, len); > > > > - putchar ('\n'); > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > } > > > > int > > test_main (void) > > { > > size_t i; > > - > > + json_ctx_t json_ctx; > > test_init (); > > > > - printf ("%20s", ""); > > + json_init (&json_ctx, 0, stdout); > > + > > + json_document_begin (&json_ctx); > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > + > > + json_attr_object_begin (&json_ctx, "functions"); > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > + json_attr_string (&json_ctx, "bench-variant", ""); > > + > > + json_array_begin (&json_ctx, "ifuncs"); > > FOR_EACH_IMPL (impl, 0) > > - printf ("\t%s", impl->name); > > - putchar ('\n'); > > + json_element_string (&json_ctx, impl->name); > > + json_array_end (&json_ctx); > > + > > + json_array_begin (&json_ctx, "results"); > > > > for (i = 1; i < 8; ++i) > > { > > - do_test (0, 16 << i, 2048, 23); > > - do_test (i, 64, 256, 23); > > - do_test (0, 16 << i, 2048, 0); > > - do_test (i, 64, 256, 0); > > + do_test (&json_ctx, 0, 16 << i, 2048, 23); > > + do_test (&json_ctx, i, 64, 256, 23); > > + do_test (&json_ctx, 0, 16 << i, 2048, 0); > > + do_test (&json_ctx, i, 64, 256, 0); > > + > > + do_test (&json_ctx, getpagesize () - 15, 64, 256, 0); > > #ifdef USE_AS_MEMRCHR > > /* Also test the position close to the beginning for memrchr. */ > > - do_test (0, i, 256, 23); > > - do_test (0, i, 256, 0); > > - do_test (i, i, 256, 23); > > - do_test (i, i, 256, 0); > > + do_test (&json_ctx, 0, i, 256, 23); > > + do_test (&json_ctx, 0, i, 256, 0); > > + do_test (&json_ctx, i, i, 256, 23); > > + do_test (&json_ctx, i, i, 256, 0); > > #endif > > } > > for (i = 1; i < 8; ++i) > > { > > - do_test (i, i << 5, 192, 23); > > - do_test (i, i << 5, 192, 0); > > - do_test (i, i << 5, 256, 23); > > - do_test (i, i << 5, 256, 0); > > - do_test (i, i << 5, 512, 23); > > - do_test (i, i << 5, 512, 0); > > + do_test (&json_ctx, i, i << 5, 192, 23); > > + do_test (&json_ctx, i, i << 5, 192, 0); > > + do_test (&json_ctx, i, i << 5, 256, 23); > > + do_test (&json_ctx, i, i << 5, 256, 0); > > + do_test (&json_ctx, i, i << 5, 512, 23); > > + do_test (&json_ctx, i, i << 5, 512, 0); > > + > > + do_test (&json_ctx, getpagesize () - 15, i << 5, 256, 23); > > } > > for (i = 1; i < 32; ++i) > > { > > - do_test (0, i, i + 1, 23); > > - do_test (0, i, i + 1, 0); > > - do_test (i, i, i + 1, 23); > > - do_test (i, i, i + 1, 0); > > - do_test (0, i, i - 1, 23); > > - do_test (0, i, i - 1, 0); > > - do_test (i, i, i - 1, 23); > > - do_test (i, i, i - 1, 0); > > + do_test (&json_ctx, 0, i, i + 1, 23); > > + do_test (&json_ctx, 0, i, i + 1, 0); > > + do_test (&json_ctx, i, i, i + 1, 23); > > + do_test (&json_ctx, i, i, i + 1, 0); > > + do_test (&json_ctx, 0, i, i - 1, 23); > > + do_test (&json_ctx, 0, i, i - 1, 0); > > + do_test (&json_ctx, i, i, i - 1, 23); > > + do_test (&json_ctx, i, i, i - 1, 0); > > + > > + do_test (&json_ctx, getpagesize () - 15, i, i - 1, 23); > > + do_test (&json_ctx, getpagesize () - 15, i, i - 1, 0); > > + > > + do_test (&json_ctx, getpagesize () - 15, i, i + 1, 23); > > + do_test (&json_ctx, getpagesize () - 15, i, i + 1, 0); > > #ifdef USE_AS_MEMRCHR > > /* Also test the position close to the beginning for memrchr. */ > > - do_test (0, 1, i + 1, 23); > > - do_test (0, 2, i + 1, 0); > > + do_test (&json_ctx, 0, 1, i + 1, 23); > > + do_test (&json_ctx, 0, 2, i + 1, 0); > > #endif > > } > > > > + json_array_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_document_end (&json_ctx); > > + > > return ret; > > } > > > > diff --git a/benchtests/bench-memmem.c b/benchtests/bench-memmem.c > > index 0fb87309c0..c2b92405dc 100644 > > --- a/benchtests/bench-memmem.c > > +++ b/benchtests/bench-memmem.c > > @@ -21,6 +21,7 @@ > > #define BUF1PAGES 20 > > #define ITERATIONS 100 > > #include "bench-string.h" > > +#include "json-lib.h" > > > > typedef char *(*proto_t) (const void *, size_t, const void *, size_t); > > > > @@ -102,44 +103,62 @@ IMPL (twoway_memmem, 0) > > IMPL (basic_memmem, 0) > > > > static void > > -do_one_test (impl_t *impl, const void *haystack, size_t haystack_len, > > - const void *needle, size_t needle_len, const void *expected) > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const void *haystack, > > + size_t haystack_len, const void *needle, size_t needle_len, > > + const void *expected) > > { > > size_t i, iters = INNER_LOOP_ITERS_SMALL; > > timing_t start, stop, cur; > > - > > + void *res; > > TIMING_NOW (start); > > for (i = 0; i < iters; ++i) > > { > > - CALL (impl, haystack, haystack_len, needle, needle_len); > > + res = CALL (impl, haystack, haystack_len, needle, needle_len); > > } > > TIMING_NOW (stop); > > > > TIMING_DIFF (cur, start, stop); > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > + json_element_double (json_ctx, (double) cur / (double) iters); > > + > > + if (res != expected) > > + { > > + error (0, 0, "Wrong result in function (%p != %p) %s(%p, %zu, %p, %zu)", > > + res, expected, impl->name, haystack, haystack_len, needle, > > + needle_len); > > + ret = 1; > > + } > > } > > > > static void > > -do_test (const char *str, size_t len, size_t idx) > > +do_test (json_ctx_t *json_ctx, const char *str, size_t len, size_t idx) > > { > > char tmpbuf[len]; > > > > memcpy (tmpbuf, buf1 + idx, len); > > memcpy (buf1 + idx, str, len); > > > > - printf ("String %s, offset %zd:", str, idx); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", BUF1PAGES * page_size); > > + json_attr_uint (json_ctx, "len_needle", len); > > + json_attr_uint (json_ctx, "haystack_ptr", (uintptr_t) buf1); > > + json_attr_uint (json_ctx, "needle_ptr", (uintptr_t) str); > > + json_attr_uint (json_ctx, "fail", 0); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, buf1, BUF1PAGES * page_size, str, len, buf1 + idx); > > + do_one_test (json_ctx, impl, buf1, BUF1PAGES * page_size, str, len, > > + buf1 + idx); > > > > memcpy (buf1 + idx, tmpbuf, len); > > > > - putchar ('\n'); > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > } > > > > static void > > -do_random_tests (void) > > +do_random_tests (json_ctx_t *json_ctx) > > { > > for (size_t n = 0; n < ITERATIONS; ++n) > > { > > @@ -159,13 +178,21 @@ do_random_tests (void) > > buf1[idx + off] = ch; > > } > > > > - printf ("String %.*s, offset %zd:", (int) len, buf1 + idx, idx); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", BUF1PAGES * page_size); > > + json_attr_uint (json_ctx, "len_needle", len); > > + json_attr_uint (json_ctx, "haystack_ptr", (uintptr_t) buf1); > > + json_attr_uint (json_ctx, "needle_ptr", (uintptr_t) (buf1 + idx)); > > + json_attr_uint (json_ctx, "fail", 0); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, buf1, BUF1PAGES * page_size, buf1 + idx, len, > > - buf1 + idx); > > + do_one_test (json_ctx, impl, buf1, BUF1PAGES * page_size, buf1 + idx, > > + len, buf1 + idx); > > > > - putchar ('\n'); > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > > > memcpy (buf1 + idx, tmpbuf, len); > > } > > @@ -178,18 +205,28 @@ static const char *const strs[] = > > "abc0", "aaaa0", "abcabc0" > > }; > > > > - > > int > > test_main (void) > > { > > + json_ctx_t json_ctx; > > size_t i; > > > > test_init (); > > + json_init (&json_ctx, 0, stdout); > > + > > + json_document_begin (&json_ctx); > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > + > > + json_attr_object_begin (&json_ctx, "functions"); > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > + json_attr_string (&json_ctx, "bench-variant", ""); > > > > - printf ("%23s", ""); > > + json_array_begin (&json_ctx, "ifuncs"); > > FOR_EACH_IMPL (impl, 0) > > - printf ("\t%s", impl->name); > > - putchar ('\n'); > > + json_element_string (&json_ctx, impl->name); > > + json_array_end (&json_ctx); > > + > > + json_array_begin (&json_ctx, "results"); > > > > for (i = 0; i < BUF1PAGES * page_size; ++i) > > buf1[i] = 60 + random () % 32; > > @@ -199,10 +236,15 @@ test_main (void) > > { > > size_t len = strlen (strs[i]); > > > > - do_test (strs[i], len, j); > > + do_test (&json_ctx, strs[i], len, j); > > } > > > > - do_random_tests (); > > + do_random_tests (&json_ctx); > > + > > + json_array_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_document_end (&json_ctx); > > return ret; > > } > > > > diff --git a/benchtests/bench-strstr.c b/benchtests/bench-strstr.c > > index 467418b12c..3838a2b6ac 100644 > > --- a/benchtests/bench-strstr.c > > +++ b/benchtests/bench-strstr.c > > @@ -21,6 +21,8 @@ > > #define TEST_NAME "strstr" > > #include "bench-string.h" > > > > +#include "json-lib.h" > > + > > static const char input[] = > > "This manual is written with the assumption that you are at least " > > "somewhat familiar with the C programming language and basic programming " > > @@ -129,7 +131,8 @@ IMPL (twoway_strstr, 0) > > IMPL (basic_strstr, 0) > > > > static void > > -do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const char *s1, > > + const char *s2, char *exp_result) > > { > > size_t i, iters = INNER_LOOP_ITERS_SMALL / 8; > > timing_t start, stop, cur; > > @@ -142,7 +145,7 @@ do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) > > > > TIMING_DIFF (cur, start, stop); > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > + json_element_double (json_ctx, (double) cur / (double) iters); > > > > if (res != exp_result) > > { > > @@ -153,14 +156,16 @@ do_one_test (impl_t *impl, const char *s1, const char *s2, char *exp_result) > > } > > } > > > > - > > static void > > -do_test (size_t align1, size_t align2, size_t len1, size_t len2, > > - int fail) > > +do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len1, > > + size_t len2, int fail) > > { > > char *s1 = (char *) (buf1 + align1); > > char *s2 = (char *) (buf2 + align2); > > > > + if (align1 + len1 >= MIN_PAGE_SIZE || align1 + len1 >= MIN_PAGE_SIZE) > > Is this really needed? Did you mean align2 + len2? Will fix align2/len2 in V2. Not needed AFAICT for any of these but generally think it makes it easier to add new tests w.o worrying about them failing. Can remove if you in V2 if you want. > > > + return; > > + > > size_t size = sizeof (input) - 1; > > size_t pos = (len1 + len2) % size; > > > > @@ -195,13 +200,21 @@ do_test (size_t align1, size_t align2, size_t len1, size_t len2, > > if (fail || ss1 != s1 + len1 - len2) > > ++ss1[len2 / 2]; > > > > - printf ("Length %4zd/%3zd, alignment %2zd/%2zd, %s:", > > - len1, len2, align1, align2, fail ? "fail " : "found"); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", len1); > > + json_attr_uint (json_ctx, "len_needle", len2); > > + json_attr_uint (json_ctx, "align_haystack", align1); > > + json_attr_uint (json_ctx, "align_needle", align2); > > + json_attr_uint (json_ctx, "fail", fail); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, s1, s2, fail ? NULL : s1 + len1 - len2); > > + do_one_test (json_ctx, impl, s1, s2, fail ? NULL : s1 + len1 - len2); > > + > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > > > - putchar ('\n'); > > } > > > > /* Test needles which exhibit worst-case performance. This shows that > > @@ -211,11 +224,14 @@ do_test (size_t align1, size_t align2, size_t len1, size_t len2, > > within a factor of 2 on several different microarchitectures. */ > > > > static void > > -test_hard_needle (size_t ne_len, size_t hs_len) > > +test_hard_needle (json_ctx_t *json_ctx, size_t ne_len, size_t hs_len) > > { > > char *ne = (char *) buf1; > > char *hs = (char *) buf2; > > > > + if (ne_len >= MIN_PAGE_SIZE || hs_len >= MIN_PAGE_SIZE) > > + return; > > + > > /* Hard needle for strstr algorithm using skip table. This results in many > > memcmp calls comparing most of the needle. */ > > { > > @@ -226,15 +242,25 @@ test_hard_needle (size_t ne_len, size_t hs_len) > > memset (hs, 'a', hs_len); > > for (size_t i = ne_len; i <= hs_len; i += ne_len) > > { > > - hs[i-5] = 'b'; > > - hs[i-62] = 'b'; > > + hs[i - 5] = 'b'; > > + hs[i - 62] = 'b'; > > } > > > > - printf ("Length %4zd/%3zd, complex needle 1:", hs_len, ne_len); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", hs_len); > > + json_attr_uint (json_ctx, "len_needle", ne_len); > > + json_attr_uint (json_ctx, "align_haystack", 0); > > + json_attr_uint (json_ctx, "align_needle", 0); > > + json_attr_uint (json_ctx, "fail", 1); > > + json_attr_string (json_ctx, "desc", "Difficult skiptable(0)"); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, hs, ne, NULL); > > - putchar ('\n'); > > + do_one_test (json_ctx, impl, hs, ne, NULL); > > + > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > } > > > > /* 2nd hard needle for strstr algorithm using skip table. This results in > > @@ -247,15 +273,25 @@ test_hard_needle (size_t ne_len, size_t hs_len) > > memset (hs, 'a', hs_len); > > for (size_t i = ne_len; i <= hs_len; i += ne_len) > > { > > - hs[i-5] = 'b'; > > - hs[i-6] = 'b'; > > + hs[i - 5] = 'b'; > > + hs[i - 6] = 'b'; > > } > > > > - printf ("Length %4zd/%3zd, complex needle 2:", hs_len, ne_len); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", hs_len); > > + json_attr_uint (json_ctx, "len_needle", ne_len); > > + json_attr_uint (json_ctx, "align_haystack", 0); > > + json_attr_uint (json_ctx, "align_needle", 0); > > + json_attr_uint (json_ctx, "fail", 1); > > + json_attr_string (json_ctx, "desc", "Difficult skiptable(1)"); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, hs, ne, NULL); > > - putchar ('\n'); > > + do_one_test (json_ctx, impl, hs, ne, NULL); > > + > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > } > > > > /* Hard needle for Two-way algorithm - the random input causes a large number > > @@ -267,45 +303,128 @@ test_hard_needle (size_t ne_len, size_t hs_len) > > hs[hs_len] = 0; > > > > memset (ne, 'a', ne_len); > > - ne[ne_len-2] = 'b'; > > + ne[ne_len - 2] = 'b'; > > ne[0] = 'b'; > > ne[ne_len] = 0; > > > > - printf ("Length %4zd/%3zd, complex needle 3:", hs_len, ne_len); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", hs_len); > > + json_attr_uint (json_ctx, "len_needle", ne_len); > > + json_attr_uint (json_ctx, "align_haystack", 0); > > + json_attr_uint (json_ctx, "align_needle", 0); > > + json_attr_uint (json_ctx, "fail", 1); > > + json_attr_string (json_ctx, "desc", "Difficult 2-way"); > > + > > + json_array_begin (json_ctx, "timings"); > > + > > + FOR_EACH_IMPL (impl, 0) > > + do_one_test (json_ctx, impl, hs, ne, NULL); > > + > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > + } > > + > > + /* Hard needle for standard algorithm testing first few characters of > > + * needle. */ > > + { > > + for (int i = 0; i < hs_len; i++) > > + hs[i] = (rand () & 255) >= 128 ? 'a' : 'b'; > > + hs[hs_len] = 0; > > + > > + for (int i = 0; i < ne_len; i++) > > + { > > + if (i % 3 == 0) > > + ne[i] = 'a'; > > + else if (i % 3 == 1) > > + ne[i] = 'b'; > > + else > > + ne[i] = 'c'; > > + } > > + ne[ne_len] = 0; > > + > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len_haystack", hs_len); > > + json_attr_uint (json_ctx, "len_needle", ne_len); > > + json_attr_uint (json_ctx, "align_haystack", 0); > > + json_attr_uint (json_ctx, "align_needle", 0); > > + json_attr_uint (json_ctx, "fail", 1); > > + json_attr_string (json_ctx, "desc", "Difficult testing first 2"); > > + > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, hs, ne, NULL); > > - putchar ('\n'); > > + do_one_test (json_ctx, impl, hs, ne, NULL); > > + > > + json_array_end (json_ctx); > > + json_element_object_end (json_ctx); > > } > > } > > > > static int > > test_main (void) > > { > > + json_ctx_t json_ctx; > > test_init (); > > > > - printf ("%23s", ""); > > + json_init (&json_ctx, 0, stdout); > > + > > + json_document_begin (&json_ctx); > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > + > > + json_attr_object_begin (&json_ctx, "functions"); > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > + json_attr_string (&json_ctx, "bench-variant", ""); > > + > > + json_array_begin (&json_ctx, "ifuncs"); > > FOR_EACH_IMPL (impl, 0) > > - printf ("\t%s", impl->name); > > - putchar ('\n'); > > + json_element_string (&json_ctx, impl->name); > > + json_array_end (&json_ctx); > > + > > + json_array_begin (&json_ctx, "results"); > > > > - for (size_t hlen = 64; hlen <= 256; hlen += 32) > > + for (size_t hlen = 8; hlen <= 256;) > > for (size_t klen = 1; klen <= 16; klen++) > > { > > - do_test (1, 3, hlen, klen, 0); > > - do_test (0, 9, hlen, klen, 1); > > + do_test (&json_ctx, 1, 3, hlen, klen, 0); > > + do_test (&json_ctx, 0, 9, hlen, klen, 1); > > + > > + do_test (&json_ctx, 1, 3, hlen + 1, klen, 0); > > + do_test (&json_ctx, 0, 9, hlen + 1, klen, 1); > > + > > + do_test (&json_ctx, getpagesize () - 15, 9, hlen, klen, 1); > > + if (hlen < 64) > > + { > > + hlen += 8; > > + } > > + else > > + { > > + hlen += 32; > > + } > > } > > > > for (size_t hlen = 256; hlen <= 65536; hlen *= 2) > > - for (size_t klen = 16; klen <= 256; klen *= 2) > > + for (size_t klen = 4; klen <= 256; klen *= 2) > > { > > - do_test (1, 11, hlen, klen, 0); > > - do_test (14, 5, hlen, klen, 1); > > + do_test (&json_ctx, 1, 11, hlen, klen, 0); > > + do_test (&json_ctx, 14, 5, hlen, klen, 1); > > + > > + do_test (&json_ctx, 1, 11, hlen + 1, klen + 1, 0); > > + do_test (&json_ctx, 14, 5, hlen + 1, klen + 1, 1); > > + > > + do_test (&json_ctx, 1, 11, hlen + 1, klen, 0); > > + do_test (&json_ctx, 14, 5, hlen + 1, klen, 1); > > + > > + do_test (&json_ctx, getpagesize () - 15, 5, hlen + 1, klen, 1); > > } > > > > - test_hard_needle (64, 65536); > > - test_hard_needle (256, 65536); > > - test_hard_needle (1024, 65536); > > + test_hard_needle (&json_ctx, 64, 65536); > > + test_hard_needle (&json_ctx, 256, 65536); > > + test_hard_needle (&json_ctx, 1024, 65536); > > + > > + json_array_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_attr_object_end (&json_ctx); > > + json_document_end (&json_ctx); > > > > return ret; > > } > > -- > > 2.34.1 > > > > > -- > H.J.