Heh - there's a question :).

Looking at the two implementations, which do you think you better
understand (with complete certainty), and which would you be willing
to (say) bet your life on?

Personally I'm *almost* certain I know what the first does :).
I would not want to bet it is bug-free.

I'm sure the shorter implementation matches the *documented* 
strlcat() function.  The fact it runs faster is likely an artifact
of compiler optimizations specific to string functions.

I'll send this off to the OpenBSD folks just for grins.


From: Andi Gutmans [mailto:[EMAIL PROTECTED]]
> Are you sure it behaves *exactly* like the existing one?
> I stole the implementation from OpenBSD so it might be a good idea for you 
> to send it to them.
> They are the best to shed light on this and see if it's exactly the same 
> and faster.
> 
> Andi
> 
> At 09:00 02/05/2002 -0700, Preston L. Bannister wrote:
> >Was looking at the strlcat() implementation in the PHP source
> >and saw that it does not take advantage of history :).
> >
> >Look at xxx_strlcat() in the following example.
> >
> >You are almost always better off using the compiler's built-in
> >string functions, due to the optimizations built-in (many years ago)
> >to improve Dhrystone benchmark scores.  The benchmark turned out to
> >be a bit bogus, but the improvements made to the string functions
> >are a benefit to us all :).
> >
> >This is more readable (and thus more likely correct), slightly faster
> >(about 4% in my testing), and in the debug build better checked.
> >
> >Full comparison benchmark program:
> >-----
> >#include <stdlib.h>
> >#include <stdio.h>
> >#include <string.h>
> >#include <time.h>
> >#include <assert.h>
> >
> >/*
> >  * Appends src to string dst of size siz (unlike strncat, siz is the
> >  * full size of dst, not space left).  At most siz-1 characters
> >  * will be copied.  Always NUL terminates (unless siz == 0).
> >  * Returns strlen(src); if retval >= siz, truncation occurred.
> >  */
> >size_t php_strlcat(char* dst,const char* src,size_t siz)
> >{
> >         register char *d = dst;
> >         register const char *s = src;
> >         register size_t n = siz;
> >         size_t dlen;
> >
> >         /* Find the end of dst and adjust bytes left but don't go past end */
> >         while (*d != '\0' && n-- != 0)
> >                 d++;
> >         dlen = d - dst;
> >         n = siz - dlen;
> >
> >         if (n == 0)
> >                 return(dlen + strlen(s));
> >         while (*s != '\0') {
> >                 if (n != 1) {
> >                         *d++ = *s;
> >                         n--;
> >                 }
> >                 s++;
> >         }
> >         *d = '\0';
> >
> >         return(dlen + (s - src));       /* count does not include NUL */
> >}
> >
> >/*
> >  * Take full advantage of any compiler/library optimizations built in
> >  * to the standard string routines.  Look up the history of compiler
> >  * comparisons with Dhrystone benchmark to understand why this wins.
> >  * Pre-Internet history - check Google's USENET archive.
> >  */
> >size_t xxx_strlcat(char* s1,const char* s2,size_t nMax)
> >{
> >     size_t n1 = strlen(s1);
> >     size_t n2 = strlen(s2);
> >     size_t nCopy = (nMax <= (n1+n2)) ? (nMax - n1 - 1) : n2;
> >
> >     /* Better to leave this out and require a valid string return */
> >     if (!nMax) return 0;
> >
> >     assert(n1 < nMax);      /* Catch pre-existing oversize strings */
> >     assert(0 < nMax);       /* Insure return is always a valid string */
> >
> >     memcpy(s1+n1,s2,nCopy);
> >     s1[n1+nCopy] = 0;
> >     return n1+n2;           /* as documented for strlcat() */
> >     /*return n1+nCopy;        /* actual number of characters */
> >}
> >
> >/*
> >  *
> >  */
> >int main(int ac, char** av)
> >{
> >     clock_t t1,dt;
> >#ifdef WIN32
> >     __int64 nTotal;
> >#else
> >     long long nTotal;
> >#endif
> >     char s1[85];
> >     static char s2[] = "1234567890";
> >     int nLoops = 10;
> >
> >     if (1 < ac) {
> >         nLoops = atoi(av[1]);
> >     }
> >
> >     printf("Compare two strlcat() implementations for %d 
> > iterations.\n",nLoops);
> >
> >     t1 = clock();
> >     nTotal = 0;
> >     for (int i=0; i<nLoops; ++i) {
> >         s1[0] = 0;
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >         nTotal += php_strlcat(s1,s2,sizeof(s1));
> >     }
> >     dt = clock() - t1;
> >
> >     printf("php_strlcat() copied %1.0f characters in %ld 
> > ticks\n",(double)nTotal,(long)dt);
> >
> >     t1 = clock();
> >     nTotal = 0;
> >     for (i=0; i<nLoops; ++i) {
> >         s1[0] = 0;
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >         nTotal += xxx_strlcat(s1,s2,sizeof(s1));
> >     }
> >     dt = clock() - t1;
> >
> >     printf("xxx_strlcat() copied %1.0f characters in %ld 
> > ticks\n",(double)nTotal,(long)dt);
> >
> >     return 0;
> >}
> >-----


-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to