2 * Copyright (c) 2000-2004 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <sys/param.h>
31 typedef unsigned int uint_t;
34 * Loop over directory sizes:
36 * touch n files in each directory
37 * stat the files round-robin
38 * readdir/unlink the files
39 * Change directory sizes by multiplication or addition.
40 * Allow control of starting & stopping sizes, name length, target directory.
41 * Print size and wallclock time (ms per file).
42 * Output can be used to make graphs (gnuplot)
46 static uint_t dirchars;
47 static char *directory;
48 static uint_t firstsize;
49 static uint_t lastsize;
50 static uint_t minchars;
54 static uint_t pfxchars;
57 static void filename(int, int, char *);
58 static int hexchars(uint_t);
59 static uint_t nextsize(uint_t);
60 static double now(void);
61 static void usage(void);
64 * Maximum size allowed, this is pretty nuts.
65 * The largest one we've ever built has been about 2 million.
67 #define MAX_DIR_SIZE (16 * 1024 * 1024)
68 #define DFL_FIRST_SIZE 1
69 #define DFL_LAST_SIZE (1024 * 1024)
70 #define MAX_DIR_COUNT 1024
71 #define MIN_DIR_COUNT 1
74 main(int argc, char **argv)
81 char name[NAME_MAX + 1];
85 while ((c = getopt(argc, argv, "a:c:d:f:l:m:n:s:")) != -1) {
88 addval = (uint_t)atoi(optarg);
91 nchars = (uint_t)atoi(optarg);
97 firstsize = (uint_t)atoi(optarg);
100 lastsize = (uint_t)atoi(optarg);
103 mulval = atof(optarg);
106 ndirs = (uint_t)atoi(optarg);
109 stats = (uint_t)atoi(optarg);
117 if (!addval && !mulval)
119 else if ((addval && mulval) || mulval < 0.0) {
128 if (mkdir(directory, 0777) < 0 && errno != EEXIST) {
132 if (chdir(directory) < 0) {
138 firstsize = DFL_FIRST_SIZE;
139 else if (firstsize > MAX_DIR_SIZE)
140 firstsize = MAX_DIR_SIZE;
142 lastsize = DFL_LAST_SIZE;
143 else if (lastsize > MAX_DIR_SIZE)
144 lastsize = MAX_DIR_SIZE;
145 if (lastsize < firstsize)
146 lastsize = firstsize;
147 minchars = hexchars(lastsize - 1);
148 if (nchars < minchars)
150 else if (nchars >= NAME_MAX + 1)
152 if (ndirs > MAX_DIR_COUNT)
153 ndirs = MAX_DIR_COUNT;
154 if (ndirs < MIN_DIR_COUNT)
155 ndirs = MIN_DIR_COUNT;
156 dirchars = hexchars(ndirs);
157 pfxchars = nchars - minchars;
159 memset(&name[dirchars + 1], 'a', pfxchars);
160 for (j = 0; j < ndirs; j++) {
161 filename(0, j, name);
162 name[dirchars] = '\0';
165 for (cursize = firstsize;
167 cursize = nextsize(cursize)) {
169 for (i = 0; i < cursize; i++) {
170 for (j = 0; j < ndirs; j++) {
171 filename((i + j) % cursize, j, name);
172 close(creat(name, 0666));
175 for (i = 0; i < cursize * stats; i++) {
176 for (j = 0; j < ndirs; j++) {
177 filename((i + j) % cursize, j, name);
181 for (j = 0; j < ndirs; j++) {
182 filename(0, j, name);
183 name[dirchars] = '\0';
184 dirp = opendir(name);
185 while (readdir(dirp))
189 for (i = 0; i < cursize; i++) {
190 for (j = 0; j < ndirs; j++) {
191 filename((i + j) % cursize, j, name);
195 printf("%d %.3f\n", cursize,
196 (now() - stime) * 1.0e3 / (cursize * ndirs));
198 for (j = 0; j < ndirs; j++) {
199 filename(0, j, name);
200 name[dirchars] = '\0';
207 filename(int idx, int dir, char *name)
209 static char hexc[16] = "0123456789abcdef";
212 for (i = dirchars - 1; i >= 0; i--)
213 *name++ = hexc[(dir >> (4 * i)) & 0xf];
215 name += pfxchars; /* skip pfx a's */
216 for (i = minchars - 1; i >= 0; i--)
217 *name++ = hexc[(idx >> (4 * i)) & 0xf];
222 hexchars(uint_t maxval)
226 if (maxval < 16 * 16)
228 if (maxval < 16 * 16 * 16)
230 if (maxval < 16 * 16 * 16 * 16)
232 if (maxval < 16 * 16 * 16 * 16 * 16)
234 if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
236 if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
242 nextsize(uint_t cursize)
251 if (n > (double)lastsize + 0.5)
252 return lastsize + 1; /* i.e. out of bounds */
253 else if ((uint_t)n == cursize)
264 gettimeofday(&tv, NULL);
265 return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
272 "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
273 "[-l last] [-c nchars] [-n ndirs] [-s nstats]\n");