faster strchr
Eric Blake
ebb9@byu.net
Tue Jun 3 18:29:00 GMT 2008
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 <ebb9@byu.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 --all\n", argv[0]);
+ printf (" or: %s size repeat offset goal\n", argv[0]);
+ printf ("\t--all - run a canned set of tests\n");
+ printf ("\tsize - buffer size to search in\n");
+ printf ("\trepeat - times to repeat search\n");
+ printf ("\toffset - offset within buf to start search, <= size\n");
+ printf ("\tgoal - 0 for end, 1 for beginning, 2 for next to last, 3 for
miss\n");
+ 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 */
More information about the Newlib
mailing list