File trees: the deeper, the weirder

Yar Tikhiy yar at comp.chem.msu.su
Sun Oct 29 14:07:22 UTC 2006


Folks,

Here's a funny observation.  A program essentially doing:

	for (;;) {
		mkdir("foo");
		chdir("foo");
	}

starts as fast as the system permits, but settles to *exactly* one
cycle per second at some depth that seems to depend only on the
amount of RAM in the machine.  An array sized at boot time seems
to play a role there: for 128M the depth is ~7800, for 512M it's
~35000.  The system feels very slow then, but only due to the fact
that fs-related syscalls often take *exactly* one second to complete.
As for the said program, it keeps its 1 Hz pace, mostly waiting on
"vlruwk".  It's killable, after a delay.  The system doesn't show
any signs of instability, and it's mostly idle according to top or
systat!

Weird, eh?  Any ideas what's going on?

-- 
Yar

P.S. Here's the test program generalised and enhanced with timing
diagnostics (-v).  By setting several -v options, you'll get the
diagnostics more often, exponentially.

/*
 * Usage:
 *
 *      xdir [-v -v ...] name-length tree-depth
 *
 * This program will create a chain of subdirectories rooted
 * in the current directory.  Each subdir's name will be:
 *
 *      000 ... [ name-lenght times ] ... 000
 *
 * The total depth will be tree-depth:
 *
 *      000+/000+/ ... [ tree-depth times] ... /000+/000+
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <err.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int verbose;

int
main(int argc, char **argv)
{
        int i, n, m, r;
        double dt;
        struct timeval tv0, tv;
        char buf[NAME_MAX + 1];

        while ((i = getopt(argc, argv, "v")) != -1)
                switch (i) {
                case 'v':
                        verbose++;
                        break;
                default:
                        errx(2, "bad option");
                }

        argc -= optind;
        argv += optind;

        if (argv[0] == NULL || (n = atoi(argv[0])) <= 0)
                errx(2, "bad length");
        if (argv[1] == NULL || (m = atoi(argv[1])) <= 0)
                errx(2, "bad depth");
        if (n > NAME_MAX)
                errx(2, "too long");

        sprintf(buf, "%0*d", n, 0);

        r = 1000;       /* fool gcc */
        if (verbose) {
                for (i = 1; i < verbose && r > 9; i++)
                        r /= 10;
                gettimeofday(&tv0, NULL);
        }

        for (i = 1; i <= m; i++) {
                if (mkdir(buf, 0700) == -1)
                        err(2, "mkdir %s", buf);
                if (chdir(buf) == -1)
                        err(2, "chdir %s", buf);
                if (verbose && (i % r) == 0) {
                        gettimeofday(&tv, NULL);
                        dt  = tv.tv_usec - tv0.tv_usec;
                        dt /= 1000000;
                        dt += tv.tv_sec - tv0.tv_sec;
                        printf("%d (%.1lf)... ", i, r / dt);
                        fflush(stdout);
                        tv0 = tv;
                }
        }
        return (0);
}


More information about the freebsd-hackers mailing list