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 #define MAXNAMELEN 256
33 typedef unsigned int uint_t;
37 * Loop over directory sizes:
39 * touch n files in each directory
40 * stat the files round-robin
41 * readdir/unlink the files
42 * Change directory sizes by multiplication or addition.
43 * Allow control of starting & stopping sizes, name length, target directory.
44 * Print size and wallclock time (ms per file).
45 * Output can be used to make graphs (gnuplot)
49 static uint_t dirchars;
50 static char *directory;
51 static uint_t firstsize;
52 static uint_t lastsize;
53 static uint_t minchars;
57 static uint_t pfxchars;
60 static void filename(int, int, char *);
61 static int hexchars(uint_t);
62 static uint_t nextsize(uint_t);
63 static double now(void);
64 static void usage(void);
67 * Maximum size allowed, this is pretty nuts.
68 * The largest one we've ever built has been about 2 million.
70 #define MAX_DIR_SIZE (16 * 1024 * 1024)
71 #define DFL_FIRST_SIZE 1
72 #define DFL_LAST_SIZE (1024 * 1024)
73 #define MAX_DIR_COUNT 1024
74 #define MIN_DIR_COUNT 1
77 main(int argc, char **argv)
84 char name[MAXNAMELEN];
88 while ((c = getopt(argc, argv, "a:c:d:f:l:m:n:s:")) != -1) {
91 addval = (uint_t)atoi(optarg);
94 nchars = (uint_t)atoi(optarg);
100 firstsize = (uint_t)atoi(optarg);
103 lastsize = (uint_t)atoi(optarg);
106 mulval = atof(optarg);
109 ndirs = (uint_t)atoi(optarg);
112 stats = (uint_t)atoi(optarg);
120 if (!addval && !mulval)
122 else if ((addval && mulval) || mulval < 0.0) {
131 if (mkdir(directory, 0777) < 0 && errno != EEXIST) {
135 if (chdir(directory) < 0) {
141 firstsize = DFL_FIRST_SIZE;
142 else if (firstsize > MAX_DIR_SIZE)
143 firstsize = MAX_DIR_SIZE;
145 lastsize = DFL_LAST_SIZE;
146 else if (lastsize > MAX_DIR_SIZE)
147 lastsize = MAX_DIR_SIZE;
148 if (lastsize < firstsize)
149 lastsize = firstsize;
150 minchars = hexchars(lastsize - 1);
151 if (nchars < minchars)
153 else if (nchars >= MAXNAMELEN)
154 nchars = MAXNAMELEN - 1;
155 if (ndirs > MAX_DIR_COUNT)
156 ndirs = MAX_DIR_COUNT;
157 if (ndirs < MIN_DIR_COUNT)
158 ndirs = MIN_DIR_COUNT;
159 dirchars = hexchars(ndirs);
160 pfxchars = nchars - minchars;
162 memset(&name[dirchars + 1], 'a', pfxchars);
163 for (j = 0; j < ndirs; j++) {
164 filename(0, j, name);
165 name[dirchars] = '\0';
168 for (cursize = firstsize;
170 cursize = nextsize(cursize)) {
172 for (i = 0; i < cursize; i++) {
173 for (j = 0; j < ndirs; j++) {
174 filename((i + j) % cursize, j, name);
175 close(creat(name, 0666));
178 for (i = 0; i < cursize * stats; i++) {
179 for (j = 0; j < ndirs; j++) {
180 filename((i + j) % cursize, j, name);
184 for (j = 0; j < ndirs; j++) {
185 filename(0, j, name);
186 name[dirchars] = '\0';
187 dirp = opendir(name);
188 while (readdir(dirp))
192 for (i = 0; i < cursize; i++) {
193 for (j = 0; j < ndirs; j++) {
194 filename((i + j) % cursize, j, name);
198 printf("%d %.3f\n", cursize,
199 (now() - stime) * 1.0e3 / (cursize * ndirs));
201 for (j = 0; j < ndirs; j++) {
202 filename(0, j, name);
203 name[dirchars] = '\0';
210 filename(int idx, int dir, char *name)
212 static char hexc[16] = "0123456789abcdef";
215 for (i = dirchars - 1; i >= 0; i--)
216 *name++ = hexc[(dir >> (4 * i)) & 0xf];
218 name += pfxchars; /* skip pfx a's */
219 for (i = minchars - 1; i >= 0; i--)
220 *name++ = hexc[(idx >> (4 * i)) & 0xf];
225 hexchars(uint_t maxval)
229 if (maxval < 16 * 16)
231 if (maxval < 16 * 16 * 16)
233 if (maxval < 16 * 16 * 16 * 16)
235 if (maxval < 16 * 16 * 16 * 16 * 16)
237 if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
239 if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
245 nextsize(uint_t cursize)
254 if (n > (double)lastsize + 0.5)
255 return lastsize + 1; /* i.e. out of bounds */
256 else if ((uint_t)n == cursize)
267 gettimeofday(&tv, NULL);
268 return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
275 "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
276 "[-l last] [-c nchars] [-n ndirs] [-s nstats]\n");