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