List Info

Thread: Re: faster strchr




Re: faster strchr
country flaguser name
United States
2008-05-28 10:21:57
Jeff Johnston <jjohnstn <at> redhat.com>
writes:

> >>>       
> >> Yes, go ahead.  I assume you have verified
that the function still works 
> >> correctly.
> >>
> > OK for this followon, which changes the generic C
code in the same manner 
(also 
> > tested)?
> 
> Yes, thanks.
> 

OK for this followup?  This codifies my regression test into
version control, 
rather than just this email thread.  I tested with:

$ cd libc/string
$ gcc -Wall -o strchr -O2 -D_REGRESSION_TEST strchr.c
$ time ./strchr --all    # C implementation

real	0m3.188s
user	0m3.171s
sys	0m0.030s
$ gcc -c -o strchr1.o -Dstrchr=strchr1
../machine/i386/strchr.S
$ gcc -Wall -o strchr -O2 -D_REGRESSION_TEST
-DTEST_STRCHR=strchr1 
  strchr.c strchr1.o
$ time ./strchr --all    # Assembly implementation

real	0m2.922s
user	0m2.890s
sys	0m0.030s


If this approach is okay, then I will make similar changes
for the other 
functions I have touched; am I pre-approved for checking
those in too?  Do you 
want me to also try and figure out how to hook this into
'make check'?

2008-05-28  Eric Blake  <ebb9byu.net>

	Add test for recent changes.
	* libc/string/strchr.c [_REGRESSION_TEST]: New section,
which can
	optionally be compiled as a regression test.

Index: libc/string/strchr.c
============================================================
=======
RCS file: /cvs/src/src/newlib/libc/string/strchr.c,v
retrieving revision 1.3
diff -u -p -r1.3 strchr.c
--- libc/string/strchr.c	22 May 2008 02:31:46 -0000	1.3
+++ libc/string/strchr.c	28 May 2008 15:17:27 -0000
 -121,3
+121,101  _DEFUN (strchr, (s1, i),
     return (char *)s;
   return NULL;
 }
+
+/* The remainder of this file can serve as a regression
test.  Compile
+   with -D_REGRESSION_TEST, and optionally with
+   -DTEST_STRCHR=strchr_alt when linked with strchr_alt.o,
to ensure
+   correct operation and allow timing tests.  */
+#ifdef _REGRESSION_TEST
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <assert.h>
+
+# ifdef TEST_STRCHR
+char *TEST_STRCHR (const char *, int);
+# else
+#  define TEST_STRCHR strchr
+# endif
+
+static void
+test (size_t size, size_t repeat, size_t offset, int goal)
+{
+  char *buf = malloc (size + 1);
+  char *expected;
+  assert (buf);
+  switch (goal)
+    {
+    case 0:
+      expected = buf + size;
+      break;
+    case 1:
+      expected = (size > 1 && offset < size -
1) ? buf + offset : NULL;
+      break;
+    case 2:
+      expected = offset < size ? buf + size - 1 : NULL;
+      break;
+    default:
+      expected = NULL;
+      break;
+    }
+  if (size)
+    {
+      memset (buf, 1, size - 1);
+      buf[size - 1] = 2;
+    }
+  buf[size] = 0;
+  buf += offset;
+  while (repeat--)
+    assert (TEST_STRCHR (buf, goal) == expected);
+  buf -= offset;
+  free (buf);
+}
+
+int
+main (int argc, char **argv)
+{
+  if (argc == 2 && strcmp (argv[1],
"--all") == 0)
+    {
+      int i, j, k;
+
+      /* Ensure all alignments for both start and target
work.  */
+      for (i = 0; i <= 32; i++)
+        for (j = 0; j < i; j++)
+          for (k = 0; k <= 3; k++)
+            test (i, 1, j, k);
+      /* Multiple runs to make timing easier.  */
+      test (1000000, 1000, 0, 0);
+      test (1000000, 1000, 1, 0);
+      test (1000000, 1000, 0, 1);
+      test (1000000, 1000, 1, 1);
+      test (1000000, 1000, 0, 2);
+      test (1000000, 1000, 1, 2);
+      test (1000000, 1000, 0, 3);
+      test (1000000, 1000, 1, 3);
+      return 0;
+    }
+  if (argc < 5)
+    {
+      printf ("usage: %s --alln", argv[0]);
+      printf ("   or: %s size repeat offset
goaln", argv[0]);
+      printf ("t--all - run a canned set of
testsn");
+      printf ("tsize - buffer size to search
inn");
+      printf ("trepeat - times to repeat
searchn");
+      printf ("toffset - offset within buf to start
search, <= sizen");
+      printf ("tgoal - 0 for end, 1 for beginning, 2
for next to last, 3 for 
missn");
+      return 1;
+    }
+  size_t size = strtol (argv[1], NULL, 0);
+  size_t repeat = strtol (argv[2], NULL, 0);
+  size_t offset = strtol (argv[3], NULL, 0);
+  int goal = strtol (argv[4], NULL, 0);
+  if (!repeat)
+    repeat = 1;
+  if (size < offset)
+    offset = size;
+  test (size, repeat, offset, goal);
+  return 0;
+}
+
+#endif /* _REGRESSION_TEST */




[1]

about | contact  Other archives ( Real Estate discussion Medical topics )