* Joe Orton wrote:

> I understand the need for a strcasecmp replacement, but are the
> strcmp/!strcmp replacements just for consistency? On some platforms
> strcmp is an optimised asm inline so unless there's a good reason to
> tempt people away from strcmp I'd leave apr_streq/strneq out.

Attached is a quick benchmark with very interesting results. Some other
compiler tests would be helpful, of course.
The main result of this one is: As long as the function is inlined and an
optimizer is turned on, it's reasonably faster than strcmp.
It's finally worth the effort, I think.

I'm wondering, how it would be as a shared lib, though.

nd
$ gcc --version
gcc (GCC) 3.2.3 20030422 (Gentoo Linux 1.4 3.2.3-r1, propolice)
[...]

$ cat foo.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define LEN  (1024 * 1024)
#define ITER (1000 * 1000 * 1000)
#define AVE  5

#ifdef INLINE
__inline__
#endif
int streq(const char *a, const char *b)
{
    while (*a == *b && *a) {
        ++a;
        ++b;
    }

    return (*a == *b);
}

int main(int argc, const char *argv[]) {
    char *a, *b;
    unsigned count, i;
    unsigned long iter, m;
    time_t start, end, ave;
    int bool;

    a = malloc(LEN + 1);
    memset(a, 'a', LEN);
    a[LEN] = '\0';
    b = malloc(LEN + 1);
    memset(b, 'b', LEN);
    b[LEN] = '\0';

    m = (argc > 1) ? atoi(argv[1]) : ITER;
    count = (argc > 2) ? atoi(argv[2]): AVE;
    ave = 0;

    printf("iterations: %lu\n\n", m);

    for (i = 0; i < count; ++i) {
        iter = m + 1;
        start = time(NULL);
        while (--iter) {
            bool = streq(a,b);
        }
        end = time(NULL);
        printf("[%02u/%02u] streq: %u sec\n", i+1, count, end-start);
        ave += (end-start);
    }

    printf("[average] streq: %g sec\n", (float)ave / (float)count);

    ave = 0;
    for (i = 0; i < count; ++i) {
        iter = m + 1;
        start = time(NULL);
        while (--iter) {
            bool = !strcmp(a,b);
        }
        end=time(NULL);
        printf("[%02u/%02u] !strcmp: %u sec\n", i+1, count, end-start);
        ave += (end-start);
    }

    printf("[average] !strcmp: %g sec\n", (float)ave / (float)count);

    return 0;
}

------------------------------
$ gcc -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 20 sec
[02/05] streq: 21 sec
[03/05] streq: 20 sec
[04/05] streq: 20 sec
[05/05] streq: 20 sec
[average] streq: 20.2 sec
[01/05] !strcmp: 17 sec
[02/05] !strcmp: 18 sec
[03/05] !strcmp: 17 sec
[04/05] !strcmp: 17 sec
[05/05] !strcmp: 17 sec
[average] !strcmp: 17.2 sec

$ gcc -DINLINE -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 20 sec
[02/05] streq: 21 sec
[03/05] streq: 20 sec
[04/05] streq: 20 sec
[05/05] streq: 20 sec
[average] streq: 20.2 sec
[01/05] !strcmp: 17 sec
[02/05] !strcmp: 18 sec
[03/05] !strcmp: 17 sec
[04/05] !strcmp: 17 sec
[05/05] !strcmp: 17 sec
[average] !strcmp: 17.2 sec

------------------------------
$ gcc -O -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 15 sec
[02/05] streq: 14 sec
[03/05] streq: 14 sec
[04/05] streq: 14 sec
[05/05] streq: 14 sec
[average] streq: 14.2 sec
[01/05] !strcmp: 13 sec
[02/05] !strcmp: 12 sec
[03/05] !strcmp: 12 sec
[04/05] !strcmp: 12 sec
[05/05] !strcmp: 13 sec
[average] !strcmp: 12.4 sec

$ gcc -O -DINLINE -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 4 sec
[02/05] streq: 4 sec
[03/05] streq: 4 sec
[04/05] streq: 4 sec
[05/05] streq: 5 sec
[average] streq: 4.2 sec
[01/05] !strcmp: 12 sec
[02/05] !strcmp: 12 sec
[03/05] !strcmp: 13 sec
[04/05] !strcmp: 12 sec
[05/05] !strcmp: 12 sec
[average] !strcmp: 12.2 sec

------------------------------
$ gcc -O2 -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 14 sec
[02/05] streq: 15 sec
[03/05] streq: 14 sec
[04/05] streq: 14 sec
[05/05] streq: 14 sec
[average] streq: 14.2 sec
[01/05] !strcmp: 13 sec
[02/05] !strcmp: 13 sec
[03/05] !strcmp: 13 sec
[04/05] !strcmp: 13 sec
[05/05] !strcmp: 12 sec
[average] !strcmp: 12.8 sec

$ gcc -O2 -DINLINE -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 3 sec
[02/05] streq: 3 sec
[03/05] streq: 3 sec
[04/05] streq: 4 sec
[05/05] streq: 3 sec
[average] streq: 3.2 sec
[01/05] !strcmp: 12 sec
[02/05] !strcmp: 12 sec
[03/05] !strcmp: 12 sec
[04/05] !strcmp: 12 sec
[05/05] !strcmp: 13 sec
[average] !strcmp: 12.2 sec

------------------------------
$ gcc -O3 -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 4 sec
[02/05] streq: 3 sec
[03/05] streq: 3 sec
[04/05] streq: 3 sec
[05/05] streq: 3 sec
[average] streq: 3.2 sec
[01/05] !strcmp: 12 sec
[02/05] !strcmp: 12 sec
[03/05] !strcmp: 12 sec
[04/05] !strcmp: 12 sec
[05/05] !strcmp: 13 sec
[average] !strcmp: 12.2 sec

$ gcc -O3 -DINLINE -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 3 sec
[02/05] streq: 3 sec
[03/05] streq: 3 sec
[04/05] streq: 3 sec
[05/05] streq: 3 sec
[average] streq: 3 sec
[01/05] !strcmp: 12 sec
[02/05] !strcmp: 13 sec
[03/05] !strcmp: 12 sec
[04/05] !strcmp: 12 sec
[05/05] !strcmp: 12 sec
[average] !strcmp: 12.2 sec

-----------------------------
$ gcc -Os -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 16 sec
[02/05] streq: 16 sec
[03/05] streq: 17 sec
[04/05] streq: 16 sec
[05/05] streq: 16 sec
[average] streq: 16.2 sec
[01/05] !strcmp: 15 sec
[02/05] !strcmp: 15 sec
[03/05] !strcmp: 16 sec
[04/05] !strcmp: 15 sec
[05/05] !strcmp: 15 sec
[average] !strcmp: 15.2 sec

$ gcc -Os -DINLINE -o foo foo.c && ./foo
iterations: 1000000000

[01/05] streq: 5 sec
[02/05] streq: 6 sec
[03/05] streq: 5 sec
[04/05] streq: 5 sec
[05/05] streq: 5 sec
[average] streq: 5.2 sec
[01/05] !strcmp: 15 sec
[02/05] !strcmp: 15 sec
[03/05] !strcmp: 15 sec
[04/05] !strcmp: 16 sec
[05/05] !strcmp: 15 sec
[average] !strcmp: 15.2 sec

Reply via email to