2 * Copyright (c) 2006 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>
32 #include <sys/attributes.h>
34 #include <attr/attributes.h>
37 #define MAXNAMELEN 256
39 typedef unsigned int uint_t;
43 * Loop over directory sizes:
45 * touch n files in each directory
46 * write y bytes to all files in each directory
47 * set DMF attribute on x files in each directory
48 * Change directory sizes by multiplication or addition.
49 * Allow control of starting & stopping sizes, name length, target directory.
50 * Print size and wallclock time (ms per file).
51 * Output can be used to make graphs (gnuplot)
55 static uint_t dirchars;
56 static char *directory;
57 static uint_t firstsize;
58 static uint_t lastsize;
59 static uint_t minchars;
63 static uint_t pfxchars;
68 static int mkfile(char *, char *);
69 static void filename(int, int, char *);
70 static int hexchars(uint_t);
71 static uint_t nextsize(uint_t);
72 static double now(void);
73 static void usage(void);
76 * Maximum size allowed, this is pretty nuts.
77 * The largest one we've ever built has been about 2 million.
79 #define MAX_DIR_SIZE (16 * 1024 * 1024)
80 #define DFL_FIRST_SIZE 1
81 #define DFL_LAST_SIZE (1024 * 1024)
82 #define MAX_DIR_COUNT 1024
83 #define MIN_DIR_COUNT 1
86 #define DMFATTRNAME "SGI_DMI_DMFATTR"
89 main(int argc, char **argv)
95 char name[MAXNAMELEN];
96 char attr[DMFATTRLEN];
99 while ((c = getopt(argc, argv, "a:b:c:d:f:l:m:n:s:")) != -1) {
102 addval = (uint_t)atoi(optarg);
105 bsize = (size_t)atol(optarg);
108 nchars = (uint_t)atoi(optarg);
114 firstsize = (uint_t)atoi(optarg);
117 lastsize = (uint_t)atoi(optarg);
120 mulval = atof(optarg);
123 ndirs = (uint_t)atoi(optarg);
126 fsize = (off64_t)atol(optarg);
134 if (!addval && !mulval)
136 else if ((addval && mulval) || mulval < 0.0) {
142 buffer = memalign(getpagesize(), bsize);
143 memset(buffer, 0xfeed, bsize);
144 memset(attr, 0xaaaaaaa, sizeof(attr));
149 if (mkdir(directory, 0777) < 0 && errno != EEXIST) {
153 if (chdir(directory) < 0) {
159 firstsize = DFL_FIRST_SIZE;
160 else if (firstsize > MAX_DIR_SIZE)
161 firstsize = MAX_DIR_SIZE;
163 lastsize = DFL_LAST_SIZE;
164 else if (lastsize > MAX_DIR_SIZE)
165 lastsize = MAX_DIR_SIZE;
166 if (lastsize < firstsize)
167 lastsize = firstsize;
168 minchars = hexchars(lastsize - 1);
169 if (nchars < minchars)
171 else if (nchars >= MAXNAMELEN)
172 nchars = MAXNAMELEN - 1;
173 if (ndirs > MAX_DIR_COUNT)
174 ndirs = MAX_DIR_COUNT;
175 if (ndirs < MIN_DIR_COUNT)
176 ndirs = MIN_DIR_COUNT;
177 dirchars = hexchars(ndirs);
178 pfxchars = nchars - minchars;
180 memset(&name[dirchars + 1], 'a', pfxchars);
183 for (j = 0; j < ndirs; j++) {
184 filename(0, j, name);
185 name[dirchars] = '\0';
188 for (i = 0; i < cursize; i++) {
189 filename((i + j) % cursize, j, name);
190 close(mkfile(name, attr));
192 printf("%d %.3f\n", cursize,
193 (now() - stime) * 1.0e3 / (cursize * ndirs));
194 cursize = nextsize(cursize);
200 mkfile(char *name, char *attr)
203 ssize_t wrote, wsize;
204 off64_t bytes = fsize;
206 if ((fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_DIRECT)) < 0) {
210 if (attr_setf(fd, DMFATTRNAME, attr, DMFATTRLEN, ATTR_ROOT) < 0) {
215 wsize = (bsize < bytes) ? bsize : bytes;
216 if ((wrote = write(fd, buffer, wsize)) < 0) {
226 filename(int idx, int dir, char *name)
228 static char hexc[16] = "0123456789abcdef";
231 for (i = dirchars - 1; i >= 0; i--)
232 *name++ = hexc[(dir >> (4 * i)) & 0xf];
234 name += pfxchars; /* skip pfx a's */
235 for (i = minchars - 1; i >= 0; i--)
236 *name++ = hexc[(idx >> (4 * i)) & 0xf];
241 hexchars(uint_t maxval)
245 if (maxval < 16 * 16)
247 if (maxval < 16 * 16 * 16)
249 if (maxval < 16 * 16 * 16 * 16)
251 if (maxval < 16 * 16 * 16 * 16 * 16)
253 if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
255 if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
261 nextsize(uint_t cursize)
270 if (n > (double)lastsize + 0.5)
271 return lastsize + 1; /* i.e. out of bounds */
272 else if ((uint_t)n == cursize)
283 gettimeofday(&tv, NULL);
284 return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
291 "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
292 "[-l last] [-c nchars] [-n ndirs] [-s size]\n");