I tried to use strcmp(p, p) as a deliberate time-waster
once. I wanted to study the behavior of a sorting function
with "fast" and "slow" user-supplied comparators: the "slow"
one was strcmp(p, p) followed by a call to the "fast" one.
My program adjusted the length of the string at p until I got
a ten-to-one speed ratio.
This worked fine on several systems, but alas! I ran
across one where my setup code kept making p longer and longer
without slowing anything down -- and it turned out that strcmp
was returning zero immediately, as described.
BUT: Was this a stupid test? I don't think so. The
strcmp implementation made a bunch of (highly non-portable)
tests to decide whether it could replace a byte-by-byte loop
with a loop that took bigger, er, bites: two, four, or even
eight at a time. The decision was based on the alignments
of the two operands -- and the "both operands equal" case just
fell out of the alignment tests.
Eventually, I arranged for p to consist entirely of 'X'
and called strcmp(p, p+1), proceeding to call the "fast" method
if ("if") strcmp didn't return zero. Works like a charm.
Turns out that the possible missed branch prediction is
inconsequential (after all, it happens only once):
int testing_strcmp(const char *_s1, const char *_s2)
{
if (_s1 == _s2)
return 0;
else
while (*_s1 && (*_s1 == *_s2)) {
_s1++;
_s2++;
}
return (*_s1 > *_s2) - (*_s1 < *_s2);
} /* strcmp */
int non_testing_strcmp(const char *_s1, const char *_s2)
{
while (*_s1 && (*_s1 == *_s2)) {
_s1++;
_s2++;
}
return (*_s1 > *_s2) - (*_s1 < *_s2);
} /* strcmp */
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
char s1[32767];
char s2[32767];
void cmptest1(FILE * f, int (*cmp) (const char *, const
char *))
{
while (fgets(s1, sizeof s1, f)) {
if (fgets(s2, sizeof s2, f)) {
(void) cmp(s1, s2);
} else
break;
}
}
int main(int argc, char **argv)
{
clock_t end, start;
if (argc <= 1) {
puts("USAGE: strcmptest <filename>");
exit(EXIT_FAILURE);
}
{
FILE *f = fopen(argv[1], "rt");
if (f == NULL) {
printf("ERROR: Failed to open file %s\n", argv[1]);
exit(EXIT_FAILURE);
}
start = clock();
cmptest1(f, testing_strcmp);
end = clock();
printf("With testing strcmp time is %f seconds\n", (end -
start)*1.0/CLOCKS_PER_SEC);
rewind(f);
start = clock();
cmptest1(f, non_testing_strcmp);
end = clock();
printf("With non-testing strcmp time is %f seconds\n", (end -
start)*1.0/CLOCKS_PER_SEC);
}
return 0;
}
/*
C:\tmp>dir b.txt
Volume in drive C has no label.
Volume Serial Number is 0890-87CA
Directory of C:\tmp
08/18/2007 12:34 AM 65,969,707 b.txt
1 File(s) 65,969,707 bytes
0 Dir(s) 1,602,658,304 bytes free
C:\tmp>strcmptest b.txt
With testing strcmp time is 0.859000 seconds
With non-testing strcmp time is 0.859000 seconds
C:\tmp>strcmptest b.txt
With testing strcmp time is 0.859000 seconds
With non-testing strcmp time is 0.875000 seconds
C:\tmp>strcmptest b.txt
With testing strcmp time is 0.859000 seconds
With non-testing strcmp time is 0.859000 seconds
C:\tmp>strcmptest b.txt
With testing strcmp time is 0.859000 seconds
With non-testing strcmp time is 0.859000 seconds
C:\tmp>strcmptest b.txt
With testing strcmp time is 0.875000 seconds
With non-testing strcmp time is 0.843000 seconds
*/