Message ID | 20220421031410.2142238-1-goldstein.w.n@gmail.com |
---|---|
State | New |
Headers | show |
Series | [v1,1/5] benchtests: Improve bench-strrchr | expand |
On Wed, Apr 20, 2022 at 8:14 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > 1. Use json-lib for printing results. > 2. Expose all parameters (before pos, seek_char, and max_char where > not printed). > 3. Add benchmarks that test multiple occurence of seek_char in the > string. > --- > benchtests/bench-strrchr.c | 126 ++++++++++++++++++++++++------------- > 1 file changed, 82 insertions(+), 44 deletions(-) > > diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c > index abdae60c51..cceea77e1b 100644 > --- a/benchtests/bench-strrchr.c > +++ b/benchtests/bench-strrchr.c > @@ -23,6 +23,7 @@ > # define TEST_NAME "strrchr" > #endif > #include "bench-string.h" > +#include "json-lib.h" > > #define BIG_CHAR MAX_CHAR > > @@ -53,7 +54,8 @@ SIMPLE_STRRCHR (const CHAR *s, int c) > } > > static void > -do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, > + CHAR *exp_res) > { > CHAR *res = CALL (impl, s, c); > size_t i, iters = INNER_LOOP_ITERS8; > @@ -61,8 +63,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > if (res != exp_res) > { > - error (0, 0, "Wrong result in function %s %p %p", impl->name, > - res, exp_res); > + error (0, 0, "Wrong result in function %s %p %p", impl->name, res, > + exp_res); These changes aren't needed. > ret = 1; > return; > } > @@ -72,24 +74,28 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > { > CALL (impl, s, c); > } > - TIMING_NOW (stop); > > + TIMING_NOW (stop); Not needed. > TIMING_DIFF (cur, start, stop); > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > + json_element_double (json_ctx, (double) cur / (double) iters); > + return; Return isn't needed. > } > > static void > -do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, > + int seek_char, int max_char, size_t freq) > /* For wcsrchr: align here means align not in bytes, > but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) > len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ > { > size_t i; > + size_t pos_chunk_sz = freq ? (pos / freq) : pos; > + size_t last_pos = len; > CHAR *result; > CHAR *buf = (CHAR *) buf1; > > - align &= 7; > + align &= (getpagesize () - 1); If we have such large alignments, the tests may be skipped. Should we change it to 127 instead? > if ((align + len) * sizeof (CHAR) >= page_size) > return; > > @@ -103,6 +109,16 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > if ((i > pos || pos >= len) && buf[align + i] == seek_char) > buf[align + i] = seek_char + 10 + (random () & 15); > } > + > + if (pos_chunk_sz == 0 && pos) > + pos_chunk_sz = 1; > + > + for (i = pos_chunk_sz; i < pos && i < len; i += pos_chunk_sz) > + { > + buf[align + i] = seek_char; > + last_pos = i; > + } > + > buf[align + len] = 0; > > if (pos < len) > @@ -110,66 +126,88 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > buf[align + pos] = seek_char; > result = (CHAR *) (buf + align + pos); > } > + else if (last_pos < len) > + result = (CHAR *) (buf + align + last_pos); > else if (seek_char == 0) > result = (CHAR *) (buf + align + len); > else > result = NULL; > > - printf ("Length %4zd, alignment in bytes %2zd:", len, align * sizeof (CHAR)); > + json_element_object_begin (json_ctx); > + json_attr_uint (json_ctx, "len", len); > + json_attr_uint (json_ctx, "pos", pos); > + json_attr_uint (json_ctx, "align", align); > + json_attr_uint (json_ctx, "freq", freq); > + json_attr_uint (json_ctx, "seek", seek_char); > + json_attr_uint (json_ctx, "max_char", max_char); > + json_array_begin (json_ctx, "timings"); > > FOR_EACH_IMPL (impl, 0) > - do_one_test (impl, (CHAR *) (buf + align), seek_char, result); > + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, result); > > - 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; > + size_t i, j; > + int seek; > > test_init (); > + json_init (&json_ctx, 0, stdout); > > - printf ("%20s", ""); > - FOR_EACH_IMPL (impl, 0) > - printf ("\t%s", impl->name); > - putchar ('\n'); > + json_document_begin (&json_ctx); > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > - for (i = 1; i < 8; ++i) > - { > - do_test (0, 16 << i, 2048, 23, SMALL_CHAR); > - do_test (i, 16 << i, 2048, 23, SMALL_CHAR); > - } > + json_attr_object_begin (&json_ctx, "functions"); > + json_attr_object_begin (&json_ctx, TEST_NAME); > + json_attr_string (&json_ctx, "bench-variant", ""); > > - for (i = 1; i < 8; ++i) > - { > - do_test (i, 64, 256, 23, SMALL_CHAR); > - do_test (i, 64, 256, 23, BIG_CHAR); > - } > - > - for (i = 0; i < 32; ++i) > - { > - do_test (0, i, i + 1, 23, SMALL_CHAR); > - do_test (0, i, i + 1, 23, BIG_CHAR); > - } > + json_array_begin (&json_ctx, "ifuncs"); > + FOR_EACH_IMPL (impl, 0) > + json_element_string (&json_ctx, impl->name); > + json_array_end (&json_ctx); > > - for (i = 1; i < 8; ++i) > - { > - do_test (0, 16 << i, 2048, 0, SMALL_CHAR); > - do_test (i, 16 << i, 2048, 0, SMALL_CHAR); > - } > + json_array_begin (&json_ctx, "results"); > > - for (i = 1; i < 8; ++i) > + for (seek = 0; seek <= 23; seek += 23) > { > - do_test (i, 64, 256, 0, SMALL_CHAR); > - do_test (i, 64, 256, 0, BIG_CHAR); > + for (j = 1; j < 32; j += j) > + { > + for (i = 1; i < 9; ++i) > + { > + do_test (&json_ctx, 0, 16 << i, 2048, seek, SMALL_CHAR, j); > + do_test (&json_ctx, i, 16 << i, 2048, seek, SMALL_CHAR, j); > + } > + > + for (i = 1; i < 8; ++i) > + { > + do_test (&json_ctx, i, 64, 256, seek, SMALL_CHAR, j); > + do_test (&json_ctx, i, 64, 256, seek, BIG_CHAR, j); > + > + do_test (&json_ctx, i * 15, 64, 256, seek, SMALL_CHAR, j); > + do_test (&json_ctx, i * 15, 64, 256, seek, BIG_CHAR, j); > + } > + > + for (i = 0; i < 32; ++i) > + { > + do_test (&json_ctx, 0, i, i + 1, seek, SMALL_CHAR, j); > + do_test (&json_ctx, 0, i, i + 1, seek, BIG_CHAR, j); > + } > + if (seek == 0) > + { > + break; > + } > + } > } > > - for (i = 0; i < 32; ++i) > - { > - do_test (0, i, i + 1, 0, SMALL_CHAR); > - do_test (0, i, i + 1, 0, BIG_CHAR); > - } > + 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.25.1 >
On Thu, Apr 21, 2022 at 3:13 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Wed, Apr 20, 2022 at 8:14 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > > > 1. Use json-lib for printing results. > > 2. Expose all parameters (before pos, seek_char, and max_char where > > not printed). > > 3. Add benchmarks that test multiple occurence of seek_char in the > > string. > > --- > > benchtests/bench-strrchr.c | 126 ++++++++++++++++++++++++------------- > > 1 file changed, 82 insertions(+), 44 deletions(-) > > > > diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c > > index abdae60c51..cceea77e1b 100644 > > --- a/benchtests/bench-strrchr.c > > +++ b/benchtests/bench-strrchr.c > > @@ -23,6 +23,7 @@ > > # define TEST_NAME "strrchr" > > #endif > > #include "bench-string.h" > > +#include "json-lib.h" > > > > #define BIG_CHAR MAX_CHAR > > > > @@ -53,7 +54,8 @@ SIMPLE_STRRCHR (const CHAR *s, int c) > > } > > > > static void > > -do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, > > + CHAR *exp_res) > > { > > CHAR *res = CALL (impl, s, c); > > size_t i, iters = INNER_LOOP_ITERS8; > > @@ -61,8 +63,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > > if (res != exp_res) > > { > > - error (0, 0, "Wrong result in function %s %p %p", impl->name, > > - res, exp_res); > > + error (0, 0, "Wrong result in function %s %p %p", impl->name, res, > > + exp_res); > > These changes aren't needed. > > > ret = 1; > > return; > > } > > @@ -72,24 +74,28 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > { > > CALL (impl, s, c); > > } > > - TIMING_NOW (stop); > > > > + TIMING_NOW (stop); > > Not needed. Will fix in V2 > > > TIMING_DIFF (cur, start, stop); > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > + json_element_double (json_ctx, (double) cur / (double) iters); > > + return; > > Return isn't needed. Will fix in V2. > > > } > > > > static void > > -do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, > > + int seek_char, int max_char, size_t freq) > > /* For wcsrchr: align here means align not in bytes, > > but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) > > len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ > > { > > size_t i; > > + size_t pos_chunk_sz = freq ? (pos / freq) : pos; > > + size_t last_pos = len; > > CHAR *result; > > CHAR *buf = (CHAR *) buf1; > > > > - align &= 7; > > + align &= (getpagesize () - 1); > > If we have such large alignments, the tests may be skipped. > Should we change it to 127 instead? There is logic around page cross cases in x86_64 versions so think makes sense to support benchmarking it. Also i think that would tend to give the previous version a bit of an unfair disadvantage as the slow aligning case will never be tested in the new version. > > > if ((align + len) * sizeof (CHAR) >= page_size) > > return; > > > > @@ -103,6 +109,16 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > if ((i > pos || pos >= len) && buf[align + i] == seek_char) > > buf[align + i] = seek_char + 10 + (random () & 15); > > } > > + > > + if (pos_chunk_sz == 0 && pos) > > + pos_chunk_sz = 1; > > + > > + for (i = pos_chunk_sz; i < pos && i < len; i += pos_chunk_sz) > > + { > > + buf[align + i] = seek_char; > > + last_pos = i; > > + } > > + > > buf[align + len] = 0; > > > > if (pos < len) > > @@ -110,66 +126,88 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > buf[align + pos] = seek_char; > > result = (CHAR *) (buf + align + pos); > > } > > + else if (last_pos < len) > > + result = (CHAR *) (buf + align + last_pos); > > else if (seek_char == 0) > > result = (CHAR *) (buf + align + len); > > else > > result = NULL; > > > > - printf ("Length %4zd, alignment in bytes %2zd:", len, align * sizeof (CHAR)); > > + json_element_object_begin (json_ctx); > > + json_attr_uint (json_ctx, "len", len); > > + json_attr_uint (json_ctx, "pos", pos); > > + json_attr_uint (json_ctx, "align", align); > > + json_attr_uint (json_ctx, "freq", freq); > > + json_attr_uint (json_ctx, "seek", seek_char); > > + json_attr_uint (json_ctx, "max_char", max_char); > > + json_array_begin (json_ctx, "timings"); > > > > FOR_EACH_IMPL (impl, 0) > > - do_one_test (impl, (CHAR *) (buf + align), seek_char, result); > > + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, result); > > > > - 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; > > + size_t i, j; > > + int seek; > > > > test_init (); > > + json_init (&json_ctx, 0, stdout); > > > > - printf ("%20s", ""); > > - FOR_EACH_IMPL (impl, 0) > > - printf ("\t%s", impl->name); > > - putchar ('\n'); > > + json_document_begin (&json_ctx); > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > > > - for (i = 1; i < 8; ++i) > > - { > > - do_test (0, 16 << i, 2048, 23, SMALL_CHAR); > > - do_test (i, 16 << i, 2048, 23, SMALL_CHAR); > > - } > > + json_attr_object_begin (&json_ctx, "functions"); > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > + json_attr_string (&json_ctx, "bench-variant", ""); > > > > - for (i = 1; i < 8; ++i) > > - { > > - do_test (i, 64, 256, 23, SMALL_CHAR); > > - do_test (i, 64, 256, 23, BIG_CHAR); > > - } > > - > > - for (i = 0; i < 32; ++i) > > - { > > - do_test (0, i, i + 1, 23, SMALL_CHAR); > > - do_test (0, i, i + 1, 23, BIG_CHAR); > > - } > > + json_array_begin (&json_ctx, "ifuncs"); > > + FOR_EACH_IMPL (impl, 0) > > + json_element_string (&json_ctx, impl->name); > > + json_array_end (&json_ctx); > > > > - for (i = 1; i < 8; ++i) > > - { > > - do_test (0, 16 << i, 2048, 0, SMALL_CHAR); > > - do_test (i, 16 << i, 2048, 0, SMALL_CHAR); > > - } > > + json_array_begin (&json_ctx, "results"); > > > > - for (i = 1; i < 8; ++i) > > + for (seek = 0; seek <= 23; seek += 23) > > { > > - do_test (i, 64, 256, 0, SMALL_CHAR); > > - do_test (i, 64, 256, 0, BIG_CHAR); > > + for (j = 1; j < 32; j += j) > > + { > > + for (i = 1; i < 9; ++i) > > + { > > + do_test (&json_ctx, 0, 16 << i, 2048, seek, SMALL_CHAR, j); > > + do_test (&json_ctx, i, 16 << i, 2048, seek, SMALL_CHAR, j); > > + } > > + > > + for (i = 1; i < 8; ++i) > > + { > > + do_test (&json_ctx, i, 64, 256, seek, SMALL_CHAR, j); > > + do_test (&json_ctx, i, 64, 256, seek, BIG_CHAR, j); > > + > > + do_test (&json_ctx, i * 15, 64, 256, seek, SMALL_CHAR, j); > > + do_test (&json_ctx, i * 15, 64, 256, seek, BIG_CHAR, j); > > + } > > + > > + for (i = 0; i < 32; ++i) > > + { > > + do_test (&json_ctx, 0, i, i + 1, seek, SMALL_CHAR, j); > > + do_test (&json_ctx, 0, i, i + 1, seek, BIG_CHAR, j); > > + } > > + if (seek == 0) > > + { > > + break; > > + } > > + } > > } > > > > - for (i = 0; i < 32; ++i) > > - { > > - do_test (0, i, i + 1, 0, SMALL_CHAR); > > - do_test (0, i, i + 1, 0, BIG_CHAR); > > - } > > + 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.25.1 > > > > > -- > H.J.
On Thu, Apr 21, 2022 at 3:08 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > On Thu, Apr 21, 2022 at 3:13 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > On Wed, Apr 20, 2022 at 8:14 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > > > > > 1. Use json-lib for printing results. > > > 2. Expose all parameters (before pos, seek_char, and max_char where > > > not printed). > > > 3. Add benchmarks that test multiple occurence of seek_char in the > > > string. > > > --- > > > benchtests/bench-strrchr.c | 126 ++++++++++++++++++++++++------------- > > > 1 file changed, 82 insertions(+), 44 deletions(-) > > > > > > diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c > > > index abdae60c51..cceea77e1b 100644 > > > --- a/benchtests/bench-strrchr.c > > > +++ b/benchtests/bench-strrchr.c > > > @@ -23,6 +23,7 @@ > > > # define TEST_NAME "strrchr" > > > #endif > > > #include "bench-string.h" > > > +#include "json-lib.h" > > > > > > #define BIG_CHAR MAX_CHAR > > > > > > @@ -53,7 +54,8 @@ SIMPLE_STRRCHR (const CHAR *s, int c) > > > } > > > > > > static void > > > -do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, > > > + CHAR *exp_res) > > > { > > > CHAR *res = CALL (impl, s, c); > > > size_t i, iters = INNER_LOOP_ITERS8; > > > @@ -61,8 +63,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > > > > if (res != exp_res) > > > { > > > - error (0, 0, "Wrong result in function %s %p %p", impl->name, > > > - res, exp_res); > > > + error (0, 0, "Wrong result in function %s %p %p", impl->name, res, > > > + exp_res); > > > > These changes aren't needed. > > > > > ret = 1; > > > return; > > > } > > > @@ -72,24 +74,28 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > { > > > CALL (impl, s, c); > > > } > > > - TIMING_NOW (stop); > > > > > > + TIMING_NOW (stop); > > > > Not needed. > > Will fix in V2 > > > > > TIMING_DIFF (cur, start, stop); > > > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > > + json_element_double (json_ctx, (double) cur / (double) iters); > > > + return; > > > > Return isn't needed. > > Will fix in V2. > > > > > } > > > > > > static void > > > -do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, > > > + int seek_char, int max_char, size_t freq) > > > /* For wcsrchr: align here means align not in bytes, > > > but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) > > > len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ > > > { > > > size_t i; > > > + size_t pos_chunk_sz = freq ? (pos / freq) : pos; > > > + size_t last_pos = len; > > > CHAR *result; > > > CHAR *buf = (CHAR *) buf1; > > > > > > - align &= 7; > > > + align &= (getpagesize () - 1); > > > > If we have such large alignments, the tests may be skipped. > > Should we change it to 127 instead? > > There is logic around page cross cases in x86_64 versions so think > makes sense to support benchmarking it. > > Also i think that would tend to give the previous version a bit of > an unfair disadvantage as the slow aligning case will never be > tested in the new version. If "align" is close to the page size, will it trigger if ((align + len) * sizeof (CHAR) >= page_size) return; and skip page cross cases? > > > > > if ((align + len) * sizeof (CHAR) >= page_size) > > > return; > > > > > > @@ -103,6 +109,16 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > if ((i > pos || pos >= len) && buf[align + i] == seek_char) > > > buf[align + i] = seek_char + 10 + (random () & 15); > > > } > > > + > > > + if (pos_chunk_sz == 0 && pos) > > > + pos_chunk_sz = 1; > > > + > > > + for (i = pos_chunk_sz; i < pos && i < len; i += pos_chunk_sz) > > > + { > > > + buf[align + i] = seek_char; > > > + last_pos = i; > > > + } > > > + > > > buf[align + len] = 0; > > > > > > if (pos < len) > > > @@ -110,66 +126,88 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > buf[align + pos] = seek_char; > > > result = (CHAR *) (buf + align + pos); > > > } > > > + else if (last_pos < len) > > > + result = (CHAR *) (buf + align + last_pos); > > > else if (seek_char == 0) > > > result = (CHAR *) (buf + align + len); > > > else > > > result = NULL; > > > > > > - printf ("Length %4zd, alignment in bytes %2zd:", len, align * sizeof (CHAR)); > > > + json_element_object_begin (json_ctx); > > > + json_attr_uint (json_ctx, "len", len); > > > + json_attr_uint (json_ctx, "pos", pos); > > > + json_attr_uint (json_ctx, "align", align); > > > + json_attr_uint (json_ctx, "freq", freq); > > > + json_attr_uint (json_ctx, "seek", seek_char); > > > + json_attr_uint (json_ctx, "max_char", max_char); > > > + json_array_begin (json_ctx, "timings"); > > > > > > FOR_EACH_IMPL (impl, 0) > > > - do_one_test (impl, (CHAR *) (buf + align), seek_char, result); > > > + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, result); > > > > > > - 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; > > > + size_t i, j; > > > + int seek; > > > > > > test_init (); > > > + json_init (&json_ctx, 0, stdout); > > > > > > - printf ("%20s", ""); > > > - FOR_EACH_IMPL (impl, 0) > > > - printf ("\t%s", impl->name); > > > - putchar ('\n'); > > > + json_document_begin (&json_ctx); > > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > > > > > - for (i = 1; i < 8; ++i) > > > - { > > > - do_test (0, 16 << i, 2048, 23, SMALL_CHAR); > > > - do_test (i, 16 << i, 2048, 23, SMALL_CHAR); > > > - } > > > + json_attr_object_begin (&json_ctx, "functions"); > > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > > + json_attr_string (&json_ctx, "bench-variant", ""); > > > > > > - for (i = 1; i < 8; ++i) > > > - { > > > - do_test (i, 64, 256, 23, SMALL_CHAR); > > > - do_test (i, 64, 256, 23, BIG_CHAR); > > > - } > > > - > > > - for (i = 0; i < 32; ++i) > > > - { > > > - do_test (0, i, i + 1, 23, SMALL_CHAR); > > > - do_test (0, i, i + 1, 23, BIG_CHAR); > > > - } > > > + json_array_begin (&json_ctx, "ifuncs"); > > > + FOR_EACH_IMPL (impl, 0) > > > + json_element_string (&json_ctx, impl->name); > > > + json_array_end (&json_ctx); > > > > > > - for (i = 1; i < 8; ++i) > > > - { > > > - do_test (0, 16 << i, 2048, 0, SMALL_CHAR); > > > - do_test (i, 16 << i, 2048, 0, SMALL_CHAR); > > > - } > > > + json_array_begin (&json_ctx, "results"); > > > > > > - for (i = 1; i < 8; ++i) > > > + for (seek = 0; seek <= 23; seek += 23) > > > { > > > - do_test (i, 64, 256, 0, SMALL_CHAR); > > > - do_test (i, 64, 256, 0, BIG_CHAR); > > > + for (j = 1; j < 32; j += j) > > > + { > > > + for (i = 1; i < 9; ++i) > > > + { > > > + do_test (&json_ctx, 0, 16 << i, 2048, seek, SMALL_CHAR, j); > > > + do_test (&json_ctx, i, 16 << i, 2048, seek, SMALL_CHAR, j); > > > + } > > > + > > > + for (i = 1; i < 8; ++i) > > > + { > > > + do_test (&json_ctx, i, 64, 256, seek, SMALL_CHAR, j); > > > + do_test (&json_ctx, i, 64, 256, seek, BIG_CHAR, j); > > > + > > > + do_test (&json_ctx, i * 15, 64, 256, seek, SMALL_CHAR, j); > > > + do_test (&json_ctx, i * 15, 64, 256, seek, BIG_CHAR, j); > > > + } > > > + > > > + for (i = 0; i < 32; ++i) > > > + { > > > + do_test (&json_ctx, 0, i, i + 1, seek, SMALL_CHAR, j); > > > + do_test (&json_ctx, 0, i, i + 1, seek, BIG_CHAR, j); > > > + } > > > + if (seek == 0) > > > + { > > > + break; > > > + } > > > + } > > > } > > > > > > - for (i = 0; i < 32; ++i) > > > - { > > > - do_test (0, i, i + 1, 0, SMALL_CHAR); > > > - do_test (0, i, i + 1, 0, BIG_CHAR); > > > - } > > > + 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.25.1 > > > > > > > > > -- > > H.J.
On Thu, Apr 21, 2022 at 6:50 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > On Thu, Apr 21, 2022 at 3:08 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > > > On Thu, Apr 21, 2022 at 3:13 PM H.J. Lu <hjl.tools@gmail.com> wrote: > > > > > > On Wed, Apr 20, 2022 at 8:14 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote: > > > > > > > > 1. Use json-lib for printing results. > > > > 2. Expose all parameters (before pos, seek_char, and max_char where > > > > not printed). > > > > 3. Add benchmarks that test multiple occurence of seek_char in the > > > > string. > > > > --- > > > > benchtests/bench-strrchr.c | 126 ++++++++++++++++++++++++------------- > > > > 1 file changed, 82 insertions(+), 44 deletions(-) > > > > > > > > diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c > > > > index abdae60c51..cceea77e1b 100644 > > > > --- a/benchtests/bench-strrchr.c > > > > +++ b/benchtests/bench-strrchr.c > > > > @@ -23,6 +23,7 @@ > > > > # define TEST_NAME "strrchr" > > > > #endif > > > > #include "bench-string.h" > > > > +#include "json-lib.h" > > > > > > > > #define BIG_CHAR MAX_CHAR > > > > > > > > @@ -53,7 +54,8 @@ SIMPLE_STRRCHR (const CHAR *s, int c) > > > > } > > > > > > > > static void > > > > -do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > > +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, > > > > + CHAR *exp_res) > > > > { > > > > CHAR *res = CALL (impl, s, c); > > > > size_t i, iters = INNER_LOOP_ITERS8; > > > > @@ -61,8 +63,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > > > > > > if (res != exp_res) > > > > { > > > > - error (0, 0, "Wrong result in function %s %p %p", impl->name, > > > > - res, exp_res); > > > > + error (0, 0, "Wrong result in function %s %p %p", impl->name, res, > > > > + exp_res); > > > > > > These changes aren't needed. > > > > > > > ret = 1; > > > > return; > > > > } > > > > @@ -72,24 +74,28 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) > > > > { > > > > CALL (impl, s, c); > > > > } > > > > - TIMING_NOW (stop); > > > > > > > > + TIMING_NOW (stop); > > > > > > Not needed. > > > > Will fix in V2 > > > > > > > TIMING_DIFF (cur, start, stop); > > > > > > > > - TIMING_PRINT_MEAN ((double) cur, (double) iters); > > > > + json_element_double (json_ctx, (double) cur / (double) iters); > > > > + return; > > > > > > Return isn't needed. > > > > Will fix in V2. > > > > > > > } > > > > > > > > static void > > > > -do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > > +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, > > > > + int seek_char, int max_char, size_t freq) > > > > /* For wcsrchr: align here means align not in bytes, > > > > but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) > > > > len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ > > > > { > > > > size_t i; > > > > + size_t pos_chunk_sz = freq ? (pos / freq) : pos; > > > > + size_t last_pos = len; > > > > CHAR *result; > > > > CHAR *buf = (CHAR *) buf1; > > > > > > > > - align &= 7; > > > > + align &= (getpagesize () - 1); > > > > > > If we have such large alignments, the tests may be skipped. > > > Should we change it to 127 instead? > > > > There is logic around page cross cases in x86_64 versions so think > > makes sense to support benchmarking it. > > > > Also i think that would tend to give the previous version a bit of > > an unfair disadvantage as the slow aligning case will never be > > tested in the new version. > > If "align" is close to the page size, will it trigger > > if ((align + len) * sizeof (CHAR) >= page_size) > return; > > and skip page cross cases? https://sourceware.org/git/?p=glibc.git;a=blob;f=benchtests/bench-string.h;h=5339ff47ffd9c9082c7bce038da00f9c48472c7f;hb=HEAD#l244 So for med/small sizes we will be fine? > > > > > > > > if ((align + len) * sizeof (CHAR) >= page_size) > > > > return; > > > > > > > > @@ -103,6 +109,16 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > > if ((i > pos || pos >= len) && buf[align + i] == seek_char) > > > > buf[align + i] = seek_char + 10 + (random () & 15); > > > > } > > > > + > > > > + if (pos_chunk_sz == 0 && pos) > > > > + pos_chunk_sz = 1; > > > > + > > > > + for (i = pos_chunk_sz; i < pos && i < len; i += pos_chunk_sz) > > > > + { > > > > + buf[align + i] = seek_char; > > > > + last_pos = i; > > > > + } > > > > + > > > > buf[align + len] = 0; > > > > > > > > if (pos < len) > > > > @@ -110,66 +126,88 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) > > > > buf[align + pos] = seek_char; > > > > result = (CHAR *) (buf + align + pos); > > > > } > > > > + else if (last_pos < len) > > > > + result = (CHAR *) (buf + align + last_pos); > > > > else if (seek_char == 0) > > > > result = (CHAR *) (buf + align + len); > > > > else > > > > result = NULL; > > > > > > > > - printf ("Length %4zd, alignment in bytes %2zd:", len, align * sizeof (CHAR)); > > > > + json_element_object_begin (json_ctx); > > > > + json_attr_uint (json_ctx, "len", len); > > > > + json_attr_uint (json_ctx, "pos", pos); > > > > + json_attr_uint (json_ctx, "align", align); > > > > + json_attr_uint (json_ctx, "freq", freq); > > > > + json_attr_uint (json_ctx, "seek", seek_char); > > > > + json_attr_uint (json_ctx, "max_char", max_char); > > > > + json_array_begin (json_ctx, "timings"); > > > > > > > > FOR_EACH_IMPL (impl, 0) > > > > - do_one_test (impl, (CHAR *) (buf + align), seek_char, result); > > > > + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, result); > > > > > > > > - 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; > > > > + size_t i, j; > > > > + int seek; > > > > > > > > test_init (); > > > > + json_init (&json_ctx, 0, stdout); > > > > > > > > - printf ("%20s", ""); > > > > - FOR_EACH_IMPL (impl, 0) > > > > - printf ("\t%s", impl->name); > > > > - putchar ('\n'); > > > > + json_document_begin (&json_ctx); > > > > + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); > > > > > > > > - for (i = 1; i < 8; ++i) > > > > - { > > > > - do_test (0, 16 << i, 2048, 23, SMALL_CHAR); > > > > - do_test (i, 16 << i, 2048, 23, SMALL_CHAR); > > > > - } > > > > + json_attr_object_begin (&json_ctx, "functions"); > > > > + json_attr_object_begin (&json_ctx, TEST_NAME); > > > > + json_attr_string (&json_ctx, "bench-variant", ""); > > > > > > > > - for (i = 1; i < 8; ++i) > > > > - { > > > > - do_test (i, 64, 256, 23, SMALL_CHAR); > > > > - do_test (i, 64, 256, 23, BIG_CHAR); > > > > - } > > > > - > > > > - for (i = 0; i < 32; ++i) > > > > - { > > > > - do_test (0, i, i + 1, 23, SMALL_CHAR); > > > > - do_test (0, i, i + 1, 23, BIG_CHAR); > > > > - } > > > > + json_array_begin (&json_ctx, "ifuncs"); > > > > + FOR_EACH_IMPL (impl, 0) > > > > + json_element_string (&json_ctx, impl->name); > > > > + json_array_end (&json_ctx); > > > > > > > > - for (i = 1; i < 8; ++i) > > > > - { > > > > - do_test (0, 16 << i, 2048, 0, SMALL_CHAR); > > > > - do_test (i, 16 << i, 2048, 0, SMALL_CHAR); > > > > - } > > > > + json_array_begin (&json_ctx, "results"); > > > > > > > > - for (i = 1; i < 8; ++i) > > > > + for (seek = 0; seek <= 23; seek += 23) > > > > { > > > > - do_test (i, 64, 256, 0, SMALL_CHAR); > > > > - do_test (i, 64, 256, 0, BIG_CHAR); > > > > + for (j = 1; j < 32; j += j) > > > > + { > > > > + for (i = 1; i < 9; ++i) > > > > + { > > > > + do_test (&json_ctx, 0, 16 << i, 2048, seek, SMALL_CHAR, j); > > > > + do_test (&json_ctx, i, 16 << i, 2048, seek, SMALL_CHAR, j); > > > > + } > > > > + > > > > + for (i = 1; i < 8; ++i) > > > > + { > > > > + do_test (&json_ctx, i, 64, 256, seek, SMALL_CHAR, j); > > > > + do_test (&json_ctx, i, 64, 256, seek, BIG_CHAR, j); > > > > + > > > > + do_test (&json_ctx, i * 15, 64, 256, seek, SMALL_CHAR, j); > > > > + do_test (&json_ctx, i * 15, 64, 256, seek, BIG_CHAR, j); > > > > + } > > > > + > > > > + for (i = 0; i < 32; ++i) > > > > + { > > > > + do_test (&json_ctx, 0, i, i + 1, seek, SMALL_CHAR, j); > > > > + do_test (&json_ctx, 0, i, i + 1, seek, BIG_CHAR, j); > > > > + } > > > > + if (seek == 0) > > > > + { > > > > + break; > > > > + } > > > > + } > > > > } > > > > > > > > - for (i = 0; i < 32; ++i) > > > > - { > > > > - do_test (0, i, i + 1, 0, SMALL_CHAR); > > > > - do_test (0, i, i + 1, 0, BIG_CHAR); > > > > - } > > > > + 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.25.1 > > > > > > > > > > > > > -- > > > H.J. > > > > -- > H.J.
diff --git a/benchtests/bench-strrchr.c b/benchtests/bench-strrchr.c index abdae60c51..cceea77e1b 100644 --- a/benchtests/bench-strrchr.c +++ b/benchtests/bench-strrchr.c @@ -23,6 +23,7 @@ # define TEST_NAME "strrchr" #endif #include "bench-string.h" +#include "json-lib.h" #define BIG_CHAR MAX_CHAR @@ -53,7 +54,8 @@ SIMPLE_STRRCHR (const CHAR *s, int c) } static void -do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) +do_one_test (json_ctx_t *json_ctx, impl_t *impl, const CHAR *s, int c, + CHAR *exp_res) { CHAR *res = CALL (impl, s, c); size_t i, iters = INNER_LOOP_ITERS8; @@ -61,8 +63,8 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) if (res != exp_res) { - error (0, 0, "Wrong result in function %s %p %p", impl->name, - res, exp_res); + error (0, 0, "Wrong result in function %s %p %p", impl->name, res, + exp_res); ret = 1; return; } @@ -72,24 +74,28 @@ do_one_test (impl_t *impl, const CHAR *s, int c, CHAR *exp_res) { CALL (impl, s, c); } - TIMING_NOW (stop); + TIMING_NOW (stop); TIMING_DIFF (cur, start, stop); - TIMING_PRINT_MEAN ((double) cur, (double) iters); + json_element_double (json_ctx, (double) cur / (double) iters); + return; } static void -do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) +do_test (json_ctx_t *json_ctx, size_t align, size_t pos, size_t len, + int seek_char, int max_char, size_t freq) /* For wcsrchr: align here means align not in bytes, but in wchar_ts, in bytes it will equal to align * (sizeof (wchar_t)) len for wcschr here isn't in bytes but it's number of wchar_t symbols. */ { size_t i; + size_t pos_chunk_sz = freq ? (pos / freq) : pos; + size_t last_pos = len; CHAR *result; CHAR *buf = (CHAR *) buf1; - align &= 7; + align &= (getpagesize () - 1); if ((align + len) * sizeof (CHAR) >= page_size) return; @@ -103,6 +109,16 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) if ((i > pos || pos >= len) && buf[align + i] == seek_char) buf[align + i] = seek_char + 10 + (random () & 15); } + + if (pos_chunk_sz == 0 && pos) + pos_chunk_sz = 1; + + for (i = pos_chunk_sz; i < pos && i < len; i += pos_chunk_sz) + { + buf[align + i] = seek_char; + last_pos = i; + } + buf[align + len] = 0; if (pos < len) @@ -110,66 +126,88 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char) buf[align + pos] = seek_char; result = (CHAR *) (buf + align + pos); } + else if (last_pos < len) + result = (CHAR *) (buf + align + last_pos); else if (seek_char == 0) result = (CHAR *) (buf + align + len); else result = NULL; - printf ("Length %4zd, alignment in bytes %2zd:", len, align * sizeof (CHAR)); + json_element_object_begin (json_ctx); + json_attr_uint (json_ctx, "len", len); + json_attr_uint (json_ctx, "pos", pos); + json_attr_uint (json_ctx, "align", align); + json_attr_uint (json_ctx, "freq", freq); + json_attr_uint (json_ctx, "seek", seek_char); + json_attr_uint (json_ctx, "max_char", max_char); + json_array_begin (json_ctx, "timings"); FOR_EACH_IMPL (impl, 0) - do_one_test (impl, (CHAR *) (buf + align), seek_char, result); + do_one_test (json_ctx, impl, (CHAR *) (buf + align), seek_char, result); - 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; + size_t i, j; + int seek; test_init (); + json_init (&json_ctx, 0, stdout); - printf ("%20s", ""); - FOR_EACH_IMPL (impl, 0) - printf ("\t%s", impl->name); - putchar ('\n'); + json_document_begin (&json_ctx); + json_attr_string (&json_ctx, "timing_type", TIMING_TYPE); - for (i = 1; i < 8; ++i) - { - do_test (0, 16 << i, 2048, 23, SMALL_CHAR); - do_test (i, 16 << i, 2048, 23, SMALL_CHAR); - } + json_attr_object_begin (&json_ctx, "functions"); + json_attr_object_begin (&json_ctx, TEST_NAME); + json_attr_string (&json_ctx, "bench-variant", ""); - for (i = 1; i < 8; ++i) - { - do_test (i, 64, 256, 23, SMALL_CHAR); - do_test (i, 64, 256, 23, BIG_CHAR); - } - - for (i = 0; i < 32; ++i) - { - do_test (0, i, i + 1, 23, SMALL_CHAR); - do_test (0, i, i + 1, 23, BIG_CHAR); - } + json_array_begin (&json_ctx, "ifuncs"); + FOR_EACH_IMPL (impl, 0) + json_element_string (&json_ctx, impl->name); + json_array_end (&json_ctx); - for (i = 1; i < 8; ++i) - { - do_test (0, 16 << i, 2048, 0, SMALL_CHAR); - do_test (i, 16 << i, 2048, 0, SMALL_CHAR); - } + json_array_begin (&json_ctx, "results"); - for (i = 1; i < 8; ++i) + for (seek = 0; seek <= 23; seek += 23) { - do_test (i, 64, 256, 0, SMALL_CHAR); - do_test (i, 64, 256, 0, BIG_CHAR); + for (j = 1; j < 32; j += j) + { + for (i = 1; i < 9; ++i) + { + do_test (&json_ctx, 0, 16 << i, 2048, seek, SMALL_CHAR, j); + do_test (&json_ctx, i, 16 << i, 2048, seek, SMALL_CHAR, j); + } + + for (i = 1; i < 8; ++i) + { + do_test (&json_ctx, i, 64, 256, seek, SMALL_CHAR, j); + do_test (&json_ctx, i, 64, 256, seek, BIG_CHAR, j); + + do_test (&json_ctx, i * 15, 64, 256, seek, SMALL_CHAR, j); + do_test (&json_ctx, i * 15, 64, 256, seek, BIG_CHAR, j); + } + + for (i = 0; i < 32; ++i) + { + do_test (&json_ctx, 0, i, i + 1, seek, SMALL_CHAR, j); + do_test (&json_ctx, 0, i, i + 1, seek, BIG_CHAR, j); + } + if (seek == 0) + { + break; + } + } } - for (i = 0; i < 32; ++i) - { - do_test (0, i, i + 1, 0, SMALL_CHAR); - do_test (0, i, i + 1, 0, BIG_CHAR); - } + json_array_end (&json_ctx); + json_attr_object_end (&json_ctx); + json_attr_object_end (&json_ctx); + json_document_end (&json_ctx); return ret; }