Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 14 Jul 2007 17:17:44 -0700
From:      Tim Kientzle <kientzle@freebsd.org>
To:        Garrett Cooper <youshi10@u.washington.edu>
Cc:        ports@freebsd.org, hackers@freebsd.org, krion@freebsd.org
Subject:   Re: Finding slowdowns in	pkg_install	(continuations	of	previous	threads)
Message-ID:  <469967A8.3080901@freebsd.org>
In-Reply-To: <4699587F.30703@u.washington.edu>
References:  <468C96C0.1040603@u.washington.edu>	<468C9718.1050108@u.washington.edu>	<468E60E9.80507@freebsd.org>	<468E6C81.4060908@u.washington.edu>	<468E7192.8030105@freebsd.org>	<4696C0D2.6010809@u.washington.edu>	<4697A210.2020301@u.washington.edu> <4698ADB5.7080600@u.washington.edu> <4698F98A.6080908@freebsd.org> <4699587F.30703@u.washington.edu>

next in thread | previous in thread | raw e-mail | index | archive | help
>    The following blog post has all of my commentary on the results I 
> have: 
> <http://blogs.freebsdish.org/gcooper/2007/07/14/modifications-to-pkg_install-the-positive-and-negative-implications/>. 

> I tried to unroll strcmp a bit by checking for the first character of the
 > command, then run strcmp ...

There's a somewhat more straightforward optimization that
relies on this same idea:

switch(cmd[0]) {
case 'c':
     /* Commands that start with 'c' */
     if (strcmp(cmd, 'cwd') == 0)
	return (CMD_CWD);
     /* FALLTHROUGH */
case 'd':
     /* Commands that start with 'd' */

     .... etc....
     /* FALLTHROUGH */
default:
     /* Unrecognized command. */
}

This is a little cleaner and easier to read
and may even be faster than the code you
presented in your blog.  Note that the fall through
ensures that all unrecognized commands end up at
the same place.  If unrecognized commands are
very rare (they should be), then the fallthrough
is not a performance issue.

> /** malloc buffer large enough to hold +CONTENTS **/
> 
> while(!feof(file_p)) {
> 
>     /** add content via fgetc **/
> }

Yuck.  Try this instead:

    struct stat st;
    int fd;
    char *buff;

    fd = open(file);
    fstat(fd, &st);
    buff = malloc(st.st_size + 1);
    read(fd, buff, st.st_size);
    buff[st.st_size] = '\0';
    close(fd);

Plus some error checking, of course.  You can
use stdio if you prefer:

    FILE *f;

    f = fopen(file, "r");
    fstat(fileno(f), &st);
    buff = malloc(st.st_size + 1);
    fread(buff, 1, st.st_size, f);
    buff[st.st_size] = '\0';
    fclose(f);

Either way, this is a lot more efficient than
tens of thousands of calls to fgetc().

Cheers,

Tim Kientzle



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?469967A8.3080901>