[4/4] bench-strcmp.c: Add workloads on page boundary

Message ID 20200612201056.228614-4-hjl.tools@gmail.com
State Superseded
Headers
Series [1/4] strncmp: Add a testcase for page boundary [BZ #25933] |

Commit Message

H.J. Lu June 12, 2020, 8:10 p.m. UTC
  Add strcmp workloads on page boundary.
---
 benchtests/bench-strcmp.c | 48 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)
  

Comments

Carlos O'Donell Sept. 24, 2020, 12:52 a.m. UTC | #1
On 6/12/20 4:10 PM, H.J. Lu via Libc-alpha wrote:
> Add strcmp workloads on page boundary.
> ---
>  benchtests/bench-strcmp.c | 48 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 

These additions to the benchmark exercise the page boundary conditions
in the algorithms implemented by all the architectures. The test is
designed from the experience with bug 25933 in mind so we should mention
that in a comment. It could be made a bit more generic by parametrizing
vector sizes and number of vector registers that might be grouped e.g.
32 * 4, but it's fine as it is for now to test the page boundary.

OK with:
- Function rename
- Added comments.
- s1a iterate over [30,21)

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> diff --git a/benchtests/bench-strcmp.c b/benchtests/bench-strcmp.c
> index 47d0a35299..3ba1399a4d 100644
> --- a/benchtests/bench-strcmp.c
> +++ b/benchtests/bench-strcmp.c
> @@ -144,6 +144,52 @@ do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len, int
>    json_element_object_end (json_ctx);
>  }
>  
> +static void
> +do_test_page_boundary_1 (json_ctx_t *json_ctx, CHAR *s1, CHAR *s2,

Rename to do_one_test_page_boundary ()

> +			 size_t align1, size_t align2, size_t len,
> +			 int exp_result)
> +{
> +  json_element_object_begin (json_ctx);
> +  json_attr_uint (json_ctx, "length", (double) len);
> +  json_attr_uint (json_ctx, "align1", (double) align1);
> +  json_attr_uint (json_ctx, "align2", (double) align2);
> +  json_array_begin (json_ctx, "timings");
> +  FOR_EACH_IMPL (impl, 0)
> +    do_one_test (json_ctx, impl, s1, s2, exp_result);

OK.

> +  json_array_end (json_ctx);
> +  json_element_object_end (json_ctx);
> +}
> +

Add a comment:

/* To trigger bug 25933 we need a size that is equal to the
   vector length times 4. In the case of AVX2 for Intel we
   need 32 * 4. We make this test generic and run it for all
   architectures as additional boundary testing for such
   related algorithms.  */

> +static void
> +do_test_page_boundary (json_ctx_t *json_ctx)
> +{
> +  size_t size = 32 * 4;
> +  size_t len;
> +  CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size);
> +  CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size);
> +  int exp_result;
> +
> +  memset (s1, 'a', page_size);
> +  memset (s2, 'a', page_size);
> +
> +  s1[(page_size / CHARBYTES) - 1] = (CHAR) 0;
> +  s2[(page_size / CHARBYTES) - 1] = (CHAR) 0;
> +


Add comment:

/* Iterate over a size that is just below where we expect
   the bug to trigger up to the size we expect will trigger
   the bug e.g. [99-128].  Likewise iterate the start of
   two strings between 30 and 31 bytes away from the
   boundary to simulate alignment changes.  */

> +  for (size_t s = 99; s <= size; s++)
> +    for (size_t s1a = 31; s1a < 32; s1a++)

Make s1a iterate over [30,32) like s2a.

> +      for (size_t s2a = 30; s2a < 32; s2a++)
> +	{
> +	  size_t align1 = (page_size / CHARBYTES - s) - s1a;
> +	  size_t align2 = (page_size / CHARBYTES - s) - s2a;
> +	  CHAR *s1p = s1 + align1;
> +	  CHAR *s2p = s2 + align2;
> +	  len = (page_size / CHARBYTES) - 1 - align1;
> +	  exp_result = SIMPLE_STRCMP (s1p, s2p);
> +	  do_test_page_boundary_1 (json_ctx, s1p, s2p, align1, align2,

Call do_one_test_page_boundary ()

> +				   len, exp_result);
> +	}
> +}
> +
>  int
>  test_main (void)
>  {
> @@ -197,6 +243,8 @@ test_main (void)
>        do_test (&json_ctx, 2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, -1);
>      }
>  
> +  do_test_page_boundary (&json_ctx);

OK.

> +
>    json_array_end (&json_ctx);
>    json_attr_object_end (&json_ctx);
>    json_attr_object_end (&json_ctx);
>
  

Patch

diff --git a/benchtests/bench-strcmp.c b/benchtests/bench-strcmp.c
index 47d0a35299..3ba1399a4d 100644
--- a/benchtests/bench-strcmp.c
+++ b/benchtests/bench-strcmp.c
@@ -144,6 +144,52 @@  do_test (json_ctx_t *json_ctx, size_t align1, size_t align2, size_t len, int
   json_element_object_end (json_ctx);
 }
 
+static void
+do_test_page_boundary_1 (json_ctx_t *json_ctx, CHAR *s1, CHAR *s2,
+			 size_t align1, size_t align2, size_t len,
+			 int exp_result)
+{
+  json_element_object_begin (json_ctx);
+  json_attr_uint (json_ctx, "length", (double) len);
+  json_attr_uint (json_ctx, "align1", (double) align1);
+  json_attr_uint (json_ctx, "align2", (double) align2);
+  json_array_begin (json_ctx, "timings");
+  FOR_EACH_IMPL (impl, 0)
+    do_one_test (json_ctx, impl, s1, s2, exp_result);
+  json_array_end (json_ctx);
+  json_element_object_end (json_ctx);
+}
+
+static void
+do_test_page_boundary (json_ctx_t *json_ctx)
+{
+  size_t size = 32 * 4;
+  size_t len;
+  CHAR *s1 = (CHAR *) (buf1 + (BUF1PAGES - 1) * page_size);
+  CHAR *s2 = (CHAR *) (buf2 + (BUF1PAGES - 1) * page_size);
+  int exp_result;
+
+  memset (s1, 'a', page_size);
+  memset (s2, 'a', page_size);
+
+  s1[(page_size / CHARBYTES) - 1] = (CHAR) 0;
+  s2[(page_size / CHARBYTES) - 1] = (CHAR) 0;
+
+  for (size_t s = 99; s <= size; s++)
+    for (size_t s1a = 31; s1a < 32; s1a++)
+      for (size_t s2a = 30; s2a < 32; s2a++)
+	{
+	  size_t align1 = (page_size / CHARBYTES - s) - s1a;
+	  size_t align2 = (page_size / CHARBYTES - s) - s2a;
+	  CHAR *s1p = s1 + align1;
+	  CHAR *s2p = s2 + align2;
+	  len = (page_size / CHARBYTES) - 1 - align1;
+	  exp_result = SIMPLE_STRCMP (s1p, s2p);
+	  do_test_page_boundary_1 (json_ctx, s1p, s2p, align1, align2,
+				   len, exp_result);
+	}
+}
+
 int
 test_main (void)
 {
@@ -197,6 +243,8 @@  test_main (void)
       do_test (&json_ctx, 2 * CHARBYTES * i, CHARBYTES * i, 8 << i, LARGECHAR, -1);
     }
 
+  do_test_page_boundary (&json_ctx);
+
   json_array_end (&json_ctx);
   json_attr_object_end (&json_ctx);
   json_attr_object_end (&json_ctx);